diff options
author | Alan Modra <amodra@gmail.com> | 2018-08-21 11:54:29 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2018-08-21 14:59:53 +0930 |
commit | 706704c88344314646e4edcc0840cb18a9cb4c82 (patch) | |
tree | ae2cd087b3be38471edaa968d45fccaf026fa886 /bfd | |
parent | 487096bf0bd5499b1d23ecbe5fd64f9f0079c0b5 (diff) | |
download | fsf-binutils-gdb-706704c88344314646e4edcc0840cb18a9cb4c82.zip fsf-binutils-gdb-706704c88344314646e4edcc0840cb18a9cb4c82.tar.gz fsf-binutils-gdb-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')
-rw-r--r-- | bfd/ChangeLog | 27 | ||||
-rw-r--r-- | bfd/bfd-in.h | 3 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 96 | ||||
-rw-r--r-- | bfd/coff-rs6000.c | 6 | ||||
-rw-r--r-- | bfd/coff64-rs6000.c | 4 | ||||
-rw-r--r-- | bfd/cpu-ns32k.c | 11 | ||||
-rw-r--r-- | bfd/reloc.c | 110 | ||||
-rw-r--r-- | bfd/vms-alpha.c | 12 |
8 files changed, 138 insertions, 131 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index f6dfda9..b515078 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,32 @@ 2018-08-21 Alan Modra <amodra@gmail.com> + * 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. + +2018-08-21 Alan Modra <amodra@gmail.com> + * reloc.c (HOWTO): Revise comment. (NEWHOWTO, HOWTO_PREPARE): Delete. * coff-arm.c (coff_arm_reloc_type_lookup): Replace const struc diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h index f00625d..47b60bc 100644 --- a/bfd/bfd-in.h +++ b/bfd/bfd-in.h @@ -234,9 +234,6 @@ bfd_format; /* A count of carsyms (canonical archive symbols). */ typedef unsigned long symindex; -/* How to perform a relocation. */ -typedef const struct reloc_howto_struct reloc_howto_type; - #define BFD_NO_MORE_SYMBOLS ((symindex) ~0) /* General purpose part of a symbol X; diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 617f2c9..46a085f 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -241,9 +241,6 @@ bfd_format; /* A count of carsyms (canonical archive symbols). */ typedef unsigned long symindex; -/* How to perform a relocation. */ -typedef const struct reloc_howto_struct reloc_howto_type; - #define BFD_NO_MORE_SYMBOLS ((symindex) ~0) /* General purpose part of a symbol X; @@ -2535,6 +2532,7 @@ typedef enum bfd_reloc_status } bfd_reloc_status_type; +typedef const struct reloc_howto_struct reloc_howto_type; typedef struct reloc_cache_entry { @@ -2572,51 +2570,39 @@ enum complain_overflow unsigned number. */ complain_overflow_unsigned }; -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 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 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 number of bits in the field to be relocated. This is used + when doing overflow checking. */ + unsigned int bitsize:7; - /* The number of bits in the item to be relocated. This is used - when doing overflow checking. */ - unsigned int bitsize; + /* The value the final relocation is shifted right by. This drops + unwanted data from the relocation. */ + unsigned int rightshift:6; - /* The relocation is relative to the field being relocated. */ - bfd_boolean pc_relative; - - /* 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 @@ -2633,33 +2619,45 @@ struct reloc_howto_struct 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; }; -#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 } #define EMPTY_HOWTO(C) \ HOWTO ((C), 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL, \ NULL, FALSE, 0, 0, FALSE) diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c index ab282df..edff50d 100644 --- a/bfd/coff-rs6000.c +++ b/bfd/coff-rs6000.c @@ -3090,7 +3090,7 @@ xcoff_complain_overflow_bitfield_func (bfd *input_bfd, 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. */ - if (howto->bitsize + howto->rightshift + if ((unsigned) howto->bitsize + howto->rightshift == bfd_arch_bits_per_address (input_bfd)) return FALSE; @@ -3458,10 +3458,6 @@ xcoff_ppc_relocate_section (bfd *output_bfd, operation, which would be tedious, or we must do the computations in a type larger than bfd_vma, which would be inefficient. */ - if ((unsigned int) howto.complain_on_overflow - >= XCOFF_MAX_COMPLAIN_OVERFLOW) - abort (); - if (((*xcoff_complain_overflow[howto.complain_on_overflow]) (input_bfd, value_to_relocate, relocation, &howto))) { diff --git a/bfd/coff64-rs6000.c b/bfd/coff64-rs6000.c index 2135001..928a23d 100644 --- a/bfd/coff64-rs6000.c +++ b/bfd/coff64-rs6000.c @@ -1306,10 +1306,6 @@ xcoff64_ppc_relocate_section (bfd *output_bfd, operation, which would be tedious, or we must do the computations in a type larger than bfd_vma, which would be inefficient. */ - if ((unsigned int) howto.complain_on_overflow - >= XCOFF_MAX_COMPLAIN_OVERFLOW) - abort (); - if (((*xcoff_complain_overflow[howto.complain_on_overflow]) (input_bfd, value_to_relocate, relocation, &howto))) { diff --git a/bfd/cpu-ns32k.c b/bfd/cpu-ns32k.c index 2eef0ba..436cba4 100644 --- a/bfd/cpu-ns32k.c +++ b/bfd/cpu-ns32k.c @@ -501,6 +501,9 @@ do_ns32k_reloc (bfd * abfd, ----------------------- R R R R R R R R R R put into bfd_put<size>. */ + if (howto->negate) + relocation = -relocation; + #define DOIT(x) \ x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask)) @@ -531,14 +534,6 @@ do_ns32k_reloc (bfd * abfd, put_data ((bfd_vma) x, location, 4); } break; - case -2: - { - bfd_vma x = get_data (location, 4); - relocation = -relocation; - DOIT(x); - put_data ((bfd_vma) x, location, 4); - } - break; case 3: /* Do nothing. */ 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. */ diff --git a/bfd/vms-alpha.c b/bfd/vms-alpha.c index fc45260..8f22a31 100644 --- a/bfd/vms-alpha.c +++ b/bfd/vms-alpha.c @@ -4001,6 +4001,7 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED) break; case ALPHA_R_LINKAGE: + size = 16; etir_output_check (abfd, section, curr_addr, 64); _bfd_vms_output_begin_subrec (recwr, ETIR__C_STC_LP_PSB); _bfd_vms_output_long @@ -5157,6 +5158,7 @@ alpha_vms_slurp_relocs (bfd *abfd) asection *sec; struct vms_section_data_struct *vms_sec; arelent *reloc; + bfd_size_type size; /* Get section to which the relocation applies. */ if (cur_psect < 0 || cur_psect > (int)PRIV (section_count)) @@ -5237,7 +5239,11 @@ alpha_vms_slurp_relocs (bfd *abfd) reloc->address = cur_address; reloc->addend = cur_addend; - vaddr += bfd_get_reloc_size (reloc->howto); + if (reloc_code == ALPHA_R_LINKAGE) + size = 16; + else + size = bfd_get_reloc_size (reloc->howto); + vaddr += size; } cur_addend = 0; @@ -5496,8 +5502,8 @@ static reloc_howto_type alpha_howto_table[] = /* Hack. Linkage is done by linker. */ HOWTO (ALPHA_R_LINKAGE, /* Type. */ 0, /* Rightshift. */ - 8, /* Size (0 = byte, 1 = short, 2 = long). */ - 256, /* Bitsize. */ + 0, /* Size (0 = byte, 1 = short, 2 = long). */ + 0, /* Bitsize. */ FALSE, /* PC relative. */ 0, /* Bitpos. */ complain_overflow_dont,/* Complain_on_overflow. */ |