coff-a29k.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 604 行 · 第 1/2 页
C
604 行
} else { asymbol *ptr; relent->sym_ptr_ptr = symbols + obj_convert(abfd)[reloc->r_symndx]; ptr = *(relent->sym_ptr_ptr); if (ptr && bfd_asymbol_bfd(ptr) == abfd && ((ptr->flags & BSF_OLD_COMMON)== 0)) { relent->addend = 0; } else { relent->addend = 0; } relent->address-= section->vma; if (reloc->r_type == R_IHIHALF) ihihalf_vaddr = relent->address; else if (ihihalf_vaddr != (bfd_vma) -1) abort (); }}/* The reloc processing routine for the optimized COFF linker. */static booleancoff_a29k_relocate_section (output_bfd, info, input_bfd, input_section, contents, relocs, syms, sections) bfd *output_bfd ATTRIBUTE_UNUSED; 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; /* 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; bfd_byte *loc; struct coff_link_hash_entry *h; struct internal_syment *sym; asection *sec; bfd_vma val; boolean overflow; unsigned long insn; long signed_value; unsigned long unsigned_value; bfd_reloc_status_type rstat; symndx = rel->r_symndx; loc = contents + rel->r_vaddr - input_section->vma; if (symndx == -1 || rel->r_type == R_IHCONST) h = NULL; else h = obj_coff_sym_hashes (input_bfd)[symndx]; sym = NULL; sec = NULL; val = 0; /* An R_IHCONST reloc does not have a symbol. Instead, the symbol index is an addend. R_IHCONST is always used in conjunction with R_IHHALF. */ if (rel->r_type != R_IHCONST) { if (h == NULL) { if (symndx == -1) sec = bfd_abs_section_ptr; else { sym = syms + symndx; sec = sections[symndx]; val = (sec->output_section->vma + sec->output_offset + sym->n_value - sec->vma); } } else { if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) { sec = h->root.u.def.section; val = (h->root.u.def.value + sec->output_section->vma + sec->output_offset); } else { if (! ((*info->callbacks->undefined_symbol) (info, h->root.root.string, input_bfd, input_section, rel->r_vaddr - input_section->vma, true))) return false; } } if (hihalf) { if (! ((*info->callbacks->reloc_dangerous) (info, _("missing IHCONST reloc"), input_bfd, input_section, rel->r_vaddr - input_section->vma))) return false; hihalf = false; } } overflow = false; switch (rel->r_type) { default: bfd_set_error (bfd_error_bad_value); return false; case R_IREL: insn = bfd_get_32 (input_bfd, loc); /* Extract the addend. */ signed_value = EXTRACT_HWORD (insn); signed_value = SIGN_EXTEND_HWORD (signed_value); signed_value <<= 2; /* Unfortunately, there are two different versions of COFF a29k. In the original AMD version, the value stored in the field for the R_IREL reloc is a simple addend. In the GNU version, the value is the negative of the address of the reloc within section. We try to cope here by assuming the AMD version, unless the addend is exactly the negative of the address; in the latter case we assume the GNU version. This means that something like .text nop jmp i-4 will fail, because the addend of -4 will happen to equal the negative of the address within the section. The compiler will never generate code like this. At some point in the future we may want to take out this check. */ if (signed_value == - (long) (rel->r_vaddr - input_section->vma)) signed_value = 0; /* Determine the destination of the jump. */ signed_value += val; if ((signed_value & ~0x3ffff) == 0) { /* We can use an absolute jump. */ insn |= (1 << 24); } else { /* Make the destination PC relative. */ signed_value -= (input_section->output_section->vma + input_section->output_offset + (rel->r_vaddr - input_section->vma)); if (signed_value > 0x1ffff || signed_value < - 0x20000) { overflow = true; signed_value = 0; } } /* Put the adjusted value back into the instruction. */ signed_value >>= 2; insn = INSERT_HWORD (insn, signed_value); bfd_put_32 (input_bfd, (bfd_vma) insn, loc); break; case R_ILOHALF: insn = bfd_get_32 (input_bfd, loc); unsigned_value = EXTRACT_HWORD (insn); unsigned_value += val; insn = INSERT_HWORD (insn, unsigned_value); bfd_put_32 (input_bfd, insn, loc); break; case R_IHIHALF: /* Save the value for the R_IHCONST reloc. */ hihalf = true; hihalf_val = val; break; case R_IHCONST: if (! hihalf) { if (! ((*info->callbacks->reloc_dangerous) (info, _("missing IHIHALF reloc"), input_bfd, input_section, rel->r_vaddr - input_section->vma))) return false; hihalf_val = 0; } insn = bfd_get_32 (input_bfd, loc); unsigned_value = rel->r_symndx + hihalf_val; unsigned_value >>= 16; insn = INSERT_HWORD (insn, unsigned_value); bfd_put_32 (input_bfd, (bfd_vma) insn, loc); hihalf = false; break; case R_BYTE: case R_HWORD: case R_WORD: rstat = _bfd_relocate_contents (howto_table + rel->r_type, input_bfd, val, loc); if (rstat == bfd_reloc_overflow) overflow = true; else if (rstat != bfd_reloc_ok) abort (); break; } if (overflow) { const char *name; char buf[SYMNMLEN + 1]; if (symndx == -1) name = "*ABS*"; else if (h != NULL) name = h->root.root.string; else if (sym == NULL) name = "*unknown*"; else if (sym->_n._n_n._n_zeroes == 0 && sym->_n._n_n._n_offset != 0) name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset; else { strncpy (buf, sym->_n._n_name, SYMNMLEN); buf[SYMNMLEN] = '\0'; name = buf; } if (! ((*info->callbacks->reloc_overflow) (info, name, howto_table[rel->r_type].name, (bfd_vma) 0, input_bfd, input_section, rel->r_vaddr - input_section->vma))) return false; } } return true;}#define coff_relocate_section coff_a29k_relocate_section/* We don't want to change the symndx of a R_IHCONST reloc, since it is actually an addend, not a symbol index at all. */static booleancoff_a29k_adjust_symndx (obfd, info, ibfd, sec, irel, adjustedp) bfd *obfd ATTRIBUTE_UNUSED; struct bfd_link_info *info ATTRIBUTE_UNUSED; bfd *ibfd ATTRIBUTE_UNUSED; asection *sec ATTRIBUTE_UNUSED; struct internal_reloc *irel; boolean *adjustedp;{ if (irel->r_type == R_IHCONST) *adjustedp = true; else *adjustedp = false; return true;}#define coff_adjust_symndx coff_a29k_adjust_symndx#include "coffcode.h"CREATE_BIG_COFF_TARGET_VEC (a29kcoff_big_vec, "coff-a29k-big", 0, SEC_READONLY, '_', NULL)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?