This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Pack reloc_howto_struct
- From: Alan Modra <amodra at gmail dot com>
- To: binutils at sourceware dot org
- Cc: Tristan Gingold <tgingold at free dot fr>
- Date: Tue, 21 Aug 2018 15:55:55 +0930
- Subject: 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.
Tristan, you might like to check whether 16 bytes is correct. The old
bitsize of 256 (which is unused) seems to disagree.
* 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.
diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index f00625d832..47b60bcfbf 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/coff-rs6000.c b/bfd/coff-rs6000.c
index ab282dfef0..edff50daaa 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 2135001f19..928a23d4f8 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 2eef0ba7bb..436cba4c41 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 ec58a7e4af..0dcf2be9a0 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 fc45260e49..8f22a31ae5 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. */
--
Alan Modra
Australia Development Lab, IBM