[Sparc] Avoid writing outside array in applyFixup

Summary: If an object file ends with a relocation that is smaller
than 4 bytes we will write outside the Data array and trigger an
"Invalid index" assertion.

Reviewers: jyknight, venkatra

Reviewed By: jyknight

Subscribers: fedor.sergeev, jrtc27, llvm-commits

Differential Revision: https://reviews.llvm.org/D50971

llvm-svn: 340736
This commit is contained in:
Daniel Cederman 2018-08-27 11:43:59 +00:00
parent 1742a1577a
commit 2a1a77b7bb
2 changed files with 23 additions and 3 deletions

View File

@ -100,6 +100,20 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
}
}
/// getFixupKindNumBytes - The number of bytes the fixup may change.
static unsigned getFixupKindNumBytes(unsigned Kind) {
switch (Kind) {
default:
return 4;
case FK_Data_1:
return 1;
case FK_Data_2:
return 2;
case FK_Data_8:
return 8;
}
}
namespace {
class SparcAsmBackend : public MCAsmBackend {
protected:
@ -290,13 +304,13 @@ namespace {
Value = adjustFixupValue(Fixup.getKind(), Value);
if (!Value) return; // Doesn't change encoding.
unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
unsigned Offset = Fixup.getOffset();
// For each byte of the fragment that the fixup touches, mask in the bits
// from the fixup value. The Value has been "split up" into the
// appropriate bitfields above.
for (unsigned i = 0; i != 4; ++i) {
unsigned Idx = Endian == support::little ? i : 3 - i;
for (unsigned i = 0; i != NumBytes; ++i) {
unsigned Idx = Endian == support::little ? i : (NumBytes - 1) - i;
Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
}
}

View File

@ -49,3 +49,9 @@
! CHECK: or %g1, sym, %g3 ! encoding: [0x86,0x10,0b011AAAAA,A]
! CHECK-NEXT: ! fixup A - offset: 0, value: sym, kind: fixup_sparc_13
or %g1, sym, %g3
! This test needs to placed last in the file
! CHECK: .half a-.Ltmp0
.half a - .
.byte a - .
a: