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,25 +885,15 @@ 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. */
{ rel->addend -= gp;
unsigned long insn; r = bfd_perform_relocation (input_bfd, rel, data, input_section,
output_bfd, &err);
/* I believe that the LITERAL reloc will only apply to a if (r == bfd_reloc_ok && gp_undefined)
ldq or ldl instruction, so check my assumption. */ {
insn = bfd_get_32 (input_bfd, data + rel->address); r = bfd_reloc_dangerous;
BFD_ASSERT (((insn >> 26) & 0x3f) == 0x29 err = (char *) _("GP relative relocation used"
|| ((insn >> 26) & 0x3f) == 0x28); " when GP not defined");
}
rel->addend -= gp;
r = bfd_perform_relocation (input_bfd, rel, data, input_section,
output_bfd, &err);
if (r == bfd_reloc_ok && gp_undefined)
{
r = bfd_reloc_dangerous;
err =
(char *) _("GP relative relocation used when GP not defined");
}
}
break; break;
case ALPHA_R_LITUSE: case ALPHA_R_LITUSE:
@@ -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,
unsigned long insn1, insn2; rel->address)
bfd_vma addend; && bfd_reloc_offset_in_range (rel->howto, input_bfd, input_section,
rel->address + rel->addend))
{
/* Get the two instructions. */
bfd_byte *p = data + rel->address;
bfd_vma insn1 = bfd_get_32 (input_bfd, p);
bfd_vma insn2 = bfd_get_32 (input_bfd, p + rel->addend);
/* Get the two instructions. */ BFD_ASSERT (((insn1 >> 26) & 0x3f) == 0x09); /* ldah */
insn1 = bfd_get_32 (input_bfd, data + rel->address); BFD_ASSERT (((insn2 >> 26) & 0x3f) == 0x08); /* lda */
insn2 = bfd_get_32 (input_bfd, data + rel->address + rel->addend);
BFD_ASSERT (((insn1 >> 26) & 0x3f) == 0x09); /* ldah */ /* Get the existing addend. We must account for the sign
BFD_ASSERT (((insn2 >> 26) & 0x3f) == 0x08); /* lda */ extension done by lda and ldah. */
bfd_vma addend = (((((insn1 & 0xffff) ^ 0x8000) - 0x8000) << 16)
+ ((((insn2 & 0xffff) ^ 0x8000) - 0x8000)));
/* Get the existing addend. We must account for the sign /* The existing addend includes the different between the
extension done by lda and ldah. */ gp of the input BFD and the address in the input BFD.
addend = ((insn1 & 0xffff) << 16) + (insn2 & 0xffff); Subtract this out. */
if (insn1 & 0x8000) addend -= ecoff_data (input_bfd)->gp - input_section->vma;
{
addend -= 0x80000000;
addend -= 0x80000000;
}
if (insn2 & 0x8000)
addend -= 0x10000;
/* The existing addend includes the different between the /* Now add in the final gp value, and subtract out the
gp of the input BFD and the address in the input BFD. final address. */
Subtract this out. */ addend += gp - (input_section->output_section->vma
addend -= (ecoff_data (input_bfd)->gp + input_section->output_offset);
- (input_section->vma + rel->address));
/* Now add in the final gp value, and subtract out the /* Change the instructions, accounting for the sign
final address. */ extension, and write them out. */
addend += (gp insn1 = (insn1 & ~0xffff) | (((addend + 0x8000) >> 16) & 0xffff);
- (input_section->output_section->vma insn2 = (insn2 & ~0xffff) | (addend & 0xffff);
+ input_section->output_offset
+ rel->address));
/* Change the instructions, accounting for the sign bfd_put_32 (input_bfd, insn1, p);
extension, and write them out. */ bfd_put_32 (input_bfd, insn2, p + rel->addend);
if (addend & 0x8000) }
addend += 0x10000; else
insn1 = (insn1 & 0xffff0000) | ((addend >> 16) & 0xffff); r = bfd_reloc_outofrange;
insn2 = (insn2 & 0xffff0000) | (addend & 0xffff);
bfd_put_32 (input_bfd, (bfd_vma) insn1, data + rel->address); rel->address += input_section->output_offset;
bfd_put_32 (input_bfd, (bfd_vma) insn2,
data + rel->address + rel->addend);
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
unsigned long insn1, insn2; && 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))
{
/* Get the two instructions. */
bfd_byte *p = contents + r_vaddr - input_section->vma;
bfd_vma insn1 = bfd_get_32 (input_bfd, p);
bfd_vma insn2 = bfd_get_32 (input_bfd, p + r_symndx);
/* Get the two instructions. */ BFD_ASSERT (((insn1 >> 26) & 0x3f) == 0x09); /* ldah */
insn1 = bfd_get_32 (input_bfd, BFD_ASSERT (((insn2 >> 26) & 0x3f) == 0x08); /* lda */
contents + r_vaddr - input_section->vma);
insn2 = bfd_get_32 (input_bfd,
(contents
+ r_vaddr
- input_section->vma
+ r_symndx));
BFD_ASSERT (((insn1 >> 26) & 0x3f) == 0x09); /* ldah */ /* Get the existing addend. We must account for the sign
BFD_ASSERT (((insn2 >> 26) & 0x3f) == 0x08); /* lda */ extension done by lda and ldah. */
addend = (((((insn1 & 0xffff) ^ 0x8000) - 0x8000) << 16)
+ (((insn2 & 0xffff) ^ 0x8000) - 0x8000));
/* Get the existing addend. We must account for the sign /* The existing addend includes the difference between the
extension done by lda and ldah. */ gp of the input BFD and the address in the input BFD.
addend = ((insn1 & 0xffff) << 16) + (insn2 & 0xffff); We want to change this to the difference between the
if (insn1 & 0x8000) final GP and the final address. */
{ addend -= ecoff_data (input_bfd)->gp - input_section->vma;
/* This is addend -= 0x100000000 without causing an addend += gp - (input_section->output_section->vma
integer overflow on a 32 bit host. */ + input_section->output_offset);
addend -= 0x80000000;
addend -= 0x80000000;
}
if (insn2 & 0x8000)
addend -= 0x10000;
/* The existing addend includes the difference between the /* Change the instructions, accounting for the sign
gp of the input BFD and the address in the input BFD. extension, and write them out. */
We want to change this to the difference between the insn1 = (insn1 & ~0xffff) | (((addend + 0x8000) >> 16) & 0xffff);
final GP and the final address. */ insn2 = (insn2 & ~0xffff) | (addend & 0xffff);
addend += (gp
- ecoff_data (input_bfd)->gp
+ input_section->vma
- (input_section->output_section->vma
+ input_section->output_offset));
/* Change the instructions, accounting for the sign bfd_put_32 (input_bfd, insn1, p);
extension, and write them out. */ bfd_put_32 (input_bfd, insn2, p + r_symndx);
if (addend & 0x8000)
addend += 0x10000;
insn1 = (insn1 & 0xffff0000) | ((addend >> 16) & 0xffff);
insn2 = (insn2 & 0xffff0000) | (addend & 0xffff);
bfd_put_32 (input_bfd, (bfd_vma) insn1, gp_usedp = true;
contents + r_vaddr - input_section->vma); }
bfd_put_32 (input_bfd, (bfd_vma) insn2, else
contents + r_vaddr - input_section->vma + r_symndx); r = bfd_reloc_outofrange;
gp_usedp = true;
}
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,37 +1932,14 @@ alpha_relocate_section (bfd *output_bfd,
relocation += input_section->vma; relocation += input_section->vma;
} }
r = _bfd_final_link_relocate (howto, if (r == bfd_reloc_ok)
input_bfd, r = _bfd_final_link_relocate (howto,
input_section, input_bfd,
contents, input_section,
r_vaddr - input_section->vma, contents,
relocation, r_vaddr - input_section->vma,
addend); relocation,
} 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;
}
} }
} }
@@ -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