xcofflink.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,198 行 · 第 1/5 页
C
2,198 行
static boolean xcoff_mark PARAMS ((struct bfd_link_info *, asection *));static void xcoff_sweep PARAMS ((struct bfd_link_info *));static boolean xcoff_build_ldsyms PARAMS ((struct xcoff_link_hash_entry *, PTR));static boolean xcoff_link_input_bfd PARAMS ((struct xcoff_final_link_info *, bfd *));static boolean xcoff_write_global_symbol PARAMS ((struct xcoff_link_hash_entry *, PTR));static boolean xcoff_reloc_link_order PARAMS ((bfd *, struct xcoff_final_link_info *, asection *, struct bfd_link_order *));static int xcoff_sort_relocs PARAMS ((const PTR, const PTR));/* Routines to swap information in the XCOFF .loader section. If we ever need to write an XCOFF loader, this stuff will need to be moved to another file shared by the linker (which XCOFF calls the ``binder'') and the loader. *//* Swap in the ldhdr structure. */static voidxcoff_swap_ldhdr_in (abfd, src, dst) bfd *abfd; const struct external_ldhdr *src; struct internal_ldhdr *dst;{ dst->l_version = bfd_get_32 (abfd, src->l_version); dst->l_nsyms = bfd_get_32 (abfd, src->l_nsyms); dst->l_nreloc = bfd_get_32 (abfd, src->l_nreloc); dst->l_istlen = bfd_get_32 (abfd, src->l_istlen); dst->l_nimpid = bfd_get_32 (abfd, src->l_nimpid); dst->l_impoff = bfd_get_32 (abfd, src->l_impoff); dst->l_stlen = bfd_get_32 (abfd, src->l_stlen); dst->l_stoff = bfd_get_32 (abfd, src->l_stoff);}/* Swap out the ldhdr structure. */static voidxcoff_swap_ldhdr_out (abfd, src, dst) bfd *abfd; const struct internal_ldhdr *src; struct external_ldhdr *dst;{ bfd_put_32 (abfd, src->l_version, dst->l_version); bfd_put_32 (abfd, src->l_nsyms, dst->l_nsyms); bfd_put_32 (abfd, src->l_nreloc, dst->l_nreloc); bfd_put_32 (abfd, src->l_istlen, dst->l_istlen); bfd_put_32 (abfd, src->l_nimpid, dst->l_nimpid); bfd_put_32 (abfd, src->l_impoff, dst->l_impoff); bfd_put_32 (abfd, src->l_stlen, dst->l_stlen); bfd_put_32 (abfd, src->l_stoff, dst->l_stoff);}/* Swap in the ldsym structure. */static voidxcoff_swap_ldsym_in (abfd, src, dst) bfd *abfd; const struct external_ldsym *src; struct internal_ldsym *dst;{ if (bfd_get_32 (abfd, src->_l._l_l._l_zeroes) != 0) memcpy (dst->_l._l_name, src->_l._l_name, SYMNMLEN); else { dst->_l._l_l._l_zeroes = 0; dst->_l._l_l._l_offset = bfd_get_32 (abfd, src->_l._l_l._l_offset); } dst->l_value = bfd_get_32 (abfd, src->l_value); dst->l_scnum = bfd_get_16 (abfd, src->l_scnum); dst->l_smtype = bfd_get_8 (abfd, src->l_smtype); dst->l_smclas = bfd_get_8 (abfd, src->l_smclas); dst->l_ifile = bfd_get_32 (abfd, src->l_ifile); dst->l_parm = bfd_get_32 (abfd, src->l_parm);}/* Swap out the ldsym structure. */static voidxcoff_swap_ldsym_out (abfd, src, dst) bfd *abfd; const struct internal_ldsym *src; struct external_ldsym *dst;{ if (src->_l._l_l._l_zeroes != 0) memcpy (dst->_l._l_name, src->_l._l_name, SYMNMLEN); else { bfd_put_32 (abfd, 0, dst->_l._l_l._l_zeroes); bfd_put_32 (abfd, src->_l._l_l._l_offset, dst->_l._l_l._l_offset); } bfd_put_32 (abfd, src->l_value, dst->l_value); bfd_put_16 (abfd, src->l_scnum, dst->l_scnum); bfd_put_8 (abfd, src->l_smtype, dst->l_smtype); bfd_put_8 (abfd, src->l_smclas, dst->l_smclas); bfd_put_32 (abfd, src->l_ifile, dst->l_ifile); bfd_put_32 (abfd, src->l_parm, dst->l_parm);}/* Swap in the ldrel structure. */static voidxcoff_swap_ldrel_in (abfd, src, dst) bfd *abfd; const struct external_ldrel *src; struct internal_ldrel *dst;{ dst->l_vaddr = bfd_get_32 (abfd, src->l_vaddr); dst->l_symndx = bfd_get_32 (abfd, src->l_symndx); dst->l_rtype = bfd_get_16 (abfd, src->l_rtype); dst->l_rsecnm = bfd_get_16 (abfd, src->l_rsecnm);}/* Swap out the ldrel structure. */static voidxcoff_swap_ldrel_out (abfd, src, dst) bfd *abfd; const struct internal_ldrel *src; struct external_ldrel *dst;{ bfd_put_32 (abfd, src->l_vaddr, dst->l_vaddr); bfd_put_32 (abfd, src->l_symndx, dst->l_symndx); bfd_put_16 (abfd, src->l_rtype, dst->l_rtype); bfd_put_16 (abfd, src->l_rsecnm, dst->l_rsecnm);}/* Routines to read XCOFF dynamic information. This don't really belong here, but we already have the ldsym manipulation routines here. *//* Read the contents of a section. */static booleanxcoff_get_section_contents (abfd, sec) bfd *abfd; asection *sec;{ if (coff_section_data (abfd, sec) == NULL) { sec->used_by_bfd = bfd_zalloc (abfd, sizeof (struct coff_section_tdata)); if (sec->used_by_bfd == NULL) return false; } if (coff_section_data (abfd, sec)->contents == NULL) { coff_section_data (abfd, sec)->contents = (bfd_byte *) bfd_malloc (sec->_raw_size); if (coff_section_data (abfd, sec)->contents == NULL) return false; if (! bfd_get_section_contents (abfd, sec, coff_section_data (abfd, sec)->contents, (file_ptr) 0, sec->_raw_size)) return false; } return true;}/* Get the size required to hold the dynamic symbols. */long_bfd_xcoff_get_dynamic_symtab_upper_bound (abfd) bfd *abfd;{ asection *lsec; bfd_byte *contents; struct internal_ldhdr ldhdr; if ((abfd->flags & DYNAMIC) == 0) { bfd_set_error (bfd_error_invalid_operation); return -1; } lsec = bfd_get_section_by_name (abfd, ".loader"); if (lsec == NULL) { bfd_set_error (bfd_error_no_symbols); return -1; } if (! xcoff_get_section_contents (abfd, lsec)) return -1; contents = coff_section_data (abfd, lsec)->contents; xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr); return (ldhdr.l_nsyms + 1) * sizeof (asymbol *);}/* Get the dynamic symbols. */long_bfd_xcoff_canonicalize_dynamic_symtab (abfd, psyms) bfd *abfd; asymbol **psyms;{ asection *lsec; bfd_byte *contents; struct internal_ldhdr ldhdr; const char *strings; struct external_ldsym *elsym, *elsymend; coff_symbol_type *symbuf; if ((abfd->flags & DYNAMIC) == 0) { bfd_set_error (bfd_error_invalid_operation); return -1; } lsec = bfd_get_section_by_name (abfd, ".loader"); if (lsec == NULL) { bfd_set_error (bfd_error_no_symbols); return -1; } if (! xcoff_get_section_contents (abfd, lsec)) return -1; contents = coff_section_data (abfd, lsec)->contents; coff_section_data (abfd, lsec)->keep_contents = true; xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr); strings = (char *) contents + ldhdr.l_stoff; symbuf = ((coff_symbol_type *) bfd_zalloc (abfd, ldhdr.l_nsyms * sizeof (coff_symbol_type))); if (symbuf == NULL) return -1; elsym = (struct external_ldsym *) (contents + LDHDRSZ); elsymend = elsym + ldhdr.l_nsyms; for (; elsym < elsymend; elsym++, symbuf++, psyms++) { struct internal_ldsym ldsym; xcoff_swap_ldsym_in (abfd, elsym, &ldsym); symbuf->symbol.the_bfd = abfd; if (ldsym._l._l_l._l_zeroes == 0) symbuf->symbol.name = strings + ldsym._l._l_l._l_offset; else { int i; for (i = 0; i < SYMNMLEN; i++) if (ldsym._l._l_name[i] == '\0') break; if (i < SYMNMLEN) symbuf->symbol.name = (char *) elsym->_l._l_name; else { char *c; c = bfd_alloc (abfd, SYMNMLEN + 1); if (c == NULL) return -1; memcpy (c, ldsym._l._l_name, SYMNMLEN); c[SYMNMLEN] = '\0'; symbuf->symbol.name = c; } } if (ldsym.l_smclas == XMC_XO) symbuf->symbol.section = bfd_abs_section_ptr; else symbuf->symbol.section = coff_section_from_bfd_index (abfd, ldsym.l_scnum); symbuf->symbol.value = ldsym.l_value - symbuf->symbol.section->vma; symbuf->symbol.flags = BSF_NO_FLAGS; if ((ldsym.l_smtype & L_EXPORT) != 0) symbuf->symbol.flags |= BSF_GLOBAL; /* FIXME: We have no way to record the other information stored with the loader symbol. */ *psyms = (asymbol *) symbuf; } *psyms = NULL; return ldhdr.l_nsyms;}/* Get the size required to hold the dynamic relocs. */long_bfd_xcoff_get_dynamic_reloc_upper_bound (abfd) bfd *abfd;{ asection *lsec; bfd_byte *contents; struct internal_ldhdr ldhdr; if ((abfd->flags & DYNAMIC) == 0) { bfd_set_error (bfd_error_invalid_operation); return -1; } lsec = bfd_get_section_by_name (abfd, ".loader"); if (lsec == NULL) { bfd_set_error (bfd_error_no_symbols); return -1; } if (! xcoff_get_section_contents (abfd, lsec)) return -1; contents = coff_section_data (abfd, lsec)->contents; xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr); return (ldhdr.l_nreloc + 1) * sizeof (arelent *);}/* The typical dynamic reloc. */static reloc_howto_type xcoff_dynamic_reloc = HOWTO (0, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ 0, /* special_function */ "R_POS", /* name */ true, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ false); /* pcrel_offset *//* Get the dynamic relocs. */long_bfd_xcoff_canonicalize_dynamic_reloc (abfd, prelocs, syms) bfd *abfd; arelent **prelocs; asymbol **syms;{ asection *lsec; bfd_byte *contents; struct internal_ldhdr ldhdr; arelent *relbuf; struct external_ldrel *elrel, *elrelend; if ((abfd->flags & DYNAMIC) == 0) { bfd_set_error (bfd_error_invalid_operation); return -1; } lsec = bfd_get_section_by_name (abfd, ".loader"); if (lsec == NULL) { bfd_set_error (bfd_error_no_symbols); return -1; } if (! xcoff_get_section_contents (abfd, lsec)) return -1; contents = coff_section_data (abfd, lsec)->contents; xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr); relbuf = (arelent *) bfd_alloc (abfd, ldhdr.l_nreloc * sizeof (arelent)); if (relbuf == NULL) return -1; elrel = ((struct external_ldrel *) (contents + LDHDRSZ + ldhdr.l_nsyms * LDSYMSZ)); elrelend = elrel + ldhdr.l_nreloc; for (; elrel < elrelend; elrel++, relbuf++, prelocs++) { struct internal_ldrel ldrel; xcoff_swap_ldrel_in (abfd, elrel, &ldrel); if (ldrel.l_symndx >= 3) relbuf->sym_ptr_ptr = syms + (ldrel.l_symndx - 3); else { const char *name; asection *sec; switch (ldrel.l_symndx) { case 0: name = ".text"; break; case 1: name = ".data"; break; case 2: name = ".bss"; break; default: abort (); break; } sec = bfd_get_section_by_name (abfd, name); if (sec == NULL) { bfd_set_error (bfd_error_bad_value); return -1; } relbuf->sym_ptr_ptr = sec->symbol_ptr_ptr; } relbuf->address = ldrel.l_vaddr; relbuf->addend = 0; /* Most dynamic relocs have the same type. FIXME: This is only correct if ldrel.l_rtype == 0. In other cases, we should use a different howto. */ relbuf->howto = &xcoff_dynamic_reloc; /* FIXME: We have no way to record the l_rsecnm field. */ *prelocs = relbuf; } *prelocs = NULL; return ldhdr.l_nreloc;}/* Routine to create an entry in an XCOFF link hash table. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?