elf64-hppa.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,237 行 · 第 1/5 页
C
2,237 行
stub = bfd_make_section (dynobj, ".stub"); if (!stub || !bfd_set_section_flags (dynobj, stub, (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY | SEC_LINKER_CREATED)) || !bfd_set_section_alignment (abfd, stub, 3)) { BFD_ASSERT (0); return false; } hppa_info->stub_sec = stub; } return true;}/* Create sections necessary for dynamic linking. This is only a rough cut and will likely change as we learn more about the somewhat unusual dynamic linking scheme HP uses. .stub: Contains code to implement cross-space calls. The first time one of the stubs is used it will call into the dynamic linker, later calls will go straight to the target. The only stub we support right now looks like ldd OFFSET(%dp),%r1 bve %r0(%r1) ldd OFFSET+8(%dp),%dp Other stubs may be needed in the future. We may want the remove the break/nop instruction. It is only used right now to keep the offset of a .plt entry and a .stub entry in sync. .dlt: This is what most people call the .got. HP used a different name. Losers. .rela.dlt: Relocations for the DLT. .plt: Function pointers as address,gp pairs. .rela.plt: Should contain dynamic IPLT (and EPLT?) relocations. .opd: FPTRS .rela.opd: EPLT relocations for symbols exported from shared libraries. */static booleanelf64_hppa_create_dynamic_sections (abfd, info) bfd *abfd; struct bfd_link_info *info;{ asection *s; if (! get_stub (abfd, info, elf64_hppa_hash_table (info))) return false; if (! get_dlt (abfd, info, elf64_hppa_hash_table (info))) return false; if (! get_plt (abfd, info, elf64_hppa_hash_table (info))) return false; if (! get_opd (abfd, info, elf64_hppa_hash_table (info))) return false; s = bfd_make_section(abfd, ".rela.dlt"); if (s == NULL || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY | SEC_LINKER_CREATED)) || !bfd_set_section_alignment (abfd, s, 3)) return false; elf64_hppa_hash_table (info)->dlt_rel_sec = s; s = bfd_make_section(abfd, ".rela.plt"); if (s == NULL || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY | SEC_LINKER_CREATED)) || !bfd_set_section_alignment (abfd, s, 3)) return false; elf64_hppa_hash_table (info)->plt_rel_sec = s; s = bfd_make_section(abfd, ".rela.data"); if (s == NULL || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY | SEC_LINKER_CREATED)) || !bfd_set_section_alignment (abfd, s, 3)) return false; elf64_hppa_hash_table (info)->other_rel_sec = s; s = bfd_make_section(abfd, ".rela.opd"); if (s == NULL || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY | SEC_LINKER_CREATED)) || !bfd_set_section_alignment (abfd, s, 3)) return false; elf64_hppa_hash_table (info)->opd_rel_sec = s; return true;}/* Allocate dynamic relocations for those symbols that turned out to be dynamic. */static booleanallocate_dynrel_entries (dyn_h, data) struct elf64_hppa_dyn_hash_entry *dyn_h; PTR data;{ struct elf64_hppa_allocate_data *x = (struct elf64_hppa_allocate_data *)data; struct elf64_hppa_link_hash_table *hppa_info; struct elf64_hppa_dyn_reloc_entry *rent; boolean dynamic_symbol, shared; hppa_info = elf64_hppa_hash_table (x->info); dynamic_symbol = elf64_hppa_dynamic_symbol_p (dyn_h->h, x->info); shared = x->info->shared; /* We may need to allocate relocations for a non-dynamic symbol when creating a shared library. */ if (!dynamic_symbol && !shared) return true; /* Take care of the normal data relocations. */ for (rent = dyn_h->reloc_entries; rent; rent = rent->next) { switch (rent->type) { case R_PARISC_FPTR64: /* Allocate one iff we are not building a shared library and !want_opd, which by this point will be true only if we're actually allocating one statically in the main executable. */ if (!x->info->shared && dyn_h->want_opd) continue; break; } hppa_info->other_rel_sec->_raw_size += sizeof (Elf64_External_Rela); /* Make sure this symbol gets into the dynamic symbol table if it is not already recorded. ?!? This should not be in the loop since the symbol need only be added once. */ if (dyn_h->h == 0 || dyn_h->h->dynindx == -1) if (!_bfd_elf64_link_record_local_dynamic_symbol (x->info, rent->sec->owner, dyn_h->sym_indx)) return false; } /* Take care of the GOT and PLT relocations. */ if ((dynamic_symbol || shared) && dyn_h->want_dlt) hppa_info->dlt_rel_sec->_raw_size += sizeof (Elf64_External_Rela); /* If we are building a shared library, then every symbol that has an opd entry will need an EPLT relocation to relocate the symbol's address and __gp value based on the runtime load address. */ if (shared && dyn_h->want_opd) hppa_info->opd_rel_sec->_raw_size += sizeof (Elf64_External_Rela); if (dyn_h->want_plt && dynamic_symbol) { bfd_size_type t = 0; /* Dynamic symbols get one IPLT relocation. Local symbols in shared libraries get two REL relocations. Local symbols in main applications get nothing. */ if (dynamic_symbol) t = sizeof (Elf64_External_Rela); else if (shared) t = 2 * sizeof (Elf64_External_Rela); hppa_info->plt_rel_sec->_raw_size += t; } return true;}/* Adjust a symbol defined by a dynamic object and referenced by a regular object. */static booleanelf64_hppa_adjust_dynamic_symbol (info, h) struct bfd_link_info *info ATTRIBUTE_UNUSED; struct elf_link_hash_entry *h;{ /* ??? Undefined symbols with PLT entries should be re-defined to be the PLT entry. */ /* If this is a weak symbol, and there is a real definition, the processor independent code will have arranged for us to see the real definition first, and we can just use the same value. */ if (h->weakdef != NULL) { BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined || h->weakdef->root.type == bfd_link_hash_defweak); h->root.u.def.section = h->weakdef->root.u.def.section; h->root.u.def.value = h->weakdef->root.u.def.value; return true; } /* If this is a reference to a symbol defined by a dynamic object which is not a function, we might allocate the symbol in our .dynbss section and allocate a COPY dynamic relocation. But PA64 code is canonically PIC, so as a rule we can avoid this sort of hackery. */ return true;}/* Set the final sizes of the dynamic sections and allocate memory for the contents of our special sections. */static booleanelf64_hppa_size_dynamic_sections (output_bfd, info) bfd *output_bfd; struct bfd_link_info *info;{ bfd *dynobj; asection *s; boolean plt; boolean relocs; boolean reltext; struct elf64_hppa_allocate_data data; struct elf64_hppa_link_hash_table *hppa_info; hppa_info = elf64_hppa_hash_table (info); dynobj = elf_hash_table (info)->dynobj; BFD_ASSERT (dynobj != NULL); if (elf_hash_table (info)->dynamic_sections_created) { /* Set the contents of the .interp section to the interpreter. */ if (! info->shared) { s = bfd_get_section_by_name (dynobj, ".interp"); BFD_ASSERT (s != NULL); s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; } } else { /* We may have created entries in the .rela.got section. However, if we are not creating the dynamic sections, we will not actually use these entries. Reset the size of .rela.dlt, which will cause it to get stripped from the output file below. */ s = bfd_get_section_by_name (dynobj, ".rela.dlt"); if (s != NULL) s->_raw_size = 0; } /* Allocate the GOT entries. */ data.info = info; if (elf64_hppa_hash_table (info)->dlt_sec) { data.ofs = 0x0; elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table, allocate_global_data_dlt, &data); hppa_info->dlt_sec->_raw_size = data.ofs; data.ofs = 0x0; elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table, allocate_global_data_plt, &data); hppa_info->plt_sec->_raw_size = data.ofs; data.ofs = 0x0; elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table, allocate_global_data_stub, &data); hppa_info->stub_sec->_raw_size = data.ofs; } /* Mark each function this program exports so that we will allocate space in the .opd section for each function's FPTR. We have to traverse the main linker hash table since we have to find functions which may not have been mentioned in any relocs. */ elf_link_hash_traverse (elf_hash_table (info), elf64_hppa_mark_exported_functions, info); /* Allocate space for entries in the .opd section. */ if (elf64_hppa_hash_table (info)->opd_sec) { data.ofs = 0; elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table, allocate_global_data_opd, &data); hppa_info->opd_sec->_raw_size = data.ofs; } /* Now allocate space for dynamic relocations, if necessary. */ if (hppa_info->root.dynamic_sections_created) elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table, allocate_dynrel_entries, &data); /* The sizes of all the sections are set. Allocate memory for them. */ plt = false; relocs = false; reltext = false; for (s = dynobj->sections; s != NULL; s = s->next) { const char *name; boolean strip; if ((s->flags & SEC_LINKER_CREATED) == 0) continue; /* It's OK to base decisions on the section name, because none of the dynobj section names depend upon the input files. */ name = bfd_get_section_name (dynobj, s); strip = 0; if (strcmp (name, ".plt") == 0) { if (s->_raw_size == 0) { /* Strip this section if we don't need it; see the comment below. */ strip = true; } else { /* Remember whether there is a PLT. */ plt = true; } } else if (strcmp (name, ".dlt") == 0) { if (s->_raw_size == 0) { /* Strip this section if we don't need it; see the comment below. */ strip = true; } } else if (strcmp (name, ".opd") == 0) { if (s->_raw_size == 0) { /* Strip this section if we don't need it; see the comment below. */ strip = true; } } else if (strncmp (name, ".rela", 4) == 0) { if (s->_raw_size == 0) { /* If we don't need this section, strip it from the output file. This is mostly to handle .rela.bss and .rela.plt. We must create both sections in create_dynamic_sections, because they must be created before the linker maps input sections to output sections. The linker does that before adjust_dynamic_symbol is called, and it is that function which decides whether anything needs to go into these sections. */ strip = true; } else { asection *target; /* Remember whether there are any reloc sections other than .rela.plt. */ if (strcmp (name, ".rela.plt") != 0) { const char *outname; relocs = true; /* If this relocation section applies to a read only section, then we probably need a DT_TEXTREL entry. The entries in the .rela.plt section really apply to the .got section, which we created ourselves and so know is not readonly. */ outname = bfd_get_section_name (output_bfd, s->output_section); target = bfd_get_section_by_name (output_bfd, outname + 4); if (target != NULL && (target->flags & SEC_READONLY) != 0 && (target->flags & SEC_ALLOC) != 0) reltext = true; } /* We use the reloc_count field as a counter if we need to copy relocs into the output file. */ s->reloc_count = 0; } } else if (strncmp (name, ".dlt", 4) != 0 && strcmp (name, ".stub") != 0 && strcmp (name, ".got") != 0) { /* It's not one of our sections, so don't allocate space. */ continue; } if (strip) { _bfd_strip_section_from_output (info, s); continue; } /* Allocate memory for the section contents if it has not been allocated already. We use bfd_zalloc here in case unused entries are not reclaimed before the section's contents are written out. This should not happen, but this way if it does, we get a R_PARISC_NONE reloc instead of garbage. */ if (s->contents == NULL) { s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); if (s->contents == NULL && s->_raw_size != 0) return false; } } if (elf_hash_table (info)->dynamic_sections_created) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?