aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2023-03-07 22:21:28 +1030
committerAlan Modra <amodra@gmail.com>2023-03-08 11:24:50 +1030
commitd64c8f7181fd21f90983f8d55369f6f9a2960c43 (patch)
tree2121d1b6c59faefb19dd040ebe4eb57929782f76 /bfd
parentb9ee26d9ca29b5f598772de9f78c3da21cfa6c1b (diff)
downloadgdb-d64c8f7181fd21f90983f8d55369f6f9a2960c43.zip
gdb-d64c8f7181fd21f90983f8d55369f6f9a2960c43.tar.gz
gdb-d64c8f7181fd21f90983f8d55369f6f9a2960c43.tar.bz2
z8 and z80 coff_reloc16_extra_cases sanity checks
* reloc16.c (bfd_coff_reloc16_get_relocated_section_contents): Use size_t variables. Sanity check reloc address. Handle errors from bfd_coff_reloc16_extra_cases. * coffcode.h (_bfd_coff_reloc16_extra_cases): Return bool, take size_t* args. (dummy_reloc16_extra_cases): Adjust to suit. Don't abort. * coff-z80.c (extra_case): Sanity check reloc address. Return errors. Tidy formatting. Use bfd_signed_vma temp var to check for reloc overflow. Don't abort on unexpected reloc type, instead print an error and return false. * coff-z8k.c (extra_case): Likewise. * libcoff.h: Regenerate.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/coff-z80.c118
-rw-r--r--bfd/coff-z8k.c150
-rw-r--r--bfd/coffcode.h14
-rw-r--r--bfd/libcoff.h4
-rw-r--r--bfd/reloc16.c28
5 files changed, 182 insertions, 132 deletions
diff --git a/bfd/coff-z80.c b/bfd/coff-z80.c
index c782e32..702fe65 100644
--- a/bfd/coff-z80.c
+++ b/bfd/coff-z80.c
@@ -330,77 +330,92 @@ reloc_processing (arelent *relent,
relent->address -= section->vma;
}
-static void
+static bool
extra_case (bfd *in_abfd,
struct bfd_link_info *link_info,
struct bfd_link_order *link_order,
arelent *reloc,
bfd_byte *data,
- unsigned int *src_ptr,
- unsigned int *dst_ptr)
+ size_t *src_ptr,
+ size_t *dst_ptr)
{
asection * input_section = link_order->u.indirect.section;
- int val = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
+ bfd_size_type end = bfd_get_section_limit_octets (in_abfd, input_section);
+ bfd_size_type reloc_size = bfd_get_reloc_size (reloc->howto);
+
+ if (*src_ptr > end
+ || reloc_size > end - *src_ptr)
+ {
+ link_info->callbacks->einfo
+ /* xgettext:c-format */
+ (_("%X%P: %pB(%pA): relocation \"%pR\" goes out of range\n"),
+ in_abfd, input_section, reloc);
+ return false;
+ }
+ int val = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
switch (reloc->howto->type)
{
case R_OFF8:
if (reloc->howto->partial_inplace)
- val += (signed char)(bfd_get_8 ( in_abfd, data+*src_ptr)
- & reloc->howto->src_mask);
- if (val>127 || val<-128) /* Test for overflow. */
- (*link_info->callbacks->reloc_overflow)
+ val += (signed char) (bfd_get_8 (in_abfd, data + *src_ptr)
+ & reloc->howto->src_mask);
+ if (val > 127 || val < -128)
+ {
+ link_info->callbacks->reloc_overflow
(link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
reloc->howto->name, reloc->addend, input_section->owner,
input_section, reloc->address);
+ return false;
+ }
- bfd_put_8 (in_abfd, val, data + *dst_ptr);
- (*dst_ptr) += 1;
- (*src_ptr) += 1;
+ bfd_put_8 (in_abfd, val, data + *dst_ptr);
+ *dst_ptr += 1;
+ *src_ptr += 1;
break;
case R_BYTE3:
bfd_put_8 (in_abfd, val >> 24, data + *dst_ptr);
- (*dst_ptr) += 1;
- (*src_ptr) += 1;
+ *dst_ptr += 1;
+ *src_ptr += 1;
break;
case R_BYTE2:
bfd_put_8 (in_abfd, val >> 16, data + *dst_ptr);
- (*dst_ptr) += 1;
- (*src_ptr) += 1;
+ *dst_ptr += 1;
+ *src_ptr += 1;
break;
case R_BYTE1:
bfd_put_8 (in_abfd, val >> 8, data + *dst_ptr);
- (*dst_ptr) += 1;
- (*src_ptr) += 1;
+ *dst_ptr += 1;
+ *src_ptr += 1;
break;
case R_IMM8:
if (reloc->howto->partial_inplace)
- val += bfd_get_8 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
+ val += bfd_get_8 (in_abfd, data + *src_ptr) & reloc->howto->src_mask;
/* Fall through. */
case R_BYTE0:
bfd_put_8 (in_abfd, val, data + *dst_ptr);
- (*dst_ptr) += 1;
- (*src_ptr) += 1;
+ *dst_ptr += 1;
+ *src_ptr += 1;
break;
case R_WORD1:
bfd_put_16 (in_abfd, val >> 16, data + *dst_ptr);
- (*dst_ptr) += 2;
- (*src_ptr) += 2;
+ *dst_ptr += 2;
+ *src_ptr += 2;
break;
case R_IMM16:
if (reloc->howto->partial_inplace)
- val += bfd_get_16 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
+ val += bfd_get_16 (in_abfd, data + *src_ptr) & reloc->howto->src_mask;
/* Fall through. */
case R_WORD0:
bfd_put_16 (in_abfd, val, data + *dst_ptr);
- (*dst_ptr) += 2;
- (*src_ptr) += 2;
+ *dst_ptr += 2;
+ *src_ptr += 2;
break;
case R_IMM24:
@@ -408,53 +423,62 @@ extra_case (bfd *in_abfd,
val += (bfd_get_24 (in_abfd, data + *src_ptr)
& reloc->howto->src_mask);
bfd_put_24 (in_abfd, val, data + *dst_ptr);
- (*dst_ptr) += 3;
- (*src_ptr) += 3;
+ *dst_ptr += 3;
+ *src_ptr += 3;
break;
case R_IMM32:
if (reloc->howto->partial_inplace)
- val += bfd_get_32 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
+ val += bfd_get_32 (in_abfd, data + *src_ptr) & reloc->howto->src_mask;
bfd_put_32 (in_abfd, val, data + *dst_ptr);
- (*dst_ptr) += 4;
- (*src_ptr) += 4;
+ *dst_ptr += 4;
+ *src_ptr += 4;
break;
case R_JR:
{
- if (reloc->howto->partial_inplace)
- val += (signed char)(bfd_get_8 ( in_abfd, data+*src_ptr)
- & reloc->howto->src_mask);
+ if (reloc->howto->partial_inplace)
+ val += (signed char) (bfd_get_8 (in_abfd, data + *src_ptr)
+ & reloc->howto->src_mask);
bfd_vma dot = (*dst_ptr
+ input_section->output_offset
+ input_section->output_section->vma);
- int gap = val - dot;
+ bfd_signed_vma gap = val - dot;
if (gap >= 128 || gap < -128)
- (*link_info->callbacks->reloc_overflow)
- (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
- reloc->howto->name, reloc->addend, input_section->owner,
- input_section, reloc->address);
+ {
+ link_info->callbacks->reloc_overflow
+ (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+ reloc->howto->name, reloc->addend, input_section->owner,
+ input_section, reloc->address);
+ return false;
+ }
bfd_put_8 (in_abfd, gap, data + *dst_ptr);
- (*dst_ptr)++;
- (*src_ptr)++;
+ *dst_ptr += 1;
+ *src_ptr += 1;
break;
}
case R_IMM16BE:
if (reloc->howto->partial_inplace)
- val += (bfd_get_8 ( in_abfd, data+*src_ptr+0) * 0x100 +
- bfd_get_8 ( in_abfd, data+*src_ptr+1)) & reloc->howto->src_mask;
+ val += ((bfd_get_8 (in_abfd, data + *src_ptr + 0) * 0x100
+ + bfd_get_8 (in_abfd, data + *src_ptr + 1))
+ & reloc->howto->src_mask);
- bfd_put_8 (in_abfd, val >> 8, data + *dst_ptr+0);
- bfd_put_8 (in_abfd, val, data + *dst_ptr+1);
- (*dst_ptr) += 2;
- (*src_ptr) += 2;
+ bfd_put_8 (in_abfd, val >> 8, data + *dst_ptr + 0);
+ bfd_put_8 (in_abfd, val, data + *dst_ptr + 1);
+ *dst_ptr += 2;
+ *src_ptr += 2;
break;
default:
- abort ();
+ link_info->callbacks->einfo
+ /* xgettext:c-format */
+ (_("%X%P: %pB(%pA): relocation \"%pR\" is not supported\n"),
+ in_abfd, input_section, reloc);
+ return false;
}
+ return true;
}
static bool
diff --git a/bfd/coff-z8k.c b/bfd/coff-z8k.c
index d030056..f50e1c8 100644
--- a/bfd/coff-z8k.c
+++ b/bfd/coff-z8k.c
@@ -193,16 +193,28 @@ reloc_processing (arelent *relent,
relent->address -= section->vma;
}
-static void
+static bool
extra_case (bfd *in_abfd,
struct bfd_link_info *link_info,
struct bfd_link_order *link_order,
arelent *reloc,
bfd_byte *data,
- unsigned int *src_ptr,
- unsigned int *dst_ptr)
+ size_t *src_ptr,
+ size_t *dst_ptr)
{
asection * input_section = link_order->u.indirect.section;
+ bfd_size_type end = bfd_get_section_limit_octets (in_abfd, input_section);
+ bfd_size_type reloc_size = bfd_get_reloc_size (reloc->howto);
+
+ if (*src_ptr > end
+ || reloc_size > end - *src_ptr)
+ {
+ link_info->callbacks->einfo
+ /* xgettext:c-format */
+ (_("%X%P: %pB(%pA): relocation \"%pR\" goes out of range\n"),
+ in_abfd, input_section, reloc);
+ return false;
+ }
switch (reloc->howto->type)
{
@@ -210,8 +222,8 @@ extra_case (bfd *in_abfd,
bfd_put_8 (in_abfd,
bfd_coff_reloc16_get_value (reloc, link_info, input_section),
data + *dst_ptr);
- (*dst_ptr) += 1;
- (*src_ptr) += 1;
+ *dst_ptr += 1;
+ *src_ptr += 1;
break;
case R_IMM32:
@@ -234,27 +246,26 @@ extra_case (bfd *in_abfd,
dst = (dst & 0xffff) | ((dst & 0xff0000) << 8) | 0x80000000;
bfd_put_32 (in_abfd, dst, data + *dst_ptr);
}
- (*dst_ptr) += 4;
- (*src_ptr) += 4;
+ *dst_ptr += 4;
+ *src_ptr += 4;
break;
case R_IMM4L:
bfd_put_8 (in_abfd,
((bfd_get_8 (in_abfd, data + *dst_ptr) & 0xf0)
- | (0x0f
- & bfd_coff_reloc16_get_value (reloc, link_info,
- input_section))),
+ | (0x0f & bfd_coff_reloc16_get_value (reloc, link_info,
+ input_section))),
data + *dst_ptr);
- (*dst_ptr) += 1;
- (*src_ptr) += 1;
+ *dst_ptr += 1;
+ *src_ptr += 1;
break;
case R_IMM16:
bfd_put_16 (in_abfd,
bfd_coff_reloc16_get_value (reloc, link_info, input_section),
data + *dst_ptr);
- (*dst_ptr) += 2;
- (*src_ptr) += 2;
+ *dst_ptr += 2;
+ *src_ptr += 2;
break;
case R_JR:
@@ -264,21 +275,22 @@ extra_case (bfd *in_abfd,
bfd_vma dot = (*dst_ptr
+ input_section->output_offset
+ input_section->output_section->vma);
- int gap = dst - dot - 1; /* -1, since we're in the odd byte of the
- word and the pc's been incremented. */
-
- if (gap & 1)
- abort ();
- gap /= 2;
- if (gap > 127 || gap < -128)
- (*link_info->callbacks->reloc_overflow)
- (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
- reloc->howto->name, reloc->addend, input_section->owner,
- input_section, reloc->address);
-
- bfd_put_8 (in_abfd, gap, data + *dst_ptr);
- (*dst_ptr)++;
- (*src_ptr)++;
+ /* -1, since we're in the odd byte of the word and the pc has
+ been incremented. */
+ bfd_signed_vma gap = dst - dot - 1;
+
+ if ((gap & 1) != 0 || gap > 254 || gap < -256)
+ {
+ link_info->callbacks->reloc_overflow
+ (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+ reloc->howto->name, reloc->addend, input_section->owner,
+ input_section, reloc->address);
+ return false;
+ }
+
+ bfd_put_8 (in_abfd, gap / 2, data + *dst_ptr);
+ *dst_ptr += 1;
+ *src_ptr += 1;
break;
}
@@ -289,24 +301,23 @@ extra_case (bfd *in_abfd,
bfd_vma dot = (*dst_ptr
+ input_section->output_offset
+ input_section->output_section->vma);
- int gap = dst - dot - 1; /* -1, since we're in the odd byte of the
- word and the pc's been incremented. */
-
- if (gap & 1)
- abort ();
- gap /= 2;
+ bfd_signed_vma gap = dst - dot - 1;
- if (gap > 0 || gap < -127)
- (*link_info->callbacks->reloc_overflow)
- (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
- reloc->howto->name, reloc->addend, input_section->owner,
- input_section, reloc->address);
+ if ((gap & 1) != 0 || gap > 0 || gap < -254)
+ {
+ link_info->callbacks->reloc_overflow
+ (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+ reloc->howto->name, reloc->addend, input_section->owner,
+ input_section, reloc->address);
+ return false;
+ }
bfd_put_8 (in_abfd,
- (bfd_get_8 ( in_abfd, data + *dst_ptr) & 0x80) + (-gap & 0x7f),
+ ((bfd_get_8 (in_abfd, data + *dst_ptr) & 0x80)
+ + (-gap / 2 & 0x7f)),
data + *dst_ptr);
- (*dst_ptr)++;
- (*src_ptr)++;
+ *dst_ptr += 1;
+ *src_ptr += 1;
break;
}
@@ -317,22 +328,23 @@ extra_case (bfd *in_abfd,
bfd_vma dot = (*dst_ptr
+ input_section->output_offset
+ input_section->output_section->vma);
- int gap = dst - dot - 2;
+ bfd_signed_vma gap = dst - dot - 2;
- if (gap & 1)
- abort ();
- if (gap > 4096 || gap < -4095)
- (*link_info->callbacks->reloc_overflow)
- (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
- reloc->howto->name, reloc->addend, input_section->owner,
- input_section, reloc->address);
+ if ((gap & 1) != 0 || gap > 4096 || gap < -4095)
+ {
+ link_info->callbacks->reloc_overflow
+ (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+ reloc->howto->name, reloc->addend, input_section->owner,
+ input_section, reloc->address);
+ return false;
+ }
- gap /= 2;
bfd_put_16 (in_abfd,
- (bfd_get_16 ( in_abfd, data + *dst_ptr) & 0xf000) | (-gap & 0x0fff),
+ ((bfd_get_16 (in_abfd, data + *dst_ptr) & 0xf000)
+ | (-gap / 2 & 0x0fff)),
data + *dst_ptr);
- (*dst_ptr) += 2;
- (*src_ptr) += 2;
+ *dst_ptr += 2;
+ *src_ptr += 2;
break;
}
@@ -343,23 +355,31 @@ extra_case (bfd *in_abfd,
bfd_vma dot = (*dst_ptr
+ input_section->output_offset
+ input_section->output_section->vma);
- int gap = dst - dot - 2;
+ bfd_signed_vma gap = dst - dot - 2;
if (gap > 32767 || gap < -32768)
- (*link_info->callbacks->reloc_overflow)
- (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
- reloc->howto->name, reloc->addend, input_section->owner,
- input_section, reloc->address);
-
- bfd_put_16 (in_abfd, (bfd_vma) gap, data + *dst_ptr);
- (*dst_ptr) += 2;
- (*src_ptr) += 2;
+ {
+ link_info->callbacks->reloc_overflow
+ (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+ reloc->howto->name, reloc->addend, input_section->owner,
+ input_section, reloc->address);
+ return false;
+ }
+
+ bfd_put_16 (in_abfd, gap, data + *dst_ptr);
+ *dst_ptr += 2;
+ *src_ptr += 2;
break;
}
default:
- abort ();
+ link_info->callbacks->einfo
+ /* xgettext:c-format */
+ (_("%X%P: %pB(%pA): relocation \"%pR\" is not supported\n"),
+ in_abfd, input_section, reloc);
+ return false;
}
+ return true;
}
#define coff_reloc16_extra_cases extra_case
diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index c4f7d19..7a4c409 100644
--- a/bfd/coffcode.h
+++ b/bfd/coffcode.h
@@ -1495,9 +1495,9 @@ Special entry points for gdb to swap in coff symbol table parts:
. (bfd *, FILE *, combined_entry_type *, combined_entry_type *,
. combined_entry_type *, unsigned int);
.
-. void (*_bfd_coff_reloc16_extra_cases)
+. bool (*_bfd_coff_reloc16_extra_cases)
. (bfd *, struct bfd_link_info *, struct bfd_link_order *, arelent *,
-. bfd_byte *, unsigned int *, unsigned int *);
+. bfd_byte *, size_t *, size_t *);
.
. int (*_bfd_coff_reloc16_estimate)
. (bfd *, asection *, arelent *, unsigned int,
@@ -5331,18 +5331,16 @@ dummy_reloc16_estimate (bfd *abfd ATTRIBUTE_UNUSED,
#define coff_reloc16_extra_cases dummy_reloc16_extra_cases
-/* This works even if abort is not declared in any header file. */
-
-static void
+static bool
dummy_reloc16_extra_cases (bfd *abfd ATTRIBUTE_UNUSED,
struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
struct bfd_link_order *link_order ATTRIBUTE_UNUSED,
arelent *reloc ATTRIBUTE_UNUSED,
bfd_byte *data ATTRIBUTE_UNUSED,
- unsigned int *src_ptr ATTRIBUTE_UNUSED,
- unsigned int *dst_ptr ATTRIBUTE_UNUSED)
+ size_t *src_ptr ATTRIBUTE_UNUSED,
+ size_t *dst_ptr ATTRIBUTE_UNUSED)
{
- abort ();
+ return false;
}
#endif
diff --git a/bfd/libcoff.h b/bfd/libcoff.h
index c2c1f4a..b7a4f67 100644
--- a/bfd/libcoff.h
+++ b/bfd/libcoff.h
@@ -801,9 +801,9 @@ typedef struct
(bfd *, FILE *, combined_entry_type *, combined_entry_type *,
combined_entry_type *, unsigned int);
- void (*_bfd_coff_reloc16_extra_cases)
+ bool (*_bfd_coff_reloc16_extra_cases)
(bfd *, struct bfd_link_info *, struct bfd_link_order *, arelent *,
- bfd_byte *, unsigned int *, unsigned int *);
+ bfd_byte *, size_t *, size_t *);
int (*_bfd_coff_reloc16_estimate)
(bfd *, asection *, arelent *, unsigned int,
diff --git a/bfd/reloc16.c b/bfd/reloc16.c
index fb4c04d..3b4e483 100644
--- a/bfd/reloc16.c
+++ b/bfd/reloc16.c
@@ -292,10 +292,10 @@ bfd_coff_reloc16_get_relocated_section_contents
{
arelent **parent = reloc_vector;
arelent *reloc;
- unsigned int dst_address = 0;
- unsigned int src_address = 0;
- unsigned int run;
- unsigned int idx;
+ size_t dst_address = 0;
+ size_t src_address = 0;
+ size_t run;
+ size_t idx;
/* Find how long a run we can do. */
while (dst_address < link_order->size)
@@ -306,6 +306,15 @@ bfd_coff_reloc16_get_relocated_section_contents
/* Note that the relaxing didn't tie up the addresses in the
relocation, so we use the original address to work out the
run of non-relocated data. */
+ if (reloc->address > link_order->size
+ || reloc->address < src_address)
+ {
+ link_info->callbacks->einfo
+ /* xgettext:c-format */
+ (_("%X%P: %pB(%pA): relocation \"%pR\" goes out of range\n"),
+ input_bfd, input_section, reloc);
+ goto error_return;
+ }
run = reloc->address - src_address;
parent++;
}
@@ -319,12 +328,11 @@ bfd_coff_reloc16_get_relocated_section_contents
data[dst_address++] = data[src_address++];
/* Now do the relocation. */
- if (reloc)
- {
- bfd_coff_reloc16_extra_cases (input_bfd, link_info, link_order,
- reloc, data, &src_address,
- &dst_address);
- }
+ if (reloc
+ && !bfd_coff_reloc16_extra_cases (input_bfd, link_info,
+ link_order, reloc, data,
+ &src_address, &dst_address))
+ goto error_return;
}
}
free (reloc_vector);