Revert "[llvm-readobj] [ARMWinEH] Fix handling of relocations and symbol offsets"

This reverts commit 3778924088.

The added test fails on at least one buildbot, by printing a reversed
combination, printing "func3_xdata +0x18 (0x8)" while it's supposed to
be "func3_xdata +0x8 (0x18)", see e.g.
https://lab.llvm.org/buildbot/#/builders/107/builds/7269. Currently
no idea how that could happen, but reverting until it can be figured
out.
This commit is contained in:
Martin Storsjö 2021-04-30 00:03:40 +03:00
parent 96ec6d91e4
commit 5bf2ef9d86
4 changed files with 79 additions and 334 deletions

View File

@ -1,59 +0,0 @@
# Check that we resolve the function name properly
# RUN: yaml2obj %s -o %t.obj
# RUN: llvm-readobj --unwind %t.obj | FileCheck %s
# CHECK: Function: entry (0x140001000)
--- !COFF
OptionalHeader:
AddressOfEntryPoint: 4096
ImageBase: 5368709120
SectionAlignment: 4096
FileAlignment: 512
MajorOperatingSystemVersion: 6
MinorOperatingSystemVersion: 0
MajorImageVersion: 0
MinorImageVersion: 0
MajorSubsystemVersion: 6
MinorSubsystemVersion: 0
Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI
DLLCharacteristics: [ IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA, IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT, IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE ]
SizeOfStackReserve: 1048576
SizeOfStackCommit: 4096
SizeOfHeapReserve: 1048576
SizeOfHeapCommit: 4096
header:
Machine: IMAGE_FILE_MACHINE_ARM64
Characteristics: [ IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LARGE_ADDRESS_AWARE ]
sections:
- Name: .text
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
VirtualAddress: 4096
VirtualSize: 20
SectionData: FD7BBFA9FD0300911F2003D5FD7BC1A8C0035FD6
- Name: .pdata
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
VirtualAddress: 8192
VirtualSize: 8
SectionData: '001000001500E000'
symbols:
- Name: .text
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
- Name: .pdata
Value: 0
SectionNumber: 2
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
- Name: entry
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
...

View File

