alpha_ecoff_get_relocated_section_contents buffer overflow

This is aimed at fixing holes in two alpha-ecoff relocation functions
that access section contents without first bounds checking offsets.
I've also rewritten ALPHA_R_OP_STORE handling to support writing to
the bytes near the end of the section.

	* coff-alpha.c (alpha_ecoff_get_relocated_section_contents): Don't
	bother checking ALPHA_R_LITERAL insn.  Range check before reading
	contents for ALPHA_R_GPDISP, and simplify handling.  Rewrite
	ALPHA_R_OP_STORE handling.  Correct error callback args.
	(alpha_relocate_section): Similarly.  Don't abort, report errors.
This commit is contained in:
Alan Modra
2023-12-05 16:32:34 +10:30
parent 1024d59cb2
commit db4ab410de

View File

@@ -885,24 +885,14 @@ alpha_ecoff_get_relocated_section_contents (bfd *abfd,
use. This would not be particularly difficult, but it is use. This would not be particularly difficult, but it is
not currently implemented. */ not currently implemented. */
{
unsigned long insn;
/* I believe that the LITERAL reloc will only apply to a
ldq or ldl instruction, so check my assumption. */
insn = bfd_get_32 (input_bfd, data + rel->address);
BFD_ASSERT (((insn >> 26) & 0x3f) == 0x29
|| ((insn >> 26) & 0x3f) == 0x28);
rel->addend -= gp; rel->addend -= gp;
r = bfd_perform_relocation (input_bfd, rel, data, input_section, r = bfd_perform_relocation (input_bfd, rel, data, input_section,
output_bfd, &err); output_bfd, &err);
if (r == bfd_reloc_ok && gp_undefined) if (r == bfd_reloc_ok && gp_undefined)
{ {
r = bfd_reloc_dangerous; r = bfd_reloc_dangerous;
err = err = (char *) _("GP relative relocation used"
(char *) _("GP relative relocation used when GP not defined"); " when GP not defined");
}
} }
break; break;
@@ -918,54 +908,46 @@ alpha_ecoff_get_relocated_section_contents (bfd *abfd,
current location. The second of the pair is r_size bytes current location. The second of the pair is r_size bytes
ahead; it used to be marked with an ALPHA_R_IGNORE reloc, ahead; it used to be marked with an ALPHA_R_IGNORE reloc,
but that no longer happens in OSF/1 3.2. */ but that no longer happens in OSF/1 3.2. */
if (bfd_reloc_offset_in_range (rel->howto, input_bfd, input_section,
rel->address)
&& bfd_reloc_offset_in_range (rel->howto, input_bfd, input_section,
rel->address + rel->addend))
{ {
unsigned long insn1, insn2;
bfd_vma addend;
/* Get the two instructions. */ /* Get the two instructions. */
insn1 = bfd_get_32 (input_bfd, data + rel->address); bfd_byte *p = data + rel->address;
insn2 = bfd_get_32 (input_bfd, data + rel->address + rel->addend); bfd_vma insn1 = bfd_get_32 (input_bfd, p);
bfd_vma insn2 = bfd_get_32 (input_bfd, p + rel->addend);
BFD_ASSERT (((insn1 >> 26) & 0x3f) == 0x09); /* ldah */ BFD_ASSERT (((insn1 >> 26) & 0x3f) == 0x09); /* ldah */
BFD_ASSERT (((insn2 >> 26) & 0x3f) == 0x08); /* lda */ BFD_ASSERT (((insn2 >> 26) & 0x3f) == 0x08); /* lda */
/* Get the existing addend. We must account for the sign /* Get the existing addend. We must account for the sign
extension done by lda and ldah. */ extension done by lda and ldah. */
addend = ((insn1 & 0xffff) << 16) + (insn2 & 0xffff); bfd_vma addend = (((((insn1 & 0xffff) ^ 0x8000) - 0x8000) << 16)
if (insn1 & 0x8000) + ((((insn2 & 0xffff) ^ 0x8000) - 0x8000)));
{
addend -= 0x80000000;
addend -= 0x80000000;
}
if (insn2 & 0x8000)
addend -= 0x10000;
/* The existing addend includes the different between the /* The existing addend includes the different between the
gp of the input BFD and the address in the input BFD. gp of the input BFD and the address in the input BFD.
Subtract this out. */ Subtract this out. */
addend -= (ecoff_data (input_bfd)->gp addend -= ecoff_data (input_bfd)->gp - input_section->vma;
- (input_section->vma + rel->address));
/* Now add in the final gp value, and subtract out the /* Now add in the final gp value, and subtract out the
final address. */ final address. */
addend += (gp addend += gp - (input_section->output_section->vma
- (input_section->output_section->vma + input_section->output_offset);
+ input_section->output_offset
+ rel->address));
/* Change the instructions, accounting for the sign /* Change the instructions, accounting for the sign
extension, and write them out. */ extension, and write them out. */
if (addend & 0x8000) insn1 = (insn1 & ~0xffff) | (((addend + 0x8000) >> 16) & 0xffff);
addend += 0x10000; insn2 = (insn2 & ~0xffff) | (addend & 0xffff);
insn1 = (insn1 & 0xffff0000) | ((addend >> 16) & 0xffff);
insn2 = (insn2 & 0xffff0000) | (addend & 0xffff);
bfd_put_32 (input_bfd, (bfd_vma) insn1, data + rel->address); bfd_put_32 (input_bfd, insn1, p);
bfd_put_32 (input_bfd, (bfd_vma) insn2, bfd_put_32 (input_bfd, insn2, p + rel->addend);
data + rel->address + rel->addend); }
else
r = bfd_reloc_outofrange;
rel->address += input_section->output_offset; rel->address += input_section->output_offset;
}
break; break;
case ALPHA_R_OP_PUSH: case ALPHA_R_OP_PUSH:
@@ -1007,9 +989,6 @@ alpha_ecoff_get_relocated_section_contents (bfd *abfd,
case ALPHA_R_OP_STORE: case ALPHA_R_OP_STORE:
/* Store a value from the reloc stack into a bitfield. */ /* Store a value from the reloc stack into a bitfield. */
{ {
bfd_vma val;
int offset, size;
if (relocatable) if (relocatable)
{ {
rel->address += input_section->output_offset; rel->address += input_section->output_offset;
@@ -1022,15 +1001,36 @@ alpha_ecoff_get_relocated_section_contents (bfd *abfd,
break; break;
} }
/* The offset and size for this reloc are encoded into the /* The offset and size in bits for this reloc are encoded
addend field by alpha_adjust_reloc_in. */ into the addend field by alpha_adjust_reloc_in. */
offset = (rel->addend >> 8) & 0xff; unsigned int offset = (rel->addend >> 8) & 0xff;
size = rel->addend & 0xff; unsigned int size = rel->addend & 0xff;
unsigned int startbyte = offset >> 3;
unsigned int endbyte = (offset + size + 7) >> 3;
unsigned int bytes = endbyte + 1 - startbyte;
val = bfd_get_64 (abfd, data + rel->address); if (bytes <= 8
val &=~ (((1 << size) - 1) << offset); && rel->address + startbyte + bytes >= rel->address
val |= (stack[--tos] & ((1 << size) - 1)) << offset; && (rel->address + startbyte + bytes
bfd_put_64 (abfd, val, data + rel->address); <= bfd_get_section_limit_octets (input_bfd, input_section)))
{
uint64_t val = 0;
for (int off = bytes - 1; off >= 0; --off)
val = (val << 8) | data[rel->address + startbyte + off];
offset -= startbyte << 3;
size -= startbyte << 3;
uint64_t mask = (((uint64_t) 1 << size) - 1) << offset;
val = (val & ~mask) | ((stack[--tos] << offset) & mask);
for (unsigned int off = 0; off < bytes; ++off)
{
data[rel->address + startbyte + off] = val & 0xff;
val >>= 8;
}
}
else
r = bfd_reloc_outofrange;
} }
break; break;
@@ -1149,20 +1149,20 @@ alpha_ecoff_get_relocated_section_contents (bfd *abfd,
(*link_info->callbacks->einfo) (*link_info->callbacks->einfo)
/* xgettext:c-format */ /* xgettext:c-format */
(_("%X%P: %pB(%pA): relocation \"%pR\" goes out of range\n"), (_("%X%P: %pB(%pA): relocation \"%pR\" goes out of range\n"),
abfd, input_section, rel); input_bfd, input_section, rel);
goto error_return; goto error_return;
case bfd_reloc_notsupported: case bfd_reloc_notsupported:
(*link_info->callbacks->einfo) (*link_info->callbacks->einfo)
/* xgettext:c-format */ /* xgettext:c-format */
(_("%X%P: %pB(%pA): relocation \"%pR\" is not supported\n"), (_("%X%P: %pB(%pA): relocation \"%pR\" is not supported\n"),
abfd, input_section, rel); input_bfd, input_section, rel);
goto error_return; goto error_return;
default: default:
(*link_info->callbacks->einfo) (*link_info->callbacks->einfo)
/* xgettext:c-format */ /* xgettext:c-format */
(_("%X%P: %pB(%pA): relocation \"%pR\"" (_("%X%P: %pB(%pA): relocation \"%pR\""
" returns an unrecognized value %x\n"), " returns an unrecognized value %x\n"),
abfd, input_section, rel, r); input_bfd, input_section, rel, r);
break; break;
} }
} }
@@ -1389,6 +1389,7 @@ alpha_relocate_section (bfd *output_bfd,
struct external_reloc *ext_rel; struct external_reloc *ext_rel;
struct external_reloc *ext_rel_end; struct external_reloc *ext_rel_end;
bfd_size_type amt; bfd_size_type amt;
bool ret = true;
/* We keep a table mapping the symndx found in an internal reloc to /* We keep a table mapping the symndx found in an internal reloc to
the appropriate section. This is faster than looking up the the appropriate section. This is faster than looking up the
@@ -1522,6 +1523,7 @@ alpha_relocate_section (bfd *output_bfd,
bool adjust_addrp; bool adjust_addrp;
bool gp_usedp; bool gp_usedp;
bfd_vma addend; bfd_vma addend;
bfd_reloc_status_type r;
r_vaddr = H_GET_64 (input_bfd, ext_rel->r_vaddr); r_vaddr = H_GET_64 (input_bfd, ext_rel->r_vaddr);
r_symndx = H_GET_32 (input_bfd, ext_rel->r_symndx); r_symndx = H_GET_32 (input_bfd, ext_rel->r_symndx);
@@ -1539,27 +1541,13 @@ alpha_relocate_section (bfd *output_bfd,
adjust_addrp = true; adjust_addrp = true;
gp_usedp = false; gp_usedp = false;
addend = 0; addend = 0;
r = bfd_reloc_ok;
switch (r_type) switch (r_type)
{ {
case ALPHA_R_GPRELHIGH:
_bfd_error_handler (_("%pB: %s unsupported"),
input_bfd, "ALPHA_R_GPRELHIGH");
bfd_set_error (bfd_error_bad_value);
continue;
case ALPHA_R_GPRELLOW:
_bfd_error_handler (_("%pB: %s unsupported"),
input_bfd, "ALPHA_R_GPRELLOW");
bfd_set_error (bfd_error_bad_value);
continue;
default: default:
/* xgettext:c-format */ r = bfd_reloc_notsupported;
_bfd_error_handler (_("%pB: unsupported relocation type %#x"), break;
input_bfd, (int) r_type);
bfd_set_error (bfd_error_bad_value);
continue;
case ALPHA_R_IGNORE: case ALPHA_R_IGNORE:
/* This reloc appears after a GPDISP reloc. On earlier /* This reloc appears after a GPDISP reloc. On earlier
@@ -1616,17 +1604,6 @@ alpha_relocate_section (bfd *output_bfd,
use. This would not be particularly difficult, but it is use. This would not be particularly difficult, but it is
not currently implemented. */ not currently implemented. */
/* I believe that the LITERAL reloc will only apply to a ldq
or ldl instruction, so check my assumption. */
{
unsigned long insn;
insn = bfd_get_32 (input_bfd,
contents + r_vaddr - input_section->vma);
BFD_ASSERT (((insn >> 26) & 0x3f) == 0x29
|| ((insn >> 26) & 0x3f) == 0x28);
}
relocatep = true; relocatep = true;
addend = ecoff_data (input_bfd)->gp - gp; addend = ecoff_data (input_bfd)->gp - gp;
gp_usedp = true; gp_usedp = true;
@@ -1643,58 +1620,45 @@ alpha_relocate_section (bfd *output_bfd,
current location. The second of the pair is r_symndx current location. The second of the pair is r_symndx
bytes ahead. It used to be marked with an ALPHA_R_IGNORE bytes ahead. It used to be marked with an ALPHA_R_IGNORE
reloc, but OSF/1 3.2 no longer does that. */ reloc, but OSF/1 3.2 no longer does that. */
if (r_vaddr >= input_section->vma
&& r_vaddr - input_section->vma < input_section->size
&& input_section->size - (r_vaddr - input_section->vma) > r_symndx
&& (input_section->size - (r_vaddr - input_section->vma)
- r_symndx >= 4))
{ {
unsigned long insn1, insn2;
/* Get the two instructions. */ /* Get the two instructions. */
insn1 = bfd_get_32 (input_bfd, bfd_byte *p = contents + r_vaddr - input_section->vma;
contents + r_vaddr - input_section->vma); bfd_vma insn1 = bfd_get_32 (input_bfd, p);
insn2 = bfd_get_32 (input_bfd, bfd_vma insn2 = bfd_get_32 (input_bfd, p + r_symndx);
(contents
+ r_vaddr
- input_section->vma
+ r_symndx));
BFD_ASSERT (((insn1 >> 26) & 0x3f) == 0x09); /* ldah */ BFD_ASSERT (((insn1 >> 26) & 0x3f) == 0x09); /* ldah */
BFD_ASSERT (((insn2 >> 26) & 0x3f) == 0x08); /* lda */ BFD_ASSERT (((insn2 >> 26) & 0x3f) == 0x08); /* lda */
/* Get the existing addend. We must account for the sign /* Get the existing addend. We must account for the sign
extension done by lda and ldah. */ extension done by lda and ldah. */
addend = ((insn1 & 0xffff) << 16) + (insn2 & 0xffff); addend = (((((insn1 & 0xffff) ^ 0x8000) - 0x8000) << 16)
if (insn1 & 0x8000) + (((insn2 & 0xffff) ^ 0x8000) - 0x8000));
{
/* This is addend -= 0x100000000 without causing an
integer overflow on a 32 bit host. */
addend -= 0x80000000;
addend -= 0x80000000;
}
if (insn2 & 0x8000)
addend -= 0x10000;
/* The existing addend includes the difference between the /* The existing addend includes the difference between the
gp of the input BFD and the address in the input BFD. gp of the input BFD and the address in the input BFD.
We want to change this to the difference between the We want to change this to the difference between the
final GP and the final address. */ final GP and the final address. */
addend += (gp addend -= ecoff_data (input_bfd)->gp - input_section->vma;
- ecoff_data (input_bfd)->gp addend += gp - (input_section->output_section->vma
+ input_section->vma + input_section->output_offset);
- (input_section->output_section->vma
+ input_section->output_offset));
/* Change the instructions, accounting for the sign /* Change the instructions, accounting for the sign
extension, and write them out. */ extension, and write them out. */
if (addend & 0x8000) insn1 = (insn1 & ~0xffff) | (((addend + 0x8000) >> 16) & 0xffff);
addend += 0x10000; insn2 = (insn2 & ~0xffff) | (addend & 0xffff);
insn1 = (insn1 & 0xffff0000) | ((addend >> 16) & 0xffff);
insn2 = (insn2 & 0xffff0000) | (addend & 0xffff);
bfd_put_32 (input_bfd, (bfd_vma) insn1, bfd_put_32 (input_bfd, insn1, p);
contents + r_vaddr - input_section->vma); bfd_put_32 (input_bfd, insn2, p + r_symndx);
bfd_put_32 (input_bfd, (bfd_vma) insn2,
contents + r_vaddr - input_section->vma + r_symndx);
gp_usedp = true; gp_usedp = true;
} }
else
r = bfd_reloc_outofrange;
break; break;
case ALPHA_R_OP_PUSH: case ALPHA_R_OP_PUSH:
@@ -1709,8 +1673,11 @@ alpha_relocate_section (bfd *output_bfd,
asection *s; asection *s;
s = symndx_to_section[r_symndx]; s = symndx_to_section[r_symndx];
if (s == (asection *) NULL) if (s == NULL)
abort (); {
r = bfd_reloc_notsupported;
break;
}
addend = s->output_section->vma + s->output_offset - s->vma; addend = s->output_section->vma + s->output_offset - s->vma;
} }
else else
@@ -1718,8 +1685,11 @@ alpha_relocate_section (bfd *output_bfd,
struct ecoff_link_hash_entry *h; struct ecoff_link_hash_entry *h;
h = sym_hashes[r_symndx]; h = sym_hashes[r_symndx];
if (h == (struct ecoff_link_hash_entry *) NULL) if (h == NULL)
abort (); {
r = bfd_reloc_notsupported;
break;
}
if (! bfd_link_relocatable (info)) if (! bfd_link_relocatable (info))
{ {
@@ -1773,19 +1743,28 @@ alpha_relocate_section (bfd *output_bfd,
{ {
case ALPHA_R_OP_PUSH: case ALPHA_R_OP_PUSH:
if (tos >= RELOC_STACKSIZE) if (tos >= RELOC_STACKSIZE)
abort (); {
r = bfd_reloc_notsupported;
break;
}
stack[tos++] = addend; stack[tos++] = addend;
break; break;
case ALPHA_R_OP_PSUB: case ALPHA_R_OP_PSUB:
if (tos == 0) if (tos == 0)
abort (); {
r = bfd_reloc_notsupported;
break;
}
stack[tos - 1] -= addend; stack[tos - 1] -= addend;
break; break;
case ALPHA_R_OP_PRSHIFT: case ALPHA_R_OP_PRSHIFT:
if (tos == 0) if (tos == 0)
abort (); {
r = bfd_reloc_notsupported;
break;
}
stack[tos - 1] >>= addend; stack[tos - 1] >>= addend;
break; break;
} }
@@ -1800,28 +1779,34 @@ alpha_relocate_section (bfd *output_bfd,
adjust the address of the reloc. */ adjust the address of the reloc. */
if (! bfd_link_relocatable (info)) if (! bfd_link_relocatable (info))
{ {
bfd_vma mask; unsigned int startbyte = r_offset >> 3;
bfd_vma val; unsigned int endbyte = (r_offset + r_size + 7) >> 3;
unsigned int bytes = endbyte + 1 - startbyte;
if (tos == 0) if (bytes <= 8
abort (); && r_vaddr >= input_section->vma
&& r_vaddr - input_section->vma < input_section->size
&& (input_section->size - (r_vaddr - input_section->vma)
>= startbyte + bytes))
{
bfd_byte *p = contents + (r_vaddr - input_section->vma);
uint64_t val = 0;
for (int off = bytes - 1; off >= 0; --off)
val = (val << 8) | p[startbyte + off];
/* Get the relocation mask. The separate steps and the r_offset -= startbyte << 3;
casts to bfd_vma are attempts to avoid a bug in the r_size -= startbyte << 3;
Alpha OSF 1.3 C compiler. See reloc.c for more uint64_t mask = (((uint64_t) 1 << r_size) - 1) << r_offset;
details. */ val = (val & ~mask) | ((stack[--tos] << r_offset) & mask);
mask = 1;
mask <<= (bfd_vma) r_size;
mask -= 1;
/* FIXME: I don't know what kind of overflow checking, for (unsigned int off = 0; off < bytes; ++off)
if any, should be done here. */ {
val = bfd_get_64 (input_bfd, p[startbyte + off] = val & 0xff;
contents + r_vaddr - input_section->vma); val >>= 8;
val &=~ mask << (bfd_vma) r_offset; }
val |= (stack[--tos] & mask) << (bfd_vma) r_offset; }
bfd_put_64 (input_bfd, val, else
contents + r_vaddr - input_section->vma); r = bfd_reloc_outofrange;
} }
break; break;
@@ -1832,13 +1817,12 @@ alpha_relocate_section (bfd *output_bfd,
break; break;
} }
if (relocatep) if (relocatep && r == bfd_reloc_ok)
{ {
reloc_howto_type *howto; reloc_howto_type *howto;
struct ecoff_link_hash_entry *h = NULL; struct ecoff_link_hash_entry *h = NULL;
asection *s = NULL; asection *s = NULL;
bfd_vma relocation; bfd_vma relocation;
bfd_reloc_status_type r;
/* Perform a relocation. */ /* Perform a relocation. */
@@ -1850,8 +1834,8 @@ alpha_relocate_section (bfd *output_bfd,
/* If h is NULL, that means that there is a reloc /* If h is NULL, that means that there is a reloc
against an external symbol which we thought was just against an external symbol which we thought was just
a debugging symbol. This should not happen. */ a debugging symbol. This should not happen. */
if (h == (struct ecoff_link_hash_entry *) NULL) if (h == NULL)
abort (); r = bfd_reloc_notsupported;
} }
else else
{ {
@@ -1860,11 +1844,14 @@ alpha_relocate_section (bfd *output_bfd,
else else
s = symndx_to_section[r_symndx]; s = symndx_to_section[r_symndx];
if (s == (asection *) NULL) if (s == NULL)
abort (); r = bfd_reloc_notsupported;
} }
if (bfd_link_relocatable (info)) if (r != bfd_reloc_ok)
;
else if (bfd_link_relocatable (info))
{ {
/* We are generating relocatable output, and must /* We are generating relocatable output, and must
convert the existing reloc. */ convert the existing reloc. */
@@ -1930,12 +1917,7 @@ alpha_relocate_section (bfd *output_bfd,
+ hsec->output_offset); + hsec->output_offset);
} }
else else
{ r = bfd_reloc_undefined;
(*info->callbacks->undefined_symbol)
(info, h->root.root.string, input_bfd, input_section,
r_vaddr - input_section->vma, true);
relocation = 0;
}
} }
else else
{ {
@@ -1950,6 +1932,7 @@ alpha_relocate_section (bfd *output_bfd,
relocation += input_section->vma; relocation += input_section->vma;
} }
if (r == bfd_reloc_ok)
r = _bfd_final_link_relocate (howto, r = _bfd_final_link_relocate (howto,
input_bfd, input_bfd,
input_section, input_section,
@@ -1958,30 +1941,6 @@ alpha_relocate_section (bfd *output_bfd,
relocation, relocation,
addend); addend);
} }
if (r != bfd_reloc_ok)
{
switch (r)
{
default:
case bfd_reloc_outofrange:
abort ();
case bfd_reloc_overflow:
{
const char *name;
if (r_extern)
name = sym_hashes[r_symndx]->root.root.string;
else
name = bfd_section_name (symndx_to_section[r_symndx]);
(*info->callbacks->reloc_overflow)
(info, NULL, name, alpha_howto_table[r_type].name,
(bfd_vma) 0, input_bfd, input_section,
r_vaddr - input_section->vma);
}
break;
}
}
} }
if (bfd_link_relocatable (info) && adjust_addrp) if (bfd_link_relocatable (info) && adjust_addrp)
@@ -1997,20 +1956,65 @@ alpha_relocate_section (bfd *output_bfd,
if (gp_usedp && gp_undefined) if (gp_usedp && gp_undefined)
{ {
(*info->callbacks->reloc_dangerous) r = bfd_reloc_dangerous;
(info, _("GP relative relocation used when GP not defined"),
input_bfd, input_section, r_vaddr - input_section->vma);
/* Only give the error once per link. */ /* Only give the error once per link. */
gp = 4; gp = 4;
_bfd_set_gp_value (output_bfd, gp); _bfd_set_gp_value (output_bfd, gp);
gp_undefined = false; gp_undefined = false;
} }
if (r != bfd_reloc_ok)
{
switch (r)
{
case bfd_reloc_overflow:
{
const char *name;
if (r_extern)
name = sym_hashes[r_symndx]->root.root.string;
else
name = bfd_section_name (symndx_to_section[r_symndx]);
(*info->callbacks->reloc_overflow)
(info, NULL, name, alpha_howto_table[r_type].name,
(bfd_vma) 0, input_bfd, input_section,
r_vaddr - input_section->vma);
}
break;
case bfd_reloc_outofrange:
(*info->callbacks->einfo)
/* xgettext:c-format */
(_("%X%P: %pB(%pA): relocation out of range\n"),
input_bfd, input_section);
break;
case bfd_reloc_undefined:
(*info->callbacks->undefined_symbol)
(info, sym_hashes[r_symndx]->root.root.string,
input_bfd, input_section,
r_vaddr - input_section->vma, true);
break;
case bfd_reloc_notsupported:
(*info->callbacks->einfo)
/* xgettext:c-format */
(_("%X%P: %pB(%pA): relocation is not supported\n"),
input_bfd, input_section);
break;
case bfd_reloc_dangerous:
(*info->callbacks->reloc_dangerous)
(info, _("GP relative relocation used when GP not defined"),
input_bfd, input_section, r_vaddr - input_section->vma);
break;
default:
abort ();
}
ret = false;
}
} }
if (tos != 0) if (tos != 0)
abort (); ret = false;
return true; return ret;
} }
/* Do final adjustments to the filehdr and the aouthdr. This routine /* Do final adjustments to the filehdr and the aouthdr. This routine