[AArch64] [Windows] Misc fixes for llvm-readobj -unwind.

Use getImageBase() helper to compute the image base. Fix various
offsets/addresses/masks so they're actually correct.

This allows decoding unwind info from DLLs, and unwind info from object
files containing multiple functions.

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

llvm-svn: 346036
This commit is contained in:
Eli Friedman 2018-11-02 19:59:08 +00:00
parent 66f7b435ed
commit d2941b43f4
3 changed files with 24 additions and 23 deletions

View File

@ -339,7 +339,7 @@ struct EpilogueScope {
return ((ES & 0xff000000) >> 24); return ((ES & 0xff000000) >> 24);
} }
uint8_t EpilogueStartIndexAArch64() const { uint16_t EpilogueStartIndexAArch64() const {
return ((ES & 0xffc00000) >> 22); return ((ES & 0xffc00000) >> 22);
} }
}; };
@ -428,7 +428,7 @@ struct ExceptionDataRecord {
inline size_t HeaderWords(const ExceptionDataRecord &XR) { inline size_t HeaderWords(const ExceptionDataRecord &XR) {
if (XR.isAArch64) if (XR.isAArch64)
return (XR.Data[0] & 0xffc0000) ? 1 : 2; return (XR.Data[0] & 0xffc00000) ? 1 : 2;
return (XR.Data[0] & 0xff800000) ? 1 : 2; return (XR.Data[0] & 0xff800000) ? 1 : 2;
} }
} }

View File

@ -7,6 +7,7 @@
// CHECK: Prologue [ // CHECK: Prologue [
// CHECK: 0xdf ; Bad opcode! // CHECK: 0xdf ; Bad opcode!
// CHECK: 0xff ; Bad opcode!
// CHECK: 0xd600 ; stp x19, lr, [sp, #0] // CHECK: 0xd600 ; stp x19, lr, [sp, #0]
// CHECK: 0x01 ; sub sp, #16 // CHECK: 0x01 ; sub sp, #16
// CHECK: 0xe4 ; end // CHECK: 0xe4 ; end
@ -48,6 +49,6 @@
.long 0x10800012 .long 0x10800012
.long 0x8 .long 0x8
.long 0xe .long 0xe
.long 0x100d6df .long 0x00d6ffdf
.long 0xe3e3e3e4 .long 0xe3e3e401

View File

@ -788,7 +788,7 @@ void Decoder::decodeOpcodes(ArrayRef<uint8_t> Opcodes, unsigned Offset,
if ((isAArch64 && (DI >= array_lengthof(Ring64))) || if ((isAArch64 && (DI >= array_lengthof(Ring64))) ||
(!isAArch64 && (DI >= array_lengthof(Ring)))) { (!isAArch64 && (DI >= array_lengthof(Ring)))) {
SW.startLine() << format("0x%02x ; Bad opcode!\n", SW.startLine() << format("0x%02x ; Bad opcode!\n",
Opcodes.data()[Offset]); Opcodes.data()[OI]);
++OI; ++OI;
break; break;
} }
@ -871,6 +871,8 @@ bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF,
SW.printNumber("EpilogueStartIndex", SW.printNumber("EpilogueStartIndex",
isAArch64 ? ES.EpilogueStartIndexAArch64() isAArch64 ? ES.EpilogueStartIndexAArch64()
: ES.EpilogueStartIndexARM()); : ES.EpilogueStartIndexARM());
if (ES.ES & ~0xffc3ffff)
SW.printNumber("ReservedBits", (ES.ES >> 18) & 0xF);
ListScope Opcodes(SW, "Opcodes"); ListScope Opcodes(SW, "Opcodes");
decodeOpcodes(XData.UnwindByteCode(), decodeOpcodes(XData.UnwindByteCode(),
@ -887,10 +889,15 @@ bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF,
+ (XData.E() ? 0 : XData.EpilogueCount()) + (XData.E() ? 0 : XData.EpilogueCount())
+ XData.CodeWords(); + XData.CodeWords();
ErrorOr<SymbolRef> Symbol = ErrorOr<SymbolRef> Symbol = getRelocatedSymbol(
getRelocatedSymbol(COFF, Section, HandlerOffset * sizeof(uint32_t)); COFF, Section, Offset + HandlerOffset * sizeof(uint32_t));
if (!Symbol) if (!Symbol)
Symbol = getSymbol(COFF, Address, /*FunctionOnly=*/true); Symbol = getSymbol(COFF, Address, /*FunctionOnly=*/true);
if (!Symbol) {
ListScope EHS(SW, "ExceptionHandler");
SW.printString("Routine", "(null)");
return true;
}
Expected<StringRef> Name = Symbol->getName(); Expected<StringRef> Name = Symbol->getName();
if (!Name) { if (!Name) {
@ -950,10 +957,7 @@ bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF,
} }
FunctionAddress = *FunctionAddressOrErr; FunctionAddress = *FunctionAddressOrErr;
} else { } else {
const pe32_header *PEHeader; FunctionAddress = COFF.getImageBase() + RF.BeginAddress;
if (COFF.getPE32Header(PEHeader))
return false;
FunctionAddress = PEHeader->ImageBase + RF.BeginAddress;
} }
SW.printString("Function", formatSymbol(FunctionName, FunctionAddress)); SW.printString("Function", formatSymbol(FunctionName, FunctionAddress));
@ -988,22 +992,18 @@ bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF,
} }
section_iterator SI = *SIOrErr; section_iterator SI = *SIOrErr;
return dumpXDataRecord(COFF, *SI, FunctionAddress, Address); // FIXME: Do we need to add an offset from the relocation?
return dumpXDataRecord(COFF, *SI, FunctionAddress,
RF.ExceptionInformationRVA());
} else { } else {
const pe32_header *PEHeader; uint64_t Address = COFF.getImageBase() + RF.ExceptionInformationRVA();
if (COFF.getPE32Header(PEHeader))
return false;
uint64_t Address = PEHeader->ImageBase + RF.ExceptionInformationRVA();
SW.printString("ExceptionRecord", formatSymbol("", Address)); SW.printString("ExceptionRecord", formatSymbol("", Address));
ErrorOr<SectionRef> Section = ErrorOr<SectionRef> Section = getSectionContaining(COFF, Address);
getSectionContaining(COFF, RF.ExceptionInformationRVA());
if (!Section) if (!Section)
return false; return false;
return dumpXDataRecord(COFF, *Section, FunctionAddress, return dumpXDataRecord(COFF, *Section, FunctionAddress, Address);
RF.ExceptionInformationRVA());
} }
} }
@ -1073,8 +1073,8 @@ bool Decoder::dumpProcedureDataEntry(const COFFObjectFile &COFF,
if (Entry.Flag() == RuntimeFunctionFlag::RFF_Unpacked) if (Entry.Flag() == RuntimeFunctionFlag::RFF_Unpacked)
return dumpUnpackedEntry(COFF, Section, Offset, Index, Entry); return dumpUnpackedEntry(COFF, Section, Offset, Index, Entry);
if (isAArch64) { if (isAArch64) {
llvm::errs() << "Packed unwind data not yet supported for ARM64\n"; SW.startLine() << "Packed unwind data not yet supported for ARM64\n";
return false; return true;
} }
return dumpPackedEntry(COFF, Section, Offset, Index, Entry); return dumpPackedEntry(COFF, Section, Offset, Index, Entry);
} }