@ -1,196 +0,0 @@
# Test reading an ExceptionRecord which is referenced in different ways:
# - Relocation against base of .xdata record, immediate offset in .pdata
# (what LLVM produces)
# - Relocation against symbol in .xdata, no immediate offset in .pdata
# (what MSVC produces)
# - Combination of the two above (unlikely to occur in the wild, but for
# testing the consistency of the code)
# RUN: yaml2obj %s -o %t.obj
# RUN: llvm-readobj --unwind %t.obj | FileCheck %s
# CHECK: UnwindInformation [
# CHECK-NEXT: RuntimeFunction {
# CHECK-NEXT: Function: func (0x0)
# CHECK-NEXT: ExceptionRecord: .xdata (0x0)
# CHECK-NEXT: ExceptionData {
# CHECK-NEXT: FunctionLength: 4
# CHECK-NEXT: Version: 0
# CHECK-NEXT: ExceptionData: No
# CHECK-NEXT: EpiloguePacked: No
# CHECK-NEXT: EpilogueScopes: 0
# CHECK-NEXT: ByteCodeLength: 4
# CHECK-NEXT: Prologue [
# CHECK-NEXT: 0xd400 ; str x19, [sp, #-8]!
# CHECK-NEXT: 0xe4 ; end
# CHECK-NEXT: ]
# CHECK-NEXT: EpilogueScopes [
# CHECK-NEXT: ]
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: RuntimeFunction {
# CHECK-NEXT: Function: func2 (0x4)
# CHECK-NEXT: ExceptionRecord: .xdata +0x8 (0x8)
# CHECK-NEXT: ExceptionData {
# CHECK-NEXT: FunctionLength: 4
# CHECK-NEXT: Version: 0
# CHECK-NEXT: ExceptionData: No
# CHECK-NEXT: EpiloguePacked: No
# CHECK-NEXT: EpilogueScopes: 0
# CHECK-NEXT: ByteCodeLength: 4
# CHECK-NEXT: Prologue [
# CHECK-NEXT: 0xdc01 ; str d8, [sp, #8]
# CHECK-NEXT: 0xe4 ; end
# CHECK-NEXT: ]
# CHECK-NEXT: EpilogueScopes [
# CHECK-NEXT: ]
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: RuntimeFunction {
# CHECK-NEXT: Function: func3 (0x8)
# CHECK-NEXT: ExceptionRecord: func3_xdata (0x10)
# CHECK-NEXT: ExceptionData {
# CHECK-NEXT: FunctionLength: 4
# CHECK-NEXT: Version: 0
# CHECK-NEXT: ExceptionData: No
# CHECK-NEXT: EpiloguePacked: No
# CHECK-NEXT: EpilogueScopes: 0
# CHECK-NEXT: ByteCodeLength: 4
# CHECK-NEXT: Prologue [
# CHECK-NEXT: 0xe1 ; mov fp, sp
# CHECK-NEXT: 0xe4 ; end
# CHECK-NEXT: ]
# CHECK-NEXT: EpilogueScopes [
# CHECK-NEXT: ]
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: RuntimeFunction {
# CHECK-NEXT: Function: func4 (0xC)
# CHECK-NEXT: ExceptionRecord: func3_xdata +0x8 (0x18)
# CHECK-NEXT: ExceptionData {
# CHECK-NEXT: FunctionLength: 4
# CHECK-NEXT: Version: 0
# CHECK-NEXT: ExceptionData: No
# CHECK-NEXT: EpiloguePacked: No
# CHECK-NEXT: EpilogueScopes: 0
# CHECK-NEXT: ByteCodeLength: 4
# CHECK-NEXT: Prologue [
# CHECK-NEXT: 0x81 ; stp x29, x30, [sp, #-16]!
# CHECK-NEXT: 0xe4 ; end
# CHECK-NEXT: ]
# CHECK-NEXT: EpilogueScopes [
# CHECK-NEXT: ]
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: ]
--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_ARM64
Characteristics: [ ]
sections:
- Name: .text
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
Alignment: 4
SectionData: F38F1FF8E80700FDFD030091FD7BBFA9
- Name: .xdata
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
Alignment: 4
SectionData: 01000008D400E4E301000008DC01E4E301000008E1E4E3E30100000881E4E3E3
- Name: .pdata
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
Alignment: 4
SectionData: '0000000000000000000000000800000000000000000000000000000008000000'
Relocations:
- VirtualAddress: 0
SymbolName: func
Type: IMAGE_REL_ARM64_ADDR32NB
- VirtualAddress: 4
SymbolName: .xdata
Type: IMAGE_REL_ARM64_ADDR32NB
- VirtualAddress: 8
SymbolName: func2
Type: IMAGE_REL_ARM64_ADDR32NB
- VirtualAddress: 12
SymbolName: .xdata
Type: IMAGE_REL_ARM64_ADDR32NB
- VirtualAddress: 16
SymbolName: func3
Type: IMAGE_REL_ARM64_ADDR32NB
- VirtualAddress: 20
SymbolName: func3_xdata
Type: IMAGE_REL_ARM64_ADDR32NB
- VirtualAddress: 24
SymbolName: func4
Type: IMAGE_REL_ARM64_ADDR32NB
- VirtualAddress: 28
SymbolName: func3_xdata
Type: IMAGE_REL_ARM64_ADDR32NB
symbols:
- Name: .text
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 16
NumberOfRelocations: 0
NumberOfLinenumbers: 0
CheckSum: 2581817939
Number: 1
- Name: .xdata
Value: 0
SectionNumber: 2
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 32
NumberOfRelocations: 0
NumberOfLinenumbers: 0
CheckSum: 3086971960
Number: 2
- Name: .pdata
Value: 0
SectionNumber: 3
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 32
NumberOfRelocations: 8
NumberOfLinenumbers: 0
CheckSum: 0
Number: 3
- Name: func
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
- Name: func2
Value: 4
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
- Name: func3
Value: 8
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
- Name: func4
Value: 12
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
- Name: func3_xdata
Value: 16
SectionNumber: 2
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
...

View File

@ -238,41 +238,6 @@ ErrorOr<SymbolRef> Decoder::getRelocatedSymbol(const COFFObjectFile &,
return inconvertibleErrorCode();
}
ErrorOr<SymbolRef> Decoder::getSymbolForLocation(
const COFFObjectFile &COFF, const SectionRef &Section,
uint64_t OffsetInSection, uint64_t ImmediateOffset, uint64_t &SymbolAddress,
uint64_t &SymbolOffset, bool FunctionOnly) {
// Try to locate a relocation that points at the offset in the section
ErrorOr<SymbolRef> SymOrErr =
getRelocatedSymbol(COFF, Section, OffsetInSection);
if (SymOrErr) {
// We found a relocation symbol; the immediate offset needs to be added
// to the symbol address.
SymbolOffset = ImmediateOffset;
Expected<uint64_t> AddressOrErr = SymOrErr->getAddress();
if (!AddressOrErr) {
std::string Buf;
llvm::raw_string_ostream OS(Buf);
logAllUnhandledErrors(AddressOrErr.takeError(), OS);
OS.flush();
report_fatal_error(Buf);
}
// We apply SymbolOffset here directly. We return it separately to allow
// the caller to print it as an offset on the symbol name.
SymbolAddress = *AddressOrErr + SymbolOffset;
} else {
// No matching relocation found; operating on a linked image. Try to
// find a descriptive symbol if possible. The immediate offset contains
// the image relative address, and we shouldn't add any offset to the
// symbol.
SymbolAddress = COFF.getImageBase() + ImmediateOffset;
SymbolOffset = 0;
SymOrErr = getSymbol(COFF, SymbolAddress, FunctionOnly);
}
return SymOrErr;
}
bool Decoder::opcode_0xxxxxxx(const uint8_t *OC, unsigned &Offset,
unsigned Length, bool Prologue) {
uint8_t Imm = OC[Offset] & 0x7f;
@ -954,16 +919,16 @@ bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF,
}
if (XData.X()) {
const uint64_t Address = COFF.getImageBase() + XData.ExceptionHandlerRVA();
const uint32_t Parameter = XData.ExceptionHandlerParameter();
const size_t HandlerOffset = HeaderWords(XData) +
(XData.E() ? 0 : XData.EpilogueCount()) +
XData.CodeWords();
const size_t HandlerOffset = HeaderWords(XData)
+ (XData.E() ? 0 : XData.EpilogueCount())
+ XData.CodeWords();
uint64_t Address, SymbolOffset;
ErrorOr<SymbolRef> Symbol = getSymbolForLocation(
COFF, Section, Offset + HandlerOffset * sizeof(uint32_t),
XData.ExceptionHandlerRVA(), Address, SymbolOffset,
/*FunctionOnly=*/true);
ErrorOr<SymbolRef> Symbol = getRelocatedSymbol(
COFF, Section, Offset + HandlerOffset * sizeof(uint32_t));
if (!Symbol)
Symbol = getSymbol(COFF, Address, /*FunctionOnly=*/true);
if (!Symbol) {
ListScope EHS(SW, "ExceptionHandler");
SW.printHex("Routine", Address);
@ -981,7 +946,7 @@ bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF,
}
ListScope EHS(SW, "ExceptionHandler");
SW.printString("Routine", formatSymbol(*Name, Address, SymbolOffset));
SW.printString("Routine", formatSymbol(*Name, Address));
SW.printHex("Parameter", Parameter);
}
@ -994,15 +959,14 @@ bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF,
assert(RF.Flag() == RuntimeFunctionFlag::RFF_Unpacked &&
"packed entry cannot be treated as an unpacked entry");
uint64_t FunctionAddress, FunctionOffset;
ErrorOr<SymbolRef> Function = getSymbolForLocation(
COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset,
/*FunctionOnly=*/true);
ErrorOr<SymbolRef> Function = getRelocatedSymbol(COFF, Section, Offset);
if (!Function)
Function = getSymbol(COFF, COFF.getImageBase() + RF.BeginAddress,
/*FunctionOnly=*/true);
uint64_t XDataAddress, XDataOffset;
ErrorOr<SymbolRef> XDataRecord = getSymbolForLocation(
COFF, Section, Offset + 4, RF.ExceptionInformationRVA(), XDataAddress,
XDataOffset);
ErrorOr<SymbolRef> XDataRecord = getRelocatedSymbol(COFF, Section, Offset + 4);
if (!XDataRecord)
XDataRecord = getSymbol(COFF, RF.ExceptionInformationRVA());
if (!RF.BeginAddress && !Function)
return false;
@ -1010,6 +974,7 @@ bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF,
return false;
StringRef FunctionName;
uint64_t FunctionAddress;
if (Function) {
Expected<StringRef> FunctionNameOrErr = Function->getName();
if (!FunctionNameOrErr) {
@ -1020,10 +985,20 @@ bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF,
report_fatal_error(Buf);
}
FunctionName = *FunctionNameOrErr;
Expected<uint64_t> FunctionAddressOrErr = Function->getAddress();
if (!FunctionAddressOrErr) {
std::string Buf;
llvm::raw_string_ostream OS(Buf);
logAllUnhandledErrors(FunctionAddressOrErr.takeError(), OS);
OS.flush();
report_fatal_error(Buf);
}
FunctionAddress = *FunctionAddressOrErr;
} else {
FunctionAddress = COFF.getImageBase() + RF.BeginAddress;
}
SW.printString("Function",
formatSymbol(FunctionName, FunctionAddress, FunctionOffset));
SW.printString("Function", formatSymbol(FunctionName, FunctionAddress));
if (XDataRecord) {
Expected<StringRef> Name = XDataRecord->getName();
@ -1035,8 +1010,17 @@ bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF,
report_fatal_error(Buf);
}
SW.printString("ExceptionRecord",
formatSymbol(*Name, XDataAddress, XDataOffset));
Expected<uint64_t> AddressOrErr = XDataRecord->getAddress();
if (!AddressOrErr) {
std::string Buf;
llvm::raw_string_ostream OS(Buf);
logAllUnhandledErrors(AddressOrErr.takeError(), OS);
OS.flush();
report_fatal_error(Buf);
}
uint64_t Address = *AddressOrErr;
SW.printString("ExceptionRecord", formatSymbol(*Name, Address));
Expected<section_iterator> SIOrErr = XDataRecord->getSection();
if (!SIOrErr) {
@ -1046,15 +1030,18 @@ bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF,
}
section_iterator SI = *SIOrErr;
return dumpXDataRecord(COFF, *SI, FunctionAddress, XDataAddress);
// FIXME: Do we need to add an offset from the relocation?
return dumpXDataRecord(COFF, *SI, FunctionAddress,
RF.ExceptionInformationRVA());
} else {
SW.printString("ExceptionRecord", formatSymbol("", XDataAddress));
uint64_t Address = COFF.getImageBase() + RF.ExceptionInformationRVA();
SW.printString("ExceptionRecord", formatSymbol("", Address));
ErrorOr<SectionRef> Section = getSectionContaining(COFF, XDataAddress);
ErrorOr<SectionRef> Section = getSectionContaining(COFF, Address);
if (!Section)
return false;
return dumpXDataRecord(COFF, *Section, FunctionAddress, XDataAddress);
return dumpXDataRecord(COFF, *Section, FunctionAddress, Address);
}
}
@ -1065,12 +1052,12 @@ bool Decoder::dumpPackedEntry(const object::COFFObjectFile &COFF,
RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
"unpacked entry cannot be treated as a packed entry");
uint64_t FunctionAddress, FunctionOffset;
ErrorOr<SymbolRef> Function = getSymbolForLocation(
COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset,
/*FunctionOnly=*/true);
ErrorOr<SymbolRef> Function = getRelocatedSymbol(COFF, Section, Offset);
if (!Function)
Function = getSymbol(COFF, RF.BeginAddress, /*FunctionOnly=*/true);
StringRef FunctionName;
uint64_t FunctionAddress;
if (Function) {
Expected<StringRef> FunctionNameOrErr = Function->getName();
if (!FunctionNameOrErr) {
@ -1081,10 +1068,20 @@ bool Decoder::dumpPackedEntry(const object::COFFObjectFile &COFF,
report_fatal_error(Buf);
}
FunctionName = *FunctionNameOrErr;
Expected<uint64_t> FunctionAddressOrErr = Function->getAddress();
if (!FunctionAddressOrErr) {
std::string Buf;
llvm::raw_string_ostream OS(Buf);
logAllUnhandledErrors(FunctionAddressOrErr.takeError(), OS);
OS.flush();
report_fatal_error(Buf);
}
FunctionAddress = *FunctionAddressOrErr;
} else {
FunctionAddress = COFF.getPE32Header()->ImageBase + RF.BeginAddress;
}
SW.printString("Function",
formatSymbol(FunctionName, FunctionAddress, FunctionOffset));
SW.printString("Function", formatSymbol(FunctionName, FunctionAddress));
if (!isAArch64)
SW.printBoolean("Fragment",
RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment);
@ -1107,12 +1104,12 @@ bool Decoder::dumpPackedARM64Entry(const object::COFFObjectFile &COFF,
RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
"unpacked entry cannot be treated as a packed entry");
uint64_t FunctionAddress, FunctionOffset;
ErrorOr<SymbolRef> Function = getSymbolForLocation(
COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset,
/*FunctionOnly=*/true);
ErrorOr<SymbolRef> Function = getRelocatedSymbol(COFF, Section, Offset);
if (!Function)
Function = getSymbol(COFF, RF.BeginAddress, /*FunctionOnly=*/true);
StringRef FunctionName;
uint64_t FunctionAddress;
if (Function) {
Expected<StringRef> FunctionNameOrErr = Function->getName();
if (!FunctionNameOrErr) {
@ -1123,10 +1120,20 @@ bool Decoder::dumpPackedARM64Entry(const object::COFFObjectFile &COFF,
report_fatal_error(Buf);
}
FunctionName = *FunctionNameOrErr;
Expected<uint64_t> FunctionAddressOrErr = Function->getAddress();
if (!FunctionAddressOrErr) {
std::string Buf;
llvm::raw_string_ostream OS(Buf);
logAllUnhandledErrors(FunctionAddressOrErr.takeError(), OS);
OS.flush();
report_fatal_error(Buf);
}
FunctionAddress = *FunctionAddressOrErr;
} else {
FunctionAddress = COFF.getPE32PlusHeader()->ImageBase + RF.BeginAddress;
}
SW.printString("Function",
formatSymbol(FunctionName, FunctionAddress, FunctionOffset));
SW.printString("Function", formatSymbol(FunctionName, FunctionAddress));
SW.printBoolean("Fragment",
RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment);
SW.printNumber("FunctionLength", RF.FunctionLength());

View File

@ -146,13 +146,6 @@ class Decoder {
getRelocatedSymbol(const object::COFFObjectFile &COFF,
const object::SectionRef &Section, uint64_t Offset);
ErrorOr<object::SymbolRef>
getSymbolForLocation(const object::COFFObjectFile &COFF,
const object::SectionRef &Section,
uint64_t OffsetInSection, uint64_t ImmediateOffset,
uint64_t &SymbolAddress, uint64_t &SymbolOffset,
bool FunctionOnly = false);
bool dumpXDataRecord(const object::COFFObjectFile &COFF,
const object::SectionRef &Section,
uint64_t FunctionAddress, uint64_t VA);