coff-ppc.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,197 行 · 第 1/5 页
C
2,197 行
}}#ifdef COFF_IMAGE_WITH_PEstatic boolean ppc_record_toc_entry PARAMS ((bfd *, struct bfd_link_info *, asection *, int, enum toc_type));static void ppc_mark_symbol_as_glue PARAMS ((bfd *, int, struct internal_reloc *));/* record a toc offset against a symbol */static booleanppc_record_toc_entry(abfd, info, sec, sym, toc_kind) bfd *abfd; struct bfd_link_info *info ATTRIBUTE_UNUSED; asection *sec ATTRIBUTE_UNUSED; int sym; enum toc_type toc_kind ATTRIBUTE_UNUSED;{ struct ppc_coff_link_hash_entry *h; const char *name; int *local_syms; h = 0; h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]); if (h != 0) { HASH_CHECK(h); } if (h == 0) { local_syms = obj_coff_local_toc_table(abfd); if (local_syms == 0) { unsigned int i; /* allocate a table */ local_syms = (int *) bfd_zalloc (abfd, obj_raw_syment_count(abfd) * sizeof (int)); if (local_syms == 0) return false; obj_coff_local_toc_table(abfd) = local_syms; for (i = 0; i < obj_raw_syment_count(abfd); ++i) { SET_UNALLOCATED(local_syms[i]); } } if (IS_UNALLOCATED(local_syms[sym])) { local_syms[sym] = global_toc_size; global_toc_size += 4; /* The size must fit in a 16bit displacment */ if (global_toc_size > 65535) { (*_bfd_error_handler) (_("TOC overflow")); bfd_set_error (bfd_error_file_too_big); return false; } } } else { name = h->root.root.root.string; /* check to see if there's a toc slot allocated. If not, do it here. It will be used in relocate_section */ if (IS_UNALLOCATED(h->toc_offset)) { h->toc_offset = global_toc_size; global_toc_size += 4; /* The size must fit in a 16bit displacment */ if (global_toc_size >= 65535) { (*_bfd_error_handler) (_("TOC overflow")); bfd_set_error (bfd_error_file_too_big); return false; } } } return true;}/* record a toc offset against a symbol */static voidppc_mark_symbol_as_glue(abfd, sym, rel) bfd *abfd; int sym; struct internal_reloc *rel;{ struct ppc_coff_link_hash_entry *h; h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]); HASH_CHECK(h); h->symbol_is_glue = 1; h->glue_insn = bfd_get_32 (abfd, (bfd_byte *) &rel->r_vaddr); return;}#endif /* COFF_IMAGE_WITH_PE *//* Return true if this relocation should appear in the output .reloc section. */static boolean in_reloc_p(abfd, howto) bfd * abfd ATTRIBUTE_UNUSED; reloc_howto_type *howto;{ return (! howto->pc_relative) && (howto->type != IMAGE_REL_PPC_ADDR32NB) && (howto->type != IMAGE_REL_PPC_TOCREL16) && (howto->type != IMAGE_REL_PPC_IMGLUE) && (howto->type != IMAGE_REL_PPC_IFGLUE) && (howto->type != IMAGE_REL_PPC_SECREL) && (howto->type != IMAGE_REL_PPC_SECTION) && (howto->type != IMAGE_REL_PPC_SECREL16) && (howto->type != IMAGE_REL_PPC_REFHI) && (howto->type != IMAGE_REL_PPC_REFLO) && (howto->type != IMAGE_REL_PPC_PAIR) && (howto->type != IMAGE_REL_PPC_TOCREL16_DEFN) ;}#if 0/* this function is in charge of performing all the ppc PE relocations *//* Don't yet know if we want to do this this particular way ... (krk) *//* FIXME: (it is not yet enabled) */static bfd_reloc_status_typepe_ppc_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd, error_message) bfd *abfd; arelent *reloc_entry; asymbol *symbol_in; PTR data; asection *input_section; bfd *output_bfd; char **error_message;{ /* the consth relocation comes in two parts, we have to remember the state between calls, in these variables */ static boolean part1_consth_active = false; static unsigned long part1_consth_value; unsigned long sym_value; unsigned short r_type; unsigned long addr = reloc_entry->address ; /*+ input_section->vma*/ r_type = reloc_entry->howto->type; if (output_bfd) { /* Partial linking - do nothing */ reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; } if (symbol_in != NULL && bfd_is_und_section (symbol_in->section)) { /* Keep the state machine happy in case we're called again */ if (r_type == IMAGE_REL_PPC_REFHI) { part1_consth_active = true; part1_consth_value = 0; } return(bfd_reloc_undefined); } if ((part1_consth_active) && (r_type != IMAGE_REL_PPC_PAIR)) { part1_consth_active = false; *error_message = (char *) _("Missing PAIR"); return(bfd_reloc_dangerous); } sym_value = get_symbol_value(symbol_in); return(bfd_reloc_ok);}#endif /* 0 *//* The reloc processing routine for the optimized COFF linker. */static booleancoff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, contents, relocs, syms, sections) bfd *output_bfd; struct bfd_link_info *info; bfd *input_bfd; asection *input_section; bfd_byte *contents; struct internal_reloc *relocs; struct internal_syment *syms; asection **sections;{ struct internal_reloc *rel; struct internal_reloc *relend; boolean hihalf; bfd_vma hihalf_val; asection *toc_section = 0; bfd_vma relocation; reloc_howto_type *howto = 0; /* If we are performing a relocateable link, we don't need to do a thing. The caller will take care of adjusting the reloc addresses and symbol indices. */ if (info->relocateable) return true; hihalf = false; hihalf_val = 0; rel = relocs; relend = rel + input_section->reloc_count; for (; rel < relend; rel++) { long symndx; struct ppc_coff_link_hash_entry *h; struct internal_syment *sym; bfd_vma val; asection *sec; bfd_reloc_status_type rstat; bfd_byte *loc; unsigned short r_type = EXTRACT_TYPE (rel->r_type); unsigned short r_flags = EXTRACT_FLAGS(rel->r_type); symndx = rel->r_symndx; loc = contents + rel->r_vaddr - input_section->vma; /* FIXME: check bounds on r_type */ howto = ppc_coff_howto_table + r_type; if (symndx == -1) { h = NULL; sym = NULL; } else { h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (input_bfd)[symndx]); if (h != 0) { HASH_CHECK(h); } sym = syms + symndx; } if (r_type == IMAGE_REL_PPC_IMGLUE && h == 0) { /* An IMGLUE reloc must have a name. Something is very wrong. */ abort (); } sec = NULL; val = 0; /* FIXME: PAIR unsupported in the following code */ if (h == NULL) { if (symndx == -1) sec = bfd_abs_section_ptr; else { sec = sections[symndx]; val = (sec->output_section->vma + sec->output_offset + sym->n_value); if (! obj_pe (output_bfd)) val -= sec->vma; } } else { HASH_CHECK(h); if (h->root.root.type == bfd_link_hash_defined || h->root.root.type == bfd_link_hash_defweak) { sec = h->root.root.u.def.section; val = (h->root.root.u.def.value + sec->output_section->vma + sec->output_offset); } else { if (! ((*info->callbacks->undefined_symbol) (info, h->root.root.root.string, input_bfd, input_section, rel->r_vaddr - input_section->vma, true))) return false; } } rstat = bfd_reloc_ok; /* Each case must do its own relocation, setting rstat appropriately */ switch (r_type) { default: (*_bfd_error_handler) (_("%s: unsupported relocation type 0x%02x"), bfd_get_filename (input_bfd), r_type); bfd_set_error (bfd_error_bad_value); return false; case IMAGE_REL_PPC_TOCREL16: { bfd_vma our_toc_offset; int fixit; DUMP_RELOC2(howto->name, rel); if (toc_section == 0) { toc_section = bfd_get_section_by_name (bfd_of_toc_owner, TOC_SECTION_NAME); if ( toc_section == NULL ) { /* There is no toc section. Something is very wrong. */ abort (); } } /* * Amazing bit tricks present. As we may have seen earlier, we * use the 1 bit to tell us whether or not a toc offset has been * allocated. Now that they've all been allocated, we will use * the 1 bit to tell us if we've written this particular toc * entry out. */ fixit = false; if (h == 0) { /* it is a file local symbol */ int *local_toc_table; const char *name; sym = syms + symndx; name = sym->_n._n_name; local_toc_table = obj_coff_local_toc_table(input_bfd); our_toc_offset = local_toc_table[symndx]; if (IS_WRITTEN(our_toc_offset)) { /* if it has been written out, it is marked with the 1 bit. Fix up our offset, but do not write it out again. */ MAKE_ADDR_AGAIN(our_toc_offset); } else { /* write out the toc entry */ record_toc(toc_section, our_toc_offset, priv, strdup(name)); bfd_put_32 (output_bfd, val, toc_section->contents + our_toc_offset); MARK_AS_WRITTEN(local_toc_table[symndx]); fixit = true; } } else { const char *name = h->root.root.root.string; our_toc_offset = h->toc_offset; if ((r_flags & IMAGE_REL_PPC_TOCDEFN) == IMAGE_REL_PPC_TOCDEFN ) { /* This is unbelievable cheese. Some knowledgable asm hacker has decided to use r2 as a base for loading a value. He/She does this by setting the tocdefn bit, and not supplying a toc definition. The behaviour is then to use the difference between the value of the symbol and the actual location of the toc as the toc index. In fact, what is usually happening is, because the Import Address Table is mapped immediately following the toc, some trippy library code trying for speed on dll linkage, takes advantage of that and considers the IAT to be part of the toc, thus saving a load. */ our_toc_offset = val - (toc_section->output_section->vma + toc_section->output_offset); /* The size must still fit in a 16bit displacment */ if (our_toc_offset >= 65535) { (*_bfd_error_handler) (_("%s: Relocation for %s of %x exceeds Toc size limit"), bfd_get_filename (input_bfd), name, our_toc_offset); bfd_set_error (bfd_error_bad_value); return false; } record_toc(toc_section, our_toc_offset, pub, strdup(name)); } else if (IS_WRITTEN(our_toc_offset)) { /* if it has been written out, it is marked with the 1 bit. Fix up our offset, but do not write it out again. */ MAKE_ADDR_AGAIN(our_toc_offset); } else { record_toc(toc_section, our_toc_offset, pub, strdup(name)); /* write out the toc entry */ bfd_put_32 (output_bfd, val, toc_section->contents + our_toc_offset); MARK_AS_WRITTEN(h->toc_offset); /* The tricky part is that this is the address that */ /* needs a .reloc entry for it */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?