aboutsummaryrefslogtreecommitdiff
path: root/bfd/reloc.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2018-08-21 11:54:29 +0930
committerAlan Modra <amodra@gmail.com>2018-08-21 14:59:53 +0930
commit706704c88344314646e4edcc0840cb18a9cb4c82 (patch)
treeae2cd087b3be38471edaa968d45fccaf026fa886 /bfd/reloc.c
parent487096bf0bd5499b1d23ecbe5fd64f9f0079c0b5 (diff)
downloadbinutils-706704c88344314646e4edcc0840cb18a9cb4c82.zip
binutils-706704c88344314646e4edcc0840cb18a9cb4c82.tar.gz
binutils-706704c88344314646e4edcc0840cb18a9cb4c82.tar.bz2
Pack reloc_howto_struct
This patch uses bitfields in reloc_howto_struct, reducing its size from 80 to 40 bytes on 64-bit hosts and from 52 to 32 bytes on 32-bit hosts (with a 32-bit bfd_vma). I've also added a new "negate" field rather than making the encoded "size" field do double duty as both a size and a flag. There was just one use of an encoded size of 8, which according to bfd_get_reloc_size meant 16 bytes, in vms-alpha.c ALPHA_R_LINKAGE. See git commit c3d8e071bf adding ALPHA_R_LINKAGE and git commit 8612a388f7 decoding size 8 in bfd_get_reloc_size. Since no other part of BFD handles 16 byte relocs, I've removed that encoding and special cased the ALPHA_R_LINKAGE size in vms-alpha.c. * reloc.c (reloc_howto_type): Typedef. (bfd_symbol): Delete forward declaration. (struct reloc_howto_struct): Add "negate" field. Make "size", "bitsize", "rightshift", "bitpos", "complain_on_overflow", "pc_relative", "partial_inplace", and "pcrel_offset" bitfields. Rearrange for better packing. Revise comments. (HOWTO): Map to rearranged reloc_howto_struct. (bfd_get_reloc_size): Delete now unused cases. (read_reloc, write_reloc): Likewise. (apply_reloc, _bfd_relocate_contents): Test howto->negate rather than howto->size < 0 for negated relocation values. * coff-rs6000.c (xcoff_complain_overflow_bitfield_func): Avoid signed/unsigned warning. (xcoff_ppc_relocate_section): Delete "condition is always false" code. * coff64-rs6000.c (xcoff64_ppc_relocate_section): Likewise. * cpu-ns32k.c (do_ns32k_reloc): Adjust to suit reloc_howto_struct changes. * vms-alpha.c (_bfd_vms_write_etir, alpha_vms_slurp_relocs): Use size 16 for ALPHA_R_LINKAGE. (alpha_howto_table <ALPHA_R_LINKAGE>): Set encoded size and bitsize to zero. * bfd-in.h (reloc_howto_type): Delete. * bfd-in2.h: Regenerate.
Diffstat (limited to 'bfd/reloc.c')
-rw-r--r--bfd/reloc.c110
1 files changed, 51 insertions, 59 deletions
diff --git a/bfd/reloc.c b/bfd/reloc.c
index ec58a7e..0dcf2be 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -94,6 +94,7 @@ CODE_FRAGMENT
. }
. bfd_reloc_status_type;
.
+.typedef const struct reloc_howto_struct reloc_howto_type;
.
.typedef struct reloc_cache_entry
.{
@@ -279,51 +280,39 @@ SUBSUBSECTION
information that libbfd needs to know to tie up a back end's data.
CODE_FRAGMENT
-.struct bfd_symbol; {* Forward declaration. *}
-.
.struct reloc_howto_struct
.{
-. {* The type field has mainly a documentary use - the back end can
-. do what it wants with it, though normally the back end's
-. external idea of what a reloc number is stored
-. in this field. For example, a PC relative word relocation
-. in a coff environment has the type 023 - because that's
-. what the outside world calls a R_PCRWORD reloc. *}
+. {* The type field has mainly a documentary use - the back end can
+. do what it wants with it, though normally the back end's idea of
+. an external reloc number is stored in this field. *}
. unsigned int type;
.
-. {* The value the final relocation is shifted right by. This drops
-. unwanted data from the relocation. *}
-. unsigned int rightshift;
-.
-. {* The size of the item to be relocated. This is *not* a
-. power-of-two measure. To get the number of bytes operated
-. on by a type of relocation, use bfd_get_reloc_size. *}
-. int size;
+. {* The encoded size of the item to be relocated. This is *not* a
+. power-of-two measure. Use bfd_get_reloc_size to find the size
+. of the item in bytes. *}
+. unsigned int size:3;
.
-. {* The number of bits in the item to be relocated. This is used
-. when doing overflow checking. *}
-. unsigned int bitsize;
+. {* The number of bits in the field to be relocated. This is used
+. when doing overflow checking. *}
+. unsigned int bitsize:7;
.
-. {* The relocation is relative to the field being relocated. *}
-. bfd_boolean pc_relative;
+. {* The value the final relocation is shifted right by. This drops
+. unwanted data from the relocation. *}
+. unsigned int rightshift:6;
.
-. {* The bit position of the reloc value in the destination.
-. The relocated value is left shifted by this amount. *}
-. unsigned int bitpos;
+. {* The bit position of the reloc value in the destination.
+. The relocated value is left shifted by this amount. *}
+. unsigned int bitpos:6;
.
. {* What type of overflow error should be checked for when
. relocating. *}
-. enum complain_overflow complain_on_overflow;
+. ENUM_BITFIELD (complain_overflow) complain_on_overflow:2;
.
-. {* If this field is non null, then the supplied function is
-. called rather than the normal function. This allows really
-. strange relocation methods to be accommodated. *}
-. bfd_reloc_status_type (*special_function)
-. (bfd *, arelent *, struct bfd_symbol *, void *, asection *,
-. bfd *, char **);
+. {* The relocation value should be negated before applying. *}
+. unsigned int negate:1;
.
-. {* The textual name of the relocation type. *}
-. char *name;
+. {* The relocation is relative to the item being relocated. *}
+. unsigned int pc_relative:1;
.
. {* Some formats record a relocation addend in the section contents
. rather than with the relocation. For ELF formats this is the
@@ -340,29 +329,39 @@ CODE_FRAGMENT
. USE_REL targets set this field to TRUE. Why this is so is peculiar
. to each particular target. For relocs that aren't used in partial
. links (e.g. GOT stuff) it doesn't matter what this is set to. *}
-. bfd_boolean partial_inplace;
+. unsigned int partial_inplace:1;
+.
+. {* When some formats create PC relative instructions, they leave
+. the value of the pc of the place being relocated in the offset
+. slot of the instruction, so that a PC relative relocation can
+. be made just by adding in an ordinary offset (e.g., sun3 a.out).
+. Some formats leave the displacement part of an instruction
+. empty (e.g., ELF); this flag signals the fact. *}
+. unsigned int pcrel_offset:1;
.
. {* src_mask selects the part of the instruction (or data) to be used
. in the relocation sum. If the target relocations don't have an
. addend in the reloc, eg. ELF USE_REL, src_mask will normally equal
. dst_mask to extract the addend from the section contents. If
. relocations do have an addend in the reloc, eg. ELF USE_RELA, this
-. field should be zero. Non-zero values for ELF USE_RELA targets are
-. bogus as in those cases the value in the dst_mask part of the
-. section contents should be treated as garbage. *}
+. field should normally be zero. Non-zero values for ELF USE_RELA
+. targets should be viewed with suspicion as normally the value in
+. the dst_mask part of the section contents should be ignored. *}
. bfd_vma src_mask;
.
. {* dst_mask selects which parts of the instruction (or data) are
. replaced with a relocated value. *}
. bfd_vma dst_mask;
.
-. {* When some formats create PC relative instructions, they leave
-. the value of the pc of the place being relocated in the offset
-. slot of the instruction, so that a PC relative relocation can
-. be made just by adding in an ordinary offset (e.g., sun3 a.out).
-. Some formats leave the displacement part of an instruction
-. empty (e.g., ELF); this flag signals the fact. *}
-. bfd_boolean pcrel_offset;
+. {* If this field is non null, then the supplied function is
+. called rather than the normal function. This allows really
+. strange relocation methods to be accommodated. *}
+. bfd_reloc_status_type (*special_function)
+. (bfd *, arelent *, struct bfd_symbol *, void *, asection *,
+. bfd *, char **);
+.
+. {* The textual name of the relocation type. *}
+. char *name;
.};
.
*/
@@ -375,8 +374,10 @@ DESCRIPTION
The HOWTO macro fills in a reloc_howto_type (a typedef for
const struct reloc_howto_struct).
-.#define HOWTO(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \
-. { (unsigned) C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC }
+.#define HOWTO(type, right, size, bits, pcrel, left, ovf, func, name, \
+. inplace, src_mask, dst_mask, pcrel_off) \
+. { (unsigned) type, size < 0 ? -size : size, bits, right, left, ovf, \
+. size < 0, pcrel, inplace, pcrel_off, src_mask, dst_mask, func, name }
DESCRIPTION
This is used to fill in an empty howto entry in an array.
@@ -405,14 +406,11 @@ bfd_get_reloc_size (reloc_howto_type *howto)
switch (howto->size)
{
case 0: return 1;
- case 1:
- case -1: return 2;
- case 2:
- case -2: return 4;
+ case 1: return 2;
+ case 2: return 4;
case 3: return 0;
case 4: return 8;
case 5: return 3;
- case 8: return 16;
default: abort ();
}
}
@@ -559,11 +557,9 @@ read_reloc (bfd *abfd, bfd_byte *data, reloc_howto_type *howto)
return bfd_get_8 (abfd, data);
case 1:
- case -1:
return bfd_get_16 (abfd, data);
case 2:
- case -2:
return bfd_get_32 (abfd, data);
case 3:
@@ -596,12 +592,10 @@ write_reloc (bfd *abfd, bfd_vma val, bfd_byte *data, reloc_howto_type *howto)
break;
case 1:
- case -1:
bfd_put_16 (abfd, val, data);
break;
case 2:
- case -2:
bfd_put_32 (abfd, val, data);
break;
@@ -632,7 +626,7 @@ apply_reloc (bfd *abfd, bfd_byte *data, reloc_howto_type *howto,
{
bfd_vma val = read_reloc (abfd, data, howto);
- if (howto->size < 0)
+ if (howto->negate)
relocation = -relocation;
val = ((val & ~howto->dst_mask)
@@ -1391,9 +1385,7 @@ _bfd_relocate_contents (reloc_howto_type *howto,
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)
+ if (howto->negate)
relocation = -relocation;
/* Get the value we are going to relocate. */