elfxx-ia64.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,106 行 · 第 1/5 页
C
2,106 行
struct elf_link_hash_entry *h; struct bfd_link_info *info;{ if (h == NULL) return false; 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; if (h->dynindx == -1) return false; switch (ELF_ST_VISIBILITY (h->other)) { case STV_INTERNAL: case STV_HIDDEN: return false; } if (h->root.type == bfd_link_hash_undefweak || h->root.type == bfd_link_hash_defweak) return true; if ((info->shared && !info->symbolic) || ((h->elf_link_hash_flags & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)) == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))) return true; return false;}static booleanelfNN_ia64_local_hash_table_init (ht, abfd, new) struct elfNN_ia64_local_hash_table *ht; bfd *abfd ATTRIBUTE_UNUSED; new_hash_entry_func new;{ memset (ht, 0, sizeof (*ht)); return bfd_hash_table_init (&ht->root, new);}static struct bfd_hash_entry*elfNN_ia64_new_loc_hash_entry (entry, table, string) struct bfd_hash_entry *entry; struct bfd_hash_table *table; const char *string;{ struct elfNN_ia64_local_hash_entry *ret; ret = (struct elfNN_ia64_local_hash_entry *) entry; /* Allocate the structure if it has not already been allocated by a subclass. */ if (!ret) ret = bfd_hash_allocate (table, sizeof (*ret)); if (!ret) return 0; /* Initialize our local data. All zeros, and definitely easier than setting a handful of bit fields. */ memset (ret, 0, sizeof (*ret)); /* Call the allocation method of the superclass. */ ret = ((struct elfNN_ia64_local_hash_entry *) bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); return (struct bfd_hash_entry *) ret;}static struct bfd_hash_entry*elfNN_ia64_new_elf_hash_entry (entry, table, string) struct bfd_hash_entry *entry; struct bfd_hash_table *table; const char *string;{ struct elfNN_ia64_link_hash_entry *ret; ret = (struct elfNN_ia64_link_hash_entry *) entry; /* Allocate the structure if it has not already been allocated by a subclass. */ if (!ret) ret = bfd_hash_allocate (table, sizeof (*ret)); if (!ret) return 0; /* Initialize our local data. All zeros, and definitely easier than setting a handful of bit fields. */ memset (ret, 0, sizeof (*ret)); /* Call the allocation method of the superclass. */ ret = ((struct elfNN_ia64_link_hash_entry *) _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); return (struct bfd_hash_entry *) ret;}static voidelfNN_ia64_hash_copy_indirect (xdir, xind) struct elf_link_hash_entry *xdir, *xind;{ struct elfNN_ia64_link_hash_entry *dir, *ind; dir = (struct elfNN_ia64_link_hash_entry *)xdir; ind = (struct elfNN_ia64_link_hash_entry *)xind; /* Copy down any references that we may have already seen to the symbol which just became indirect. */ dir->root.elf_link_hash_flags |= (ind->root.elf_link_hash_flags & (ELF_LINK_HASH_REF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR | ELF_LINK_HASH_REF_REGULAR_NONWEAK)); /* Copy over the got and plt data. This would have been done by check_relocs. */ if (dir->info == NULL) { struct elfNN_ia64_dyn_sym_info *dyn_i; dir->info = dyn_i = ind->info; ind->info = NULL; /* Fix up the dyn_sym_info pointers to the global symbol. */ for (; dyn_i; dyn_i = dyn_i->next) dyn_i->h = &dir->root; } BFD_ASSERT (ind->info == NULL); /* Copy over the dynindx. */ if (dir->root.dynindx == -1) { dir->root.dynindx = ind->root.dynindx; dir->root.dynstr_index = ind->root.dynstr_index; ind->root.dynindx = -1; ind->root.dynstr_index = 0; } BFD_ASSERT (ind->root.dynindx == -1);}static voidelfNN_ia64_hash_hide_symbol (info, xh) struct bfd_link_info *info ATTRIBUTE_UNUSED; struct elf_link_hash_entry *xh;{ struct elfNN_ia64_link_hash_entry *h; struct elfNN_ia64_dyn_sym_info *dyn_i; h = (struct elfNN_ia64_link_hash_entry *)xh; h->root.elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; if ((h->root.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0) h->root.dynindx = -1; for (dyn_i = h->info; dyn_i; dyn_i = dyn_i->next) dyn_i->want_plt2 = 0;}/* Create the derived linker hash table. The IA-64 ELF port uses this derived hash table to keep information specific to the IA-64 ElF linker (without using static variables). */static struct bfd_link_hash_table*elfNN_ia64_hash_table_create (abfd) bfd *abfd;{ struct elfNN_ia64_link_hash_table *ret; ret = bfd_alloc (abfd, sizeof (*ret)); if (!ret) return 0; if (!_bfd_elf_link_hash_table_init (&ret->root, abfd, elfNN_ia64_new_elf_hash_entry)) { bfd_release (abfd, ret); return 0; } if (!elfNN_ia64_local_hash_table_init (&ret->loc_hash_table, abfd, elfNN_ia64_new_loc_hash_entry)) return 0; return &ret->root.root;}/* Look up an entry in a Alpha ELF linker hash table. */static INLINE struct elfNN_ia64_local_hash_entry *elfNN_ia64_local_hash_lookup(table, string, create, copy) struct elfNN_ia64_local_hash_table *table; const char *string; boolean create, copy;{ return ((struct elfNN_ia64_local_hash_entry *) bfd_hash_lookup (&table->root, string, create, copy));}/* Traverse both local and global hash tables. */struct elfNN_ia64_dyn_sym_traverse_data{ boolean (*func) PARAMS ((struct elfNN_ia64_dyn_sym_info *, PTR)); PTR data;};static booleanelfNN_ia64_global_dyn_sym_thunk (xentry, xdata) struct bfd_hash_entry *xentry; PTR xdata;{ struct elfNN_ia64_link_hash_entry *entry = (struct elfNN_ia64_link_hash_entry *) xentry; struct elfNN_ia64_dyn_sym_traverse_data *data = (struct elfNN_ia64_dyn_sym_traverse_data *) xdata; struct elfNN_ia64_dyn_sym_info *dyn_i; for (dyn_i = entry->info; dyn_i; dyn_i = dyn_i->next) if (! (*data->func) (dyn_i, data->data)) return false; return true;}static booleanelfNN_ia64_local_dyn_sym_thunk (xentry, xdata) struct bfd_hash_entry *xentry; PTR xdata;{ struct elfNN_ia64_local_hash_entry *entry = (struct elfNN_ia64_local_hash_entry *) xentry; struct elfNN_ia64_dyn_sym_traverse_data *data = (struct elfNN_ia64_dyn_sym_traverse_data *) xdata; struct elfNN_ia64_dyn_sym_info *dyn_i; for (dyn_i = entry->info; dyn_i; dyn_i = dyn_i->next) if (! (*data->func) (dyn_i, data->data)) return false; return true;}static voidelfNN_ia64_dyn_sym_traverse (ia64_info, func, data) struct elfNN_ia64_link_hash_table *ia64_info; boolean (*func) PARAMS ((struct elfNN_ia64_dyn_sym_info *, PTR)); PTR data;{ struct elfNN_ia64_dyn_sym_traverse_data xdata; xdata.func = func; xdata.data = data; elf_link_hash_traverse (&ia64_info->root, elfNN_ia64_global_dyn_sym_thunk, &xdata); bfd_hash_traverse (&ia64_info->loc_hash_table.root, elfNN_ia64_local_dyn_sym_thunk, &xdata);}static booleanelfNN_ia64_create_dynamic_sections (abfd, info) bfd *abfd; struct bfd_link_info *info;{ struct elfNN_ia64_link_hash_table *ia64_info; asection *s; if (! _bfd_elf_create_dynamic_sections (abfd, info)) return false; ia64_info = elfNN_ia64_hash_table (info); ia64_info->plt_sec = bfd_get_section_by_name (abfd, ".plt"); ia64_info->got_sec = bfd_get_section_by_name (abfd, ".got"); { flagword flags = bfd_get_section_flags (abfd, ia64_info->got_sec); bfd_set_section_flags (abfd, ia64_info->got_sec, SEC_SMALL_DATA | flags); } if (!get_pltoff (abfd, info, ia64_info)) return false; s = bfd_make_section(abfd, ".rela.IA_64.pltoff"); if (s == NULL || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED | SEC_READONLY)) || !bfd_set_section_alignment (abfd, s, 3)) return false; ia64_info->rel_pltoff_sec = s; s = bfd_make_section(abfd, ".rela.got"); if (s == NULL || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED | SEC_READONLY)) || !bfd_set_section_alignment (abfd, s, 3)) return false; ia64_info->rel_got_sec = s; return true;}/* Find and/or create a descriptor for dynamic symbol info. This will vary based on global or local symbol, and the addend to the reloc. */static struct elfNN_ia64_dyn_sym_info *get_dyn_sym_info (ia64_info, h, abfd, rel, create) struct elfNN_ia64_link_hash_table *ia64_info; struct elf_link_hash_entry *h; bfd *abfd; const Elf_Internal_Rela *rel; boolean create;{ struct elfNN_ia64_dyn_sym_info **pp; struct elfNN_ia64_dyn_sym_info *dyn_i; bfd_vma addend = rel ? rel->r_addend : 0; if (h) pp = &((struct elfNN_ia64_link_hash_entry *)h)->info; else { struct elfNN_ia64_local_hash_entry *loc_h; char *addr_name; size_t len; /* Construct a string for use in the elfNN_ia64_local_hash_table. The name describes what was once anonymous memory. */ len = sizeof (void*)*2 + 1 + sizeof (bfd_vma)*4 + 1 + 1; len += 10; /* %p slop */ addr_name = alloca (len); sprintf (addr_name, "%p:%lx", (void *) abfd, ELFNN_R_SYM (rel->r_info)); /* Collect the canonical entry data for this address. */ loc_h = elfNN_ia64_local_hash_lookup (&ia64_info->loc_hash_table, addr_name, create, create); BFD_ASSERT (loc_h); pp = &loc_h->info; } for (dyn_i = *pp; dyn_i && dyn_i->addend != addend; dyn_i = *pp) pp = &dyn_i->next; if (dyn_i == NULL && create) { dyn_i = (struct elfNN_ia64_dyn_sym_info *) bfd_zalloc (abfd, sizeof *dyn_i); *pp = dyn_i; dyn_i->addend = addend; } return dyn_i;}static asection *get_got (abfd, info, ia64_info) bfd *abfd; struct bfd_link_info *info; struct elfNN_ia64_link_hash_table *ia64_info;{ asection *got; bfd *dynobj; got = ia64_info->got_sec; if (!got) { flagword flags; dynobj = ia64_info->root.dynobj; if (!dynobj) ia64_info->root.dynobj = dynobj = abfd; if (!_bfd_elf_create_got_section (dynobj, info)) return 0; got = bfd_get_section_by_name (dynobj, ".got"); BFD_ASSERT (got); ia64_info->got_sec = got; flags = bfd_get_section_flags (abfd, got); bfd_set_section_flags (abfd, got, SEC_SMALL_DATA | flags); } return got;}/* Create function descriptor section (.opd). This section is called .opd because it contains "official prodecure descriptors". The "official" refers to the fact that these descriptors are used when taking the address of a procedure, thus ensuring a unique address for each procedure. */static asection *get_fptr (abfd, info, ia64_info) bfd *abfd; struct bfd_link_info *info ATTRIBUTE_UNUSED; struct elfNN_ia64_link_hash_table *ia64_info;{ asection *fptr; bfd *dynobj; fptr = ia64_info->fptr_sec; if (!fptr) { dynobj = ia64_info->root.dynobj; if (!dynobj) ia64_info->root.dynobj = dynobj = abfd; fptr = bfd_make_section (dynobj, ".opd"); if (!fptr || !bfd_set_section_flags (dynobj, fptr, (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?