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