xcofflink.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,198 行 · 第 1/5 页
C
2,198 行
static struct bfd_hash_entry *xcoff_link_hash_newfunc (entry, table, string) struct bfd_hash_entry *entry; struct bfd_hash_table *table; const char *string;{ struct xcoff_link_hash_entry *ret = (struct xcoff_link_hash_entry *) entry; /* Allocate the structure if it has not already been allocated by a subclass. */ if (ret == (struct xcoff_link_hash_entry *) NULL) ret = ((struct xcoff_link_hash_entry *) bfd_hash_allocate (table, sizeof (struct xcoff_link_hash_entry))); if (ret == (struct xcoff_link_hash_entry *) NULL) return (struct bfd_hash_entry *) ret; /* Call the allocation method of the superclass. */ ret = ((struct xcoff_link_hash_entry *) _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); if (ret != NULL) { /* Set local fields. */ ret->indx = -1; ret->toc_section = NULL; ret->u.toc_indx = -1; ret->descriptor = NULL; ret->ldsym = NULL; ret->ldindx = -1; ret->flags = 0; ret->smclas = XMC_UA; } return (struct bfd_hash_entry *) ret;}/* Create a XCOFF link hash table. */struct bfd_link_hash_table *_bfd_xcoff_bfd_link_hash_table_create (abfd) bfd *abfd;{ struct xcoff_link_hash_table *ret; ret = ((struct xcoff_link_hash_table *) bfd_alloc (abfd, sizeof (struct xcoff_link_hash_table))); if (ret == (struct xcoff_link_hash_table *) NULL) return (struct bfd_link_hash_table *) NULL; if (! _bfd_link_hash_table_init (&ret->root, abfd, xcoff_link_hash_newfunc)) { bfd_release (abfd, ret); return (struct bfd_link_hash_table *) NULL; } ret->debug_strtab = _bfd_xcoff_stringtab_init (); ret->debug_section = NULL; ret->loader_section = NULL; ret->ldrel_count = 0; memset (&ret->ldhdr, 0, sizeof (struct internal_ldhdr)); ret->linkage_section = NULL; ret->toc_section = NULL; ret->descriptor_section = NULL; ret->imports = NULL; ret->file_align = 0; ret->textro = false; ret->gc = false; memset (ret->special_sections, 0, sizeof ret->special_sections); /* The linker will always generate a full a.out header. We need to record that fact now, before the sizeof_headers routine could be called. */ xcoff_data (abfd)->full_aouthdr = true; return &ret->root;}/* Look up an entry in an XCOFF link hash table. */#define xcoff_link_hash_lookup(table, string, create, copy, follow) \ ((struct xcoff_link_hash_entry *) \ bfd_link_hash_lookup (&(table)->root, (string), (create), (copy),\ (follow)))/* Traverse an XCOFF link hash table. */#define xcoff_link_hash_traverse(table, func, info) \ (bfd_link_hash_traverse \ (&(table)->root, \ (boolean (*) PARAMS ((struct bfd_link_hash_entry *, PTR))) (func), \ (info)))/* Get the XCOFF link hash table from the info structure. This is just a cast. */#define xcoff_hash_table(p) ((struct xcoff_link_hash_table *) ((p)->hash))/* Read internal relocs for an XCOFF csect. This is a wrapper around _bfd_coff_read_internal_relocs which tries to take advantage of any relocs which may have been cached for the enclosing section. */static struct internal_reloc *xcoff_read_internal_relocs (abfd, sec, cache, external_relocs, require_internal, internal_relocs) bfd *abfd; asection *sec; boolean cache; bfd_byte *external_relocs; boolean require_internal; struct internal_reloc *internal_relocs;{ if (coff_section_data (abfd, sec) != NULL && coff_section_data (abfd, sec)->relocs == NULL && xcoff_section_data (abfd, sec) != NULL) { asection *enclosing; enclosing = xcoff_section_data (abfd, sec)->enclosing; if (enclosing != NULL && (coff_section_data (abfd, enclosing) == NULL || coff_section_data (abfd, enclosing)->relocs == NULL) && cache && enclosing->reloc_count > 0) { if (_bfd_coff_read_internal_relocs (abfd, enclosing, true, external_relocs, false, (struct internal_reloc *) NULL) == NULL) return NULL; } if (enclosing != NULL && coff_section_data (abfd, enclosing) != NULL && coff_section_data (abfd, enclosing)->relocs != NULL) { size_t off; off = ((sec->rel_filepos - enclosing->rel_filepos) / bfd_coff_relsz (abfd)); if (! require_internal) return coff_section_data (abfd, enclosing)->relocs + off; memcpy (internal_relocs, coff_section_data (abfd, enclosing)->relocs + off, sec->reloc_count * sizeof (struct internal_reloc)); return internal_relocs; } } return _bfd_coff_read_internal_relocs (abfd, sec, cache, external_relocs, require_internal, internal_relocs);}/* Given an XCOFF BFD, add symbols to the global hash table as appropriate. */boolean_bfd_xcoff_bfd_link_add_symbols (abfd, info) bfd *abfd; struct bfd_link_info *info;{ switch (bfd_get_format (abfd)) { case bfd_object: return xcoff_link_add_object_symbols (abfd, info); case bfd_archive: /* If the archive has a map, do the usual search. We then need to check the archive for stripped dynamic objects, because they will not appear in the archive map even though they should, perhaps, be included. If the archive has no map, we just consider each object file in turn, since that apparently is what the AIX native linker does. */ if (bfd_has_map (abfd)) { if (! (_bfd_generic_link_add_archive_symbols (abfd, info, xcoff_link_check_archive_element))) return false; } { bfd *member; member = bfd_openr_next_archived_file (abfd, (bfd *) NULL); while (member != NULL) { if (bfd_check_format (member, bfd_object) && (! bfd_has_map (abfd) || ((member->flags & DYNAMIC) != 0 && (member->flags & HAS_SYMS) == 0))) { boolean needed; if (! xcoff_link_check_archive_element (member, info, &needed)) return false; if (needed) member->archive_pass = -1; } member = bfd_openr_next_archived_file (abfd, member); } } return true; default: bfd_set_error (bfd_error_wrong_format); return false; }}/* Add symbols from an XCOFF object file. */static booleanxcoff_link_add_object_symbols (abfd, info) bfd *abfd; struct bfd_link_info *info;{ if (! _bfd_coff_get_external_symbols (abfd)) return false; if (! xcoff_link_add_symbols (abfd, info)) return false; if (! info->keep_memory) { if (! _bfd_coff_free_symbols (abfd)) return false; } return true;}/* Check a single archive element to see if we need to include it in the link. *PNEEDED is set according to whether this element is needed in the link or not. This is called via _bfd_generic_link_add_archive_symbols. */static booleanxcoff_link_check_archive_element (abfd, info, pneeded) bfd *abfd; struct bfd_link_info *info; boolean *pneeded;{ if (! _bfd_coff_get_external_symbols (abfd)) return false; if (! xcoff_link_check_ar_symbols (abfd, info, pneeded)) return false; if (*pneeded) { if (! xcoff_link_add_symbols (abfd, info)) return false; } if (! info->keep_memory || ! *pneeded) { if (! _bfd_coff_free_symbols (abfd)) return false; } return true;}/* Look through the symbols to see if this object file should be included in the link. */static booleanxcoff_link_check_ar_symbols (abfd, info, pneeded) bfd *abfd; struct bfd_link_info *info; boolean *pneeded;{ bfd_size_type symesz; bfd_byte *esym; bfd_byte *esym_end; *pneeded = false; if ((abfd->flags & DYNAMIC) != 0 && ! info->static_link && info->hash->creator == abfd->xvec) return xcoff_link_check_dynamic_ar_symbols (abfd, info, pneeded); symesz = bfd_coff_symesz (abfd); esym = (bfd_byte *) obj_coff_external_syms (abfd); esym_end = esym + obj_raw_syment_count (abfd) * symesz; while (esym < esym_end) { struct internal_syment sym; bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym); if (sym.n_sclass == C_EXT && sym.n_scnum != N_UNDEF) { const char *name; char buf[SYMNMLEN + 1]; struct bfd_link_hash_entry *h; /* This symbol is externally visible, and is defined by this object file. */ name = _bfd_coff_internal_syment_name (abfd, &sym, buf); if (name == NULL) return false; h = bfd_link_hash_lookup (info->hash, name, false, false, true); /* We are only interested in symbols that are currently undefined. If a symbol is currently known to be common, XCOFF linkers do not bring in an object file which defines it. We also don't bring in symbols to satisfy undefined references in shared objects. */ if (h != (struct bfd_link_hash_entry *) NULL && h->type == bfd_link_hash_undefined && (info->hash->creator != abfd->xvec || (((struct xcoff_link_hash_entry *) h)->flags & XCOFF_DEF_DYNAMIC) == 0)) { if (! (*info->callbacks->add_archive_element) (info, abfd, name)) return false; *pneeded = true; return true; } } esym += (sym.n_numaux + 1) * symesz; } /* We do not need this object file. */ return true;}/* Look through the loader symbols to see if this dynamic object should be included in the link. The native linker uses the loader symbols, not the normal symbol table, so we do too. */static booleanxcoff_link_check_dynamic_ar_symbols (abfd, info, pneeded) bfd *abfd; struct bfd_link_info *info; boolean *pneeded;{ asection *lsec; bfd_byte *buf; struct internal_ldhdr ldhdr; const char *strings; struct external_ldsym *elsym, *elsymend; *pneeded = false; lsec = bfd_get_section_by_name (abfd, ".loader"); if (lsec == NULL) { /* There are no symbols, so don't try to include it. */ return true; } if (! xcoff_get_section_contents (abfd, lsec)) return false; buf = coff_section_data (abfd, lsec)->contents; xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) buf, &ldhdr); strings = (char *) buf + ldhdr.l_stoff; elsym = (struct external_ldsym *) (buf + LDHDRSZ); elsymend = elsym + ldhdr.l_nsyms; for (; elsym < elsymend; elsym++) { struct internal_ldsym ldsym; char nambuf[SYMNMLEN + 1]; const char *name; struct bfd_link_hash_entry *h; xcoff_swap_ldsym_in (abfd, elsym, &ldsym); /* We are only interested in exported symbols. */ if ((ldsym.l_smtype & L_EXPORT) == 0) continue; if (ldsym._l._l_l._l_zeroes == 0) name = strings + ldsym._l._l_l._l_offset; else { memcpy (nambuf, ldsym._l._l_name, SYMNMLEN); nambuf[SYMNMLEN] = '\0'; name = nambuf; } h = bfd_link_hash_lookup (info->hash, name, false, false, true); /* We are only interested in symbols that are currently undefined. At this point we know that we are using an XCOFF hash table. */ if (h != NULL && h->type == bfd_link_hash_undefined && (((struct xcoff_link_hash_entry *) h)->flags & XCOFF_DEF_DYNAMIC) == 0) { if (! (*info->callbacks->add_archive_element) (info, abfd, name)) return false; *pneeded = true; return true; } } /* We do not need this shared object. */ if (buf != NULL && ! coff_section_data (abfd, lsec)->keep_contents) { free (coff_section_data (abfd, lsec)->contents); coff_section_data (abfd, lsec)->contents = NULL; } return true;}/* Returns the index of reloc in RELOCS with the least address greater than or equal to ADDRESS. The relocs are sorted by address. */static bfd_size_typexcoff_find_reloc (relocs, count, address) struct internal_reloc *relocs; bfd_size_type count; bfd_vma address;{ bfd_size_type min, max, this; if (count < 2) { if (count == 1 && relocs[0].r_vaddr < address) return 1; else return 0; } min = 0; max = count; /* Do a binary search over (min,max]. */ while (min + 1 < max) { bfd_vma raddr;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?