reloc.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,228 行 · 第 1/5 页
C
2,228 行
relocateable link depends upon how the object format defines relocations. FIXME: This routine ignores any special_function in the HOWTO, since the existing special_function values have been written for bfd_perform_relocation. HOWTO is the reloc howto information. INPUT_BFD is the BFD which the reloc applies to. INPUT_SECTION is the section which the reloc applies to. CONTENTS is the contents of the section. ADDRESS is the address of the reloc within INPUT_SECTION. VALUE is the value of the symbol the reloc refers to. ADDEND is the addend of the reloc. */bfd_reloc_status_type_bfd_final_link_relocate (howto, input_bfd, input_section, contents, address, value, addend) reloc_howto_type *howto; bfd *input_bfd; asection *input_section; bfd_byte *contents; bfd_vma address; bfd_vma value; bfd_vma addend;{ bfd_vma relocation; /* Sanity check the address. */ if (address > input_section->_raw_size) return bfd_reloc_outofrange; /* This function assumes that we are dealing with a basic relocation against a symbol. We want to compute the value of the symbol to relocate to. This is just VALUE, the value of the symbol, plus ADDEND, any addend associated with the reloc. */ relocation = value + addend; /* If the relocation is PC relative, we want to set RELOCATION to the distance between the symbol (currently in RELOCATION) and the location we are relocating. Some targets (e.g., i386-aout) arrange for the contents of the section to be the negative of the offset of the location within the section; for such targets pcrel_offset is false. Other targets (e.g., m88kbcs or ELF) simply leave the contents of the section as zero; for such targets pcrel_offset is true. If pcrel_offset is false we do not need to subtract out the offset of the location within the section (which is just ADDRESS). */ if (howto->pc_relative) { relocation -= (input_section->output_section->vma + input_section->output_offset); if (howto->pcrel_offset) relocation -= address; } return _bfd_relocate_contents (howto, input_bfd, relocation, contents + address);}/* Relocate a given location using a given value and howto. */bfd_reloc_status_type_bfd_relocate_contents (howto, input_bfd, relocation, location) reloc_howto_type *howto; bfd *input_bfd; bfd_vma relocation; bfd_byte *location;{ int size; bfd_vma x = 0; bfd_reloc_status_type flag; unsigned int rightshift = howto->rightshift; unsigned int bitpos = howto->bitpos; /* If the size is negative, negate RELOCATION. This isn't very general. */ if (howto->size < 0) relocation = -relocation; /* Get the value we are going to relocate. */ size = bfd_get_reloc_size (howto); switch (size) { default: case 0: abort (); case 1: x = bfd_get_8 (input_bfd, location); break; case 2: x = bfd_get_16 (input_bfd, location); break; case 4: x = bfd_get_32 (input_bfd, location); break; case 8:#ifdef BFD64 x = bfd_get_64 (input_bfd, location);#else abort ();#endif break; } /* Check for overflow. FIXME: We may drop bits during the addition which we don't check for. We must either check at every single operation, which would be tedious, or we must do the computations in a type larger than bfd_vma, which would be inefficient. */ flag = bfd_reloc_ok; if (howto->complain_on_overflow != complain_overflow_dont) { bfd_vma addrmask, fieldmask, signmask, ss; bfd_vma a, b, sum; /* Get the values to be added together. For signed and unsigned relocations, we assume that all values should be truncated to the size of an address. For bitfields, all the bits matter. See also bfd_check_overflow. */ fieldmask = N_ONES (howto->bitsize); addrmask = N_ONES (bfd_arch_bits_per_address (input_bfd)) | fieldmask; a = relocation; b = x & howto->src_mask; switch (howto->complain_on_overflow) { case complain_overflow_signed: a = (a & addrmask) >> rightshift; /* If any sign bits are set, all sign bits must be set. That is, A must be a valid negative address after shifting. */ signmask = ~ (fieldmask >> 1); ss = a & signmask; if (ss != 0 && ss != ((addrmask >> rightshift) & signmask)) flag = bfd_reloc_overflow; /* We only need this next bit of code if the sign bit of B is below the sign bit of A. This would only happen if SRC_MASK had fewer bits than BITSIZE. Note that if SRC_MASK has more bits than BITSIZE, we can get into trouble; we would need to verify that B is in range, as we do for A above. */ signmask = ((~ howto->src_mask) >> 1) & howto->src_mask; /* Set all the bits above the sign bit. */ b = (b ^ signmask) - signmask; b = (b & addrmask) >> bitpos; /* Now we can do the addition. */ sum = a + b; /* See if the result has the correct sign. Bits above the sign bit are junk now; ignore them. If the sum is positive, make sure we did not have all negative inputs; if the sum is negative, make sure we did not have all positive inputs. The test below looks only at the sign bits, and it really just SIGN (A) == SIGN (B) && SIGN (A) != SIGN (SUM) */ signmask = (fieldmask >> 1) + 1; if (((~ (a ^ b)) & (a ^ sum)) & signmask) flag = bfd_reloc_overflow; break; case complain_overflow_unsigned: /* Checking for an unsigned overflow is relatively easy: trim the addresses and add, and trim the result as well. Overflow is normally indicated when the result does not fit in the field. However, we also need to consider the case when, e.g., fieldmask is 0x7fffffff or smaller, an input is 0x80000000, and bfd_vma is only 32 bits; then we will get sum == 0, but there is an overflow, since the inputs did not fit in the field. Instead of doing a separate test, we can check for this by or-ing in the operands when testing for the sum overflowing its final field. */ a = (a & addrmask) >> rightshift; b = (b & addrmask) >> bitpos; sum = (a + b) & addrmask; if ((a | b | sum) & ~ fieldmask) flag = bfd_reloc_overflow; break; case complain_overflow_bitfield: /* Much like the signed check, but for a field one bit wider, and no trimming inputs with addrmask. We allow a bitfield to represent numbers in the range -2**n to 2**n-1, where n is the number of bits in the field. Note that when bfd_vma is 32 bits, a 32-bit reloc can't overflow, which is exactly what we want. */ a >>= rightshift; signmask = ~ fieldmask; ss = a & signmask; if (ss != 0 && ss != (((bfd_vma) -1 >> rightshift) & signmask)) flag = bfd_reloc_overflow; signmask = ((~ howto->src_mask) >> 1) & howto->src_mask; b = (b ^ signmask) - signmask; b >>= bitpos; sum = a + b; /* We mask with addrmask here to explicitly allow an address wrap-around. The Linux kernel relies on it, and it is the only way to write assembler code which can run when loaded at a location 0x80000000 away from the location at which it is linked. */ signmask = fieldmask + 1; if (((~ (a ^ b)) & (a ^ sum)) & signmask & addrmask) flag = bfd_reloc_overflow; break; default: abort (); } } /* Put RELOCATION in the right bits. */ relocation >>= (bfd_vma) rightshift; relocation <<= (bfd_vma) bitpos; /* Add RELOCATION to the right bits of X. */ x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask)); /* Put the relocated value back in the object file. */ switch (size) { default: case 0: abort (); case 1: bfd_put_8 (input_bfd, x, location); break; case 2: bfd_put_16 (input_bfd, x, location); break; case 4: bfd_put_32 (input_bfd, x, location); break; case 8:#ifdef BFD64 bfd_put_64 (input_bfd, x, location);#else abort ();#endif break; } 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 code. The idea is that, eventually, there will be one enumerator for every type of relocation we ever do. Pass one of these values to <<bfd_reloc_type_lookup>>, and it'll return a howto pointer. This does mean that the application must determine the correct enumerator value; you can't get a howto pointer from a random set of attributes.SENUM bfd_reloc_code_realENUM BFD_RELOC_64ENUMX BFD_RELOC_32ENUMX BFD_RELOC_26ENUMX BFD_RELOC_24ENUMX BFD_RELOC_16ENUMX BFD_RELOC_14ENUMX BFD_RELOC_8ENUMDOC Basic absolute relocations of N bits.ENUM BFD_RELOC_64_PCRELENUMX BFD_RELOC_32_PCRELENUMX BFD_RELOC_24_PCRELENUMX BFD_RELOC_16_PCRELENUMX BFD_RELOC_12_PCRELENUMX BFD_RELOC_8_PCRELENUMDOC PC-relative relocations. Sometimes these are relative to the addressof the relocation itself; sometimes they are relative to the start ofthe section containing the relocation. It depends on the specific target.The 24-bit relocation is used in some Intel 960 configurations.ENUM BFD_RELOC_32_GOT_PCRELENUMX BFD_RELOC_16_GOT_PCRELENUMX BFD_RELOC_8_GOT_PCRELENUMX BFD_RELOC_32_GOTOFFENUMX BFD_RELOC_16_GOTOFFENUMX BFD_RELOC_LO16_GOTOFFENUMX BFD_RELOC_HI16_GOTOFFENUMX BFD_RELOC_HI16_S_GOTOFFENUMX BFD_RELOC_8_GOTOFFENUMX BFD_RELOC_32_PLT_PCRELENUMX BFD_RELOC_24_PLT_PCRELENUMX BFD_RELOC_16_PLT_PCRELENUMX BFD_RELOC_8_PLT_PCRELENUMX BFD_RELOC_32_PLTOFFENUMX BFD_RELOC_16_PLTOFFENUMX BFD_RELOC_LO16_PLTOFFENUMX BFD_RELOC_HI16_PLTOFFENUMX BFD_RELOC_HI16_S_PLTOFFENUMX BFD_RELOC_8_PLTOFFENUMDOC For ELF.ENUM BFD_RELOC_68K_GLOB_DATENUMX BFD_RELOC_68K_JMP_SLOTENUMX BFD_RELOC_68K_RELATIVEENUMDOC Relocations used by 68K ELF.ENUM BFD_RELOC_32_BASERELENUMX BFD_RELOC_16_BASERELENUMX BFD_RELOC_LO16_BASERELENUMX BFD_RELOC_HI16_BASERELENUMX BFD_RELOC_HI16_S_BASERELENUMX BFD_RELOC_8_BASERELENUMX BFD_RELOC_RVAENUMDOC Linkage-table relative.ENUM BFD_RELOC_8_FFnnENUMDOC Absolute 8-bit relocation, but used to form an address like 0xFFnn.ENUM BFD_RELOC_32_PCREL_S2ENUMX BFD_RELOC_16_PCREL_S2ENUMX BFD_RELOC_23_PCREL_S2ENUMDOC These PC-relative relocations are stored as word displacements --i.e., byte displacements shifted right two bits. The 30-bit worddisplacement (<<32_PCREL_S2>> -- 32 bits, shifted 2) is used on theSPARC. (SPARC tools generally refer to this as <<WDISP30>>.) Thesigned 16-bit displacement is used on the MIPS, and the 23-bitdisplacement is used on the Alpha.ENUM BFD_RELOC_HI22ENUMX BFD_RELOC_LO10ENUMDOC High 22 bits and low 10 bits of 32-bit value, placed into lower bits ofthe target word. These are used on the SPARC.ENUM BFD_RELOC_GPREL16ENUMX BFD_RELOC_GPREL32ENUMDOC For systems that allocate a Global Pointer register, these aredisplacements off that register. These relocation types arehandled specially, because the value the register will have isdecided relatively late.ENUM BFD_RELOC_I960_CALLJENUMDOC Reloc types used for i960/b.out.ENUM BFD_RELOC_NONEENUMX BFD_RELOC_SPARC_WDISP22ENUMX BFD_RELOC_SPARC22ENUMX BFD_RELOC_SPARC13ENUMX BFD_RELOC_SPARC_GOT10ENUMX
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?