elfxx-ia64.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,106 行 · 第 1/5 页
C
2,106 行
| SEC_READONLY | SEC_LINKER_CREATED)) || !bfd_set_section_alignment (abfd, fptr, 4)) { BFD_ASSERT (0); return NULL; } ia64_info->fptr_sec = fptr; } return fptr;}static asection *get_pltoff (abfd, info, ia64_info) bfd *abfd; struct bfd_link_info *info ATTRIBUTE_UNUSED; struct elfNN_ia64_link_hash_table *ia64_info;{ asection *pltoff; bfd *dynobj; pltoff = ia64_info->pltoff_sec; if (!pltoff) { dynobj = ia64_info->root.dynobj; if (!dynobj) ia64_info->root.dynobj = dynobj = abfd; pltoff = bfd_make_section (dynobj, ELF_STRING_ia64_pltoff); if (!pltoff || !bfd_set_section_flags (dynobj, pltoff, (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_SMALL_DATA | SEC_LINKER_CREATED)) || !bfd_set_section_alignment (abfd, pltoff, 4)) { BFD_ASSERT (0); return NULL; } ia64_info->pltoff_sec = pltoff; } return pltoff;}static asection *get_reloc_section (abfd, ia64_info, sec, create) bfd *abfd; struct elfNN_ia64_link_hash_table *ia64_info; asection *sec; boolean create;{ const char *srel_name; asection *srel; bfd *dynobj; srel_name = (bfd_elf_string_from_elf_section (abfd, elf_elfheader(abfd)->e_shstrndx, elf_section_data(sec)->rel_hdr.sh_name)); if (srel_name == NULL) return NULL; BFD_ASSERT ((strncmp (srel_name, ".rela", 5) == 0 && strcmp (bfd_get_section_name (abfd, sec), srel_name+5) == 0) || (strncmp (srel_name, ".rel", 4) == 0 && strcmp (bfd_get_section_name (abfd, sec), srel_name+4) == 0)); dynobj = ia64_info->root.dynobj; if (!dynobj) ia64_info->root.dynobj = dynobj = abfd; srel = bfd_get_section_by_name (dynobj, srel_name); if (srel == NULL && create) { srel = bfd_make_section (dynobj, srel_name); if (srel == NULL || !bfd_set_section_flags (dynobj, srel, (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED | SEC_READONLY)) || !bfd_set_section_alignment (dynobj, srel, 3)) return NULL; } return srel;}static booleancount_dyn_reloc (abfd, dyn_i, srel, type) bfd *abfd; struct elfNN_ia64_dyn_sym_info *dyn_i; asection *srel; int type;{ struct elfNN_ia64_dyn_reloc_entry *rent; for (rent = dyn_i->reloc_entries; rent; rent = rent->next) if (rent->srel == srel && rent->type == type) break; if (!rent) { rent = (struct elfNN_ia64_dyn_reloc_entry *) bfd_alloc (abfd, sizeof (*rent)); if (!rent) return false; rent->next = dyn_i->reloc_entries; rent->srel = srel; rent->type = type; rent->count = 0; dyn_i->reloc_entries = rent; } rent->count++; return true;}static booleanelfNN_ia64_check_relocs (abfd, info, sec, relocs) bfd *abfd; struct bfd_link_info *info; asection *sec; const Elf_Internal_Rela *relocs;{ struct elfNN_ia64_link_hash_table *ia64_info; const Elf_Internal_Rela *relend; Elf_Internal_Shdr *symtab_hdr; const Elf_Internal_Rela *rel; asection *got, *fptr, *srel; if (info->relocateable) return true; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; ia64_info = elfNN_ia64_hash_table (info); got = fptr = srel = NULL; relend = relocs + sec->reloc_count; for (rel = relocs; rel < relend; ++rel) { enum { NEED_GOT = 1, NEED_FPTR = 2, NEED_PLTOFF = 4, NEED_MIN_PLT = 8, NEED_FULL_PLT = 16, NEED_DYNREL = 32, NEED_LTOFF_FPTR = 64, }; struct elf_link_hash_entry *h = NULL; unsigned long r_symndx = ELFNN_R_SYM (rel->r_info); struct elfNN_ia64_dyn_sym_info *dyn_i; int need_entry; boolean maybe_dynamic; int dynrel_type = R_IA64_NONE; if (r_symndx >= symtab_hdr->sh_info) { /* We're dealing with a global symbol -- find its hash entry and mark it as being referenced. */ long indx = r_symndx - symtab_hdr->sh_info; h = elf_sym_hashes (abfd)[indx]; while (h->root.type == bfd_link_hash_indirect || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; h->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR; } /* We can only get preliminary data on whether a symbol is locally or externally defined, as not all of the input files have yet been processed. Do something with what we know, as this may help reduce memory usage and processing time later. */ maybe_dynamic = false; if (h && ((info->shared && ! info->symbolic) || ! (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) || h->root.type == bfd_link_hash_defweak)) maybe_dynamic = true; need_entry = 0; switch (ELFNN_R_TYPE (rel->r_info)) { case R_IA64_TPREL22: case R_IA64_TPREL64MSB: case R_IA64_TPREL64LSB: case R_IA64_LTOFF_TP22: return false; case R_IA64_LTOFF_FPTR22: case R_IA64_LTOFF_FPTR64I: case R_IA64_LTOFF_FPTR64MSB: case R_IA64_LTOFF_FPTR64LSB: need_entry = NEED_FPTR | NEED_GOT | NEED_LTOFF_FPTR; break; case R_IA64_FPTR64I: case R_IA64_FPTR32MSB: case R_IA64_FPTR32LSB: case R_IA64_FPTR64MSB: case R_IA64_FPTR64LSB: if (info->shared || h) need_entry = NEED_FPTR | NEED_DYNREL; else need_entry = NEED_FPTR; dynrel_type = R_IA64_FPTR64LSB; break; case R_IA64_LTOFF22: case R_IA64_LTOFF22X: case R_IA64_LTOFF64I: need_entry = NEED_GOT; break; case R_IA64_PLTOFF22: case R_IA64_PLTOFF64I: case R_IA64_PLTOFF64MSB: case R_IA64_PLTOFF64LSB: need_entry = NEED_PLTOFF; if (h) { if (maybe_dynamic) need_entry |= NEED_MIN_PLT; } else { (*info->callbacks->warning) (info, _("@pltoff reloc against local symbol"), 0, abfd, 0, 0); } break; case R_IA64_PCREL21B: case R_IA64_PCREL60B: /* Depending on where this symbol is defined, we may or may not need a full plt entry. Only skip if we know we'll not need the entry -- static or symbolic, and the symbol definition has already been seen. */ if (maybe_dynamic && rel->r_addend == 0) need_entry = NEED_FULL_PLT; break; case R_IA64_IMM14: case R_IA64_IMM22: case R_IA64_IMM64: case R_IA64_DIR32MSB: case R_IA64_DIR32LSB: case R_IA64_DIR64MSB: case R_IA64_DIR64LSB: /* Shared objects will always need at least a REL relocation. */ if (info->shared || maybe_dynamic) need_entry = NEED_DYNREL; dynrel_type = R_IA64_DIR64LSB; break; case R_IA64_IPLTMSB: case R_IA64_IPLTLSB: /* Shared objects will always need at least a REL relocation. */ if (info->shared || maybe_dynamic) need_entry = NEED_DYNREL; dynrel_type = R_IA64_IPLTLSB; break; case R_IA64_PCREL22: case R_IA64_PCREL64I: case R_IA64_PCREL32MSB: case R_IA64_PCREL32LSB: case R_IA64_PCREL64MSB: case R_IA64_PCREL64LSB: if (maybe_dynamic) need_entry = NEED_DYNREL; dynrel_type = R_IA64_PCREL64LSB; break; } if (!need_entry) continue; if ((need_entry & NEED_FPTR) != 0 && rel->r_addend) { (*info->callbacks->warning) (info, _("non-zero addend in @fptr reloc"), 0, abfd, 0, 0); } dyn_i = get_dyn_sym_info (ia64_info, h, abfd, rel, true); /* Record whether or not this is a local symbol. */ dyn_i->h = h; /* Create what's needed. */ if (need_entry & NEED_GOT) { if (!got) { got = get_got (abfd, info, ia64_info); if (!got) return false; } dyn_i->want_got = 1; } if (need_entry & NEED_FPTR) { if (!fptr) { fptr = get_fptr (abfd, info, ia64_info); if (!fptr) return false; } /* FPTRs for shared libraries are allocated by the dynamic linker. Make sure this local symbol will appear in the dynamic symbol table. */ if (!h && info->shared) { if (! (_bfd_elfNN_link_record_local_dynamic_symbol (info, abfd, r_symndx))) return false; } dyn_i->want_fptr = 1; } if (need_entry & NEED_LTOFF_FPTR) dyn_i->want_ltoff_fptr = 1; if (need_entry & (NEED_MIN_PLT | NEED_FULL_PLT)) { if (!ia64_info->root.dynobj) ia64_info->root.dynobj = abfd; h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; dyn_i->want_plt = 1; } if (need_entry & NEED_FULL_PLT) dyn_i->want_plt2 = 1; if (need_entry & NEED_PLTOFF) dyn_i->want_pltoff = 1; if ((need_entry & NEED_DYNREL) && (sec->flags & SEC_ALLOC)) { if (!srel) { srel = get_reloc_section (abfd, ia64_info, sec, true); if (!srel) return false; } if (!count_dyn_reloc (abfd, dyn_i, srel, dynrel_type)) return false; } } return true;}struct elfNN_ia64_allocate_data{ struct bfd_link_info *info; bfd_size_type ofs;};/* For cleanliness, and potentially faster dynamic loading, allocate external GOT entries first. */static booleanallocate_global_data_got (dyn_i, data) struct elfNN_ia64_dyn_sym_info *dyn_i; PTR data;{ struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data; if (dyn_i->want_got && ! dyn_i->want_fptr && elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info)) { dyn_i->got_offset = x->ofs; x->ofs += 8; } return true;}/* Next, allocate all the GOT entries used by LTOFF_FPTR relocs. */static booleanallocate_global_fptr_got (dyn_i, data) struct elfNN_ia64_dyn_sym_info *dyn_i; PTR data;{ struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data; if (dyn_i->want_got && dyn_i->want_fptr && elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info)) { dyn_i->got_offset = x->ofs; x->ofs += 8; } return true;}/* Lastly, allocate all the GOT entries for local data. */static booleanallocate_local_got (dyn_i, data) struct elfNN_ia64_dyn_sym_info *dyn_i; PTR data;{ struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)d
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?