📄 reloc.c
字号:
} /* Work out which section the relocation is targetted at and the initial relocation command value. */ if (symbol->section == &bfd_com_section) { relocation = 0; } else { relocation = symbol->value; } reloc_target_output_section = symbol->section->output_section; if (output_bfd && howto->partial_inplace==false) { output_base = 0; } else { output_base = reloc_target_output_section->vma; } relocation += output_base + symbol->section->output_offset; relocation += reloc_entry->addend ; if(reloc_entry->address > input_section->_cooked_size) { return bfd_reloc_outofrange; } if (howto->pc_relative == true) { /* Anything which started out as pc relative should end up that way too. There are two ways we can see a pcrel instruction. Sometimes the pcrel displacement has been partially calculated, it includes the distance from the start of the section to the instruction in it (eg sun3), and sometimes the field is totally blank - eg m88kbcs. */ relocation -= input_section->output_section->vma + input_section->output_offset; if (howto->pcrel_offset == true) { relocation -= reloc_entry->address; } } if (output_bfd!= (bfd *)NULL) { if ( howto->partial_inplace == false) { /* This is a partial relocation, and we want to apply the relocation to the reloc entry rather than the raw data. Modify the reloc inplace to reflect what we now know. */ reloc_entry->addend = relocation ; reloc_entry->address += input_section->output_offset; return flag; } else { /* This is a partial relocation, but inplace, so modify the reloc record a bit. If we've relocated with a symbol with a section, change into a ref to the section belonging to the symbol */ reloc_entry->addend = relocation ; reloc_entry->address += input_section->output_offset; } } else { reloc_entry->addend = 0; } /* Either we are relocating all the way, or we don't want to apply the relocation to the reloc entry (probably because there isn't any room in the output format to describe addends to relocs) */ relocation >>= howto->rightshift; /* Shift everything up to where it's going to be used */ relocation <<= howto->bitpos; /* Wait for the day when all have the mask in them */ /* What we do: i instruction to be left alone o offset within instruction r relocation offset to apply S src mask D dst mask N ~dst mask A part 1 B part 2 R result Do this: i i i i i o o o o o from bfd_get<size> and S S S S S to get the size offset we want + r r r r r r r r r r to get the final value to place and D D D D D to chop to right size ----------------------- A A A A A And this: ... i i i i i o o o o o from bfd_get<size> and N N N N N get instruction ----------------------- ... B B B B B And then: B B B B B or A A A A A ----------------------- R R R R R R R R R R put into bfd_put<size> */#define DOIT(x) \ x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask)) switch (howto->size) { case 0: { char x = bfd_get_8(abfd, (char *)data + addr); DOIT(x); bfd_put_8(abfd,x, (unsigned char *) data + addr); } break; case 1: { short x = bfd_get_16(abfd, (bfd_byte *)data + addr); DOIT(x); bfd_put_16(abfd, x, (unsigned char *)data + addr); } break; case 2: { long x = bfd_get_32(abfd, (bfd_byte *) data + addr); DOIT(x); bfd_put_32(abfd,x, (bfd_byte *)data + addr); } break; case -2: { long x = bfd_get_32(abfd, (bfd_byte *) data + addr); relocation = -relocation; DOIT(x); bfd_put_32(abfd,x, (bfd_byte *)data + addr); } break; case 3: /* Do nothing */ break; default: return bfd_reloc_other; } return flag;}/*DOCDDINODE howto manager, , typedef arelent, RelocationsSECTION The howto manager When an application wants to create a relocation, but doesn't know what the target machine might call it, it can find out by using this bit of code.*//*TYPEDEF bfd_reloc_code_typeDESCRIPTION The insides of a reloc codeCODE_FRAGMENT..typedef enum bfd_reloc_code_real ..{. {* 16 bits wide, simple reloc *}. BFD_RELOC_16, .. {* 8 bits wide, but used to form an address like 0xffnn *}. BFD_RELOC_8_FFnn,.. {* 8 bits wide, simple *}. BFD_RELOC_8,.. {* 8 bits wide, pc relative *}. BFD_RELOC_8_PCREL,.. {* The type of reloc used to build a contructor table - at the. moment probably a 32 bit wide abs address, but the cpu can. choose. *}.. BFD_RELOC_CTOR,.. {* 32 bits wide, simple reloc *}. BFD_RELOC_32,. {* 32 bits, PC-relative *}. BFD_RELOC_32_PCREL,.. {* High 22 bits of 32-bit value; simple reloc. *}. BFD_RELOC_HI22,. {* Low 10 bits. *}. BFD_RELOC_LO10,.. {* Reloc types used for i960/b.out. *}. BFD_RELOC_24_PCREL,. BFD_RELOC_I960_CALLJ,.. BFD_RELOC_16_PCREL,. {* 32-bit pc-relative, shifted right 2 bits (i.e., 30-bit. word displacement, e.g. for SPARC) *}. BFD_RELOC_32_PCREL_S2,.. {* now for the sparc/elf codes *}. BFD_RELOC_NONE, {* actually used *}. BFD_RELOC_SPARC_WDISP22,. BFD_RELOC_SPARC22,. BFD_RELOC_SPARC13,. BFD_RELOC_SPARC_BASE13,. BFD_RELOC_SPARC_GOT10,. BFD_RELOC_SPARC_GOT13,. BFD_RELOC_SPARC_GOT22,. BFD_RELOC_SPARC_PC10,. BFD_RELOC_SPARC_PC22,. BFD_RELOC_SPARC_WPLT30,. BFD_RELOC_SPARC_COPY,. BFD_RELOC_SPARC_GLOB_DAT,. BFD_RELOC_SPARC_JMP_SLOT,. BFD_RELOC_SPARC_RELATIVE,. BFD_RELOC_SPARC_UA32,.. {* this one is a.out specific? *}. BFD_RELOC_SPARC_BASE22,.. {* this must be the highest numeric value *}. BFD_RELOC_UNUSED. } bfd_reloc_code_real_type;*//*SECTION bfd_reloc_type_lookupSYNOPSIS CONST struct reloc_howto_struct * bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code);DESCRIPTION This routine returns a pointer to a howto struct which when invoked, will perform the supplied relocation on data from the architecture noted.*/CONST struct reloc_howto_struct *DEFUN(bfd_reloc_type_lookup,(abfd, code), bfd *abfd AND bfd_reloc_code_real_type code){ return BFD_SEND (abfd, reloc_type_lookup, (abfd, code));}static reloc_howto_type bfd_howto_32 = HOWTO(0, 00,2,32,false,0,false,true,0,"VRT32", false,0xffffffff,0xffffffff,true);/*INTERNAL_FUNCTION bfd_default_reloc_type_lookupSYNOPSIS CONST struct reloc_howto_struct *bfd_default_reloc_type_lookup (CONST struct bfd_arch_info *, bfd_reloc_code_real_type code);DESCRIPTION Provides a default relocation lookuperer for any architectue */CONST struct reloc_howto_struct *DEFUN(bfd_default_reloc_type_lookup,(arch, code), CONST struct bfd_arch_info *arch AND bfd_reloc_code_real_type code){ switch (code) { case BFD_RELOC_CTOR: /* The type of reloc used in a ctor, which will be as wide as the address - so either a 64, 32, or 16 bitter.. */ switch (arch->bits_per_address) { case 64: BFD_FAIL(); case 32: return &bfd_howto_32; case 16: BFD_FAIL(); default: BFD_FAIL(); } default: BFD_FAIL(); }return (CONST struct reloc_howto_struct *)NULL;}/*INTERNAL_FUNCTION bfd_generic_relax_sectionSYNOPSIS boolean bfd_generic_relax_section (bfd *abfd, asection *section, asymbol **symbols);DESCRIPTION Provides default handling for relaxing for back ends which don't do relaxing -- i.e., does nothing.*/booleanDEFUN(bfd_generic_relax_section,(abfd, section, symbols), bfd *abfd AND asection *section AND asymbol **symbols){ return false; } /*INTERNAL_FUNCTION bfd_generic_get_relocated_section_contentsSYNOPSIS bfd_byte * bfd_generic_get_relocated_section_contents(bfd *abfd, struct bfd_seclet_struct *seclet, bfd_byte *data)DESCRIPTION Provides default handling of relocation effort for back ends which can't be bothered to do it efficiently.*/bfd_byte *DEFUN(bfd_generic_get_relocated_section_contents,(abfd, seclet, data), bfd *abfd AND struct bfd_seclet_struct *seclet AND bfd_byte *data){ extern bfd_error_vector_type bfd_error_vector; /* Get enough memory to hold the stuff */ bfd *input_bfd = seclet->u.indirect.section->owner; asection *input_section = seclet->u.indirect.section; bfd_size_type reloc_size = bfd_get_reloc_upper_bound(input_bfd, input_section); arelent **reloc_vector = (arelent **) alloca(reloc_size); /* read in the section */ bfd_get_section_contents(input_bfd, input_section, data, 0, input_section->_raw_size); /* We're not relaxing the section, so just copy the size info */ input_section->_cooked_size = input_section->_raw_size; input_section->reloc_done = true; if (bfd_canonicalize_reloc(input_bfd, input_section, reloc_vector, seclet->u.indirect.symbols) ) { arelent **parent; for (parent = reloc_vector; * parent != (arelent *)NULL; parent++) { bfd_reloc_status_type r= bfd_perform_relocation(input_bfd, *parent, data, input_section, 0); if (r != bfd_reloc_ok) { switch (r) { case bfd_reloc_undefined: bfd_error_vector.undefined_symbol(*parent, seclet); break; case bfd_reloc_dangerous: bfd_error_vector.reloc_dangerous(*parent, seclet); break; case bfd_reloc_outofrange: case bfd_reloc_overflow: bfd_error_vector.reloc_value_truncated(*parent, seclet); break; default: abort(); break; } } } } return data; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -