From 66a277abe2b75c998a0549c7818e8c10e5f6be31 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 22 Jul 1993 18:03:51 +0000 Subject: [PATCH] * reloc.c (enum complain_overflow): New enumeration with the various flavours of overflow checking. (srtuct reloc_howto_struct): Changed complain_on_overflow field from boolean to emum complain_overflow. Removed obsolete absolute field. (HOWTO): Removed absolute argument. (bfd_perform_relocation): Do overflow checking on all types of fields. * bfd-in2.h: Updated accordingly. * all targets: Updated initialization of reloc howto tables. --- bfd/ChangeLog | 13 +++++++ bfd/bfd-in2.h | 37 ++++++++++++++----- bfd/coff-a29k.c | 21 +++++------ bfd/reloc.c | 98 +++++++++++++++++++++++++++++++++++++++---------- 4 files changed, 128 insertions(+), 41 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index a6880d65665..3395c41fa4f 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,16 @@ +Thu Jul 22 13:34:57 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * reloc.c (enum complain_overflow): New enumeration with the + various flavours of overflow checking. + (srtuct reloc_howto_struct): Changed complain_on_overflow field + from boolean to emum complain_overflow. Removed obsolete absolute + field. + (HOWTO): Removed absolute argument. + (bfd_perform_relocation): Do overflow checking on all types of + fields. + * bfd-in2.h: Updated accordingly. + * all targets: Updated initialization of reloc howto tables. + Wed Jul 21 20:34:34 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * opncls.c (bfd_create): Don't use C++ keyword "template" as a C diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 276e05128a3..720c5957a9d 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -955,6 +955,23 @@ typedef struct reloc_cache_entry CONST struct reloc_howto_struct *howto; } arelent; +enum complain_overflow +{ + /* Do not complain on overflow. */ + complain_overflow_dont, + + /* Complain if the bitfield overflows, whether it is considered + as signed or unsigned. */ + complain_overflow_bitfield, + + /* Complain if the value overflows when considered as signed + number. */ + complain_overflow_signed, + + /* Complain if the value overflows when considered as an + unsigned number. */ + complain_overflow_unsigned +}; typedef CONST struct reloc_howto_struct { @@ -975,7 +992,8 @@ typedef CONST struct reloc_howto_struct result is to be subtracted from the data. */ int size; - /* Now obsolete? But m68k-coff still uses it... */ + /* The number of bits in the item to be relocated. This is used + when doing overflow checking. */ unsigned int bitsize; /* Notes that the relocation is relative to the location in the @@ -984,14 +1002,13 @@ typedef CONST struct reloc_howto_struct being relocated. */ 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; - /* Now obsolete */ - boolean absolute; - - /* Causes the relocation routine to return an error if overflow - is detected when relocating. */ - boolean complain_on_overflow; + /* What type of overflow error should be checked for when + relocating. */ + enum complain_overflow complain_on_overflow; /* If this field is non null, then the supplied function is called rather than the normal function. This allows really @@ -1036,9 +1053,9 @@ typedef CONST struct reloc_howto_struct boolean pcrel_offset; } reloc_howto_type; -#define HOWTO(C, R,S,B, P, BI, ABS, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \ - {(unsigned)C,R,S,B, P, BI, ABS,O,SF,NAME,INPLACE,MASKSRC,MASKDST,PC} -#define NEWHOWTO( FUNCTION, NAME,SIZE,REL,IN) HOWTO(0,0,SIZE,0,REL,0,false,false,FUNCTION, NAME,false,0,0,IN) +#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 NEWHOWTO( FUNCTION, NAME,SIZE,REL,IN) HOWTO(0,0,SIZE,0,REL,0,complain_overflow_dont,FUNCTION, NAME,false,0,0,IN) #define HOWTO_PREPARE(relocation, symbol) \ { \ diff --git a/bfd/coff-a29k.c b/bfd/coff-a29k.c index e60fd40c547..01a2679c8c9 100644 --- a/bfd/coff-a29k.c +++ b/bfd/coff-a29k.c @@ -226,24 +226,21 @@ DEFUN(a29k_reloc,(abfd, reloc_entry, symbol_in, data, input_section, output_bfd) */ /*FIXME: I'm not real sure about this table */ -#define NA 0 /* Obsolete fields, via the documentation */ -#define NAB false static reloc_howto_type howto_table[] = { - {R_ABS, 0, 3, NA, false, NA, NAB, true,a29k_reloc,"ABS", true, 0xffffffff,0xffffffff, false}, + {R_ABS, 0, 3, 32, false, 0, complain_overflow_bitfield,a29k_reloc,"ABS", true, 0xffffffff,0xffffffff, false}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {12}, {13}, {14}, {15}, {16}, {17}, {18}, {19}, {20}, {21}, {22}, {23}, - {R_IREL, 0, 3, NA, true, NA, NAB, true,a29k_reloc,"IREL", true, 0xffffffff,0xffffffff, false}, - {R_IABS, 0, 3, NA, false, NA, NAB, true,a29k_reloc,"IABS", true, 0xffffffff,0xffffffff, false}, - {R_ILOHALF, 0, 3, NA, true, NA, NAB, true,a29k_reloc,"ILOHALF", true, 0x0000ffff,0x0000ffff, false}, - {R_IHIHALF, 0, 3, NA, true, NA, NAB, true,a29k_reloc,"IHIHALF", true, 0xffff0000,0xffff0000, false}, - {R_IHCONST, 0, 3, NA, true, NA, NAB, true,a29k_reloc,"IHCONST", true, 0xffff0000,0xffff0000, false}, - {R_BYTE, 0, 0, NA, false, NA, NAB, true,a29k_reloc,"BYTE", true, 0x000000ff,0x000000ff, false}, - {R_HWORD, 0, 1, NA, false, NA, NAB, true,a29k_reloc,"HWORD", true, 0x0000ffff,0x0000ffff, false}, - {R_WORD, 0, 2, NA, false, NA, NAB, true,a29k_reloc,"WORD", true, 0xffffffff,0xffffffff, false}, + {R_IREL, 0, 3, 32, true, 0, complain_overflow_signed,a29k_reloc,"IREL", true, 0xffffffff,0xffffffff, false}, + {R_IABS, 0, 3, 32, false, 0, complain_overflow_bitfield, a29k_reloc,"IABS", true, 0xffffffff,0xffffffff, false}, + {R_ILOHALF, 0, 3, 16, true, 0, complain_overflow_signed, a29k_reloc,"ILOHALF", true, 0x0000ffff,0x0000ffff, false}, + {R_IHIHALF, 0, 3, 16, true, 16, complain_overflow_signed, a29k_reloc,"IHIHALF", true, 0xffff0000,0xffff0000, false}, + {R_IHCONST, 0, 3, 16, true, 0, complain_overflow_signed, a29k_reloc,"IHCONST", true, 0xffff0000,0xffff0000, false}, + {R_BYTE, 0, 0, 8, false, 0, complain_overflow_bitfield, a29k_reloc,"BYTE", true, 0x000000ff,0x000000ff, false}, + {R_HWORD, 0, 1, 16, false, 0, complain_overflow_bitfield, a29k_reloc,"HWORD", true, 0x0000ffff,0x0000ffff, false}, + {R_WORD, 0, 2, 32, false, 0, complain_overflow_bitfield, a29k_reloc,"WORD", true, 0xffffffff,0xffffffff, false}, }; -#undef NA #define BADMAG(x) A29KBADMAG(x) diff --git a/bfd/reloc.c b/bfd/reloc.c index bfa7c855273..890cb6f3d62 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -242,6 +242,34 @@ DESCRIPTION */ +/* +SUBSUBSECTION + <> + + Indicates what sort of overflow checking should be done when + performing a relocation. + +CODE_FRAGMENT +. +.enum complain_overflow +.{ +. {* Do not complain on overflow. *} +. complain_overflow_dont, +. +. {* Complain if the bitfield overflows, whether it is considered +. as signed or unsigned. *} +. complain_overflow_bitfield, +. +. {* Complain if the value overflows when considered as signed +. number. *} +. complain_overflow_signed, +. +. {* Complain if the value overflows when considered as an +. unsigned number. *} +. complain_overflow_unsigned +.}; + +*/ /* SUBSUBSECTION @@ -272,7 +300,8 @@ CODE_FRAGMENT . result is to be subtracted from the data. *} . int size; . -. {* Now obsolete? But m68k-coff still uses it... *} +. {* The number of bits in the item to be relocated. This is used +. when doing overflow checking. *} . unsigned int bitsize; . . {* Notes that the relocation is relative to the location in the @@ -281,14 +310,13 @@ CODE_FRAGMENT . being relocated. *} . 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; . -. {* Now obsolete *} -. boolean absolute; -. -. {* Causes the relocation routine to return an error if overflow -. is detected when relocating. *} -. boolean complain_on_overflow; +. {* What type of overflow error should be checked for when +. relocating. *} +. enum complain_overflow complain_on_overflow; . . {* If this field is non null, then the supplied function is . called rather than the normal function. This allows really @@ -344,15 +372,15 @@ DESCRIPTION The HOWTO define is horrible and will go away. -.#define HOWTO(C, R,S,B, P, BI, ABS, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \ -. {(unsigned)C,R,S,B, P, BI, ABS,O,SF,NAME,INPLACE,MASKSRC,MASKDST,PC} +.#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} DESCRIPTION And will be replaced with the totally magic way. But for the moment, we are compatible, so do it this way.. -.#define NEWHOWTO( FUNCTION, NAME,SIZE,REL,IN) HOWTO(0,0,SIZE,0,REL,0,false,false,FUNCTION, NAME,false,0,0,IN) +.#define NEWHOWTO( FUNCTION, NAME,SIZE,REL,IN) HOWTO(0,0,SIZE,0,REL,0,complain_overflow_dont,FUNCTION, NAME,false,0,0,IN) . DESCRIPTION Helper routine to turn a symbol into a relocation value. @@ -548,18 +576,50 @@ DEFUN(bfd_perform_relocation,(abfd, } - if (howto->complain_on_overflow && howto->pc_relative) + /* FIXME: This overflow checking is incomplete, because the value + might have overflowed before we get here. For a correct check we + need to compute the value in a size larger than bitsize, but we + can't reasonably do that for a reloc the same size as a host + machine word. */ + switch (howto->complain_on_overflow) { - /* We can detect overflow safely here */ + case complain_overflow_dont: + break; + case complain_overflow_signed: + { + /* Assumes two's complement. */ + bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1; + bfd_signed_vma reloc_signed_min = ~ reloc_signed_max; - bfd_signed_vma reloc_max = (1 << (howto->bitsize - 1))-1; - bfd_signed_vma reloc_min = ~(reloc_max); + if ((bfd_signed_vma) relocation > reloc_signed_max + || (bfd_signed_vma) relocation < reloc_signed_min) + flag = bfd_reloc_overflow; + } + break; + case complain_overflow_unsigned: + { + /* Assumes two's complement. This expression avoids overflow + if howto->bitsize is the number of bits in bfd_vma. */ + bfd_vma reloc_unsigned_max = + (((1 << (howto->bitsize - 1)) - 1) << 1) | 1; - if ((bfd_signed_vma) relocation > reloc_max - || (bfd_signed_vma) relocation < reloc_min) - { + if ((bfd_vma) relocation > reloc_unsigned_max) flag = bfd_reloc_overflow; - } + } + break; + case complain_overflow_bitfield: + { + /* Assumes two's complement. This expression avoids overflow + if howto->bitsize is the number of bits in bfd_vma. */ + bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1; + + if (((bfd_vma) relocation &~ reloc_bits) != 0 + && ((bfd_vma) relocation &~ reloc_bits) != (-1 &~ reloc_bits)) + flag = bfd_reloc_overflow; + } + break; + default: + abort (); } /* @@ -905,7 +965,7 @@ DEFUN(bfd_reloc_type_lookup,(abfd, code), } static reloc_howto_type bfd_howto_32 = - HOWTO(0, 00,2,32,false,0,false,true,0,"VRT32", false,0xffffffff,0xffffffff,true); + HOWTO(0, 00,2,32,false,0,complain_overflow_bitfield,0,"VRT32", false,0xffffffff,0xffffffff,true); /* -- 2.30.2