Commit 706704c8 authored by Alan Modra's avatar Alan Modra
Browse files

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 c3d8e071 adding ALPHA_R_LINKAGE and git commit
8612a388 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.
parent 487096bf
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.
......
......@@ -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;
......
......@@ -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)
......
......@@ -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)))
{
......
......@@ -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)))
{
......
......@@ -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. */
......
......@@ -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. */
......
......@@ -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. */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment