diff --git a/llvm/test/tools/llvm-readobj/COFF/arm64-unwind-preferred-symbol2.yaml b/llvm/test/tools/llvm-readobj/COFF/arm64-unwind-preferred-symbol2.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/COFF/arm64-unwind-preferred-symbol2.yaml @@ -0,0 +1,99 @@ +## Check that we print the external symbol "func1" and "func2", even though +## the pdata relocations point at .text with an immediate offset. + +# RUN: yaml2obj %s -o %t.obj +# RUN: llvm-readobj --unwind %t.obj | FileCheck %s + +# CHECK: Function: func1 (0x0) +# CHECK: Function: func2 (0x14) + +--- !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: FE0F1FF8E133009100000094FE0741F8C0035FD6FF8300D1F60B00F9FE0F00F9E1330091E0031FAA00000094FE0F40F9F60B40F9FF830091C0035FD6 + Relocations: + - VirtualAddress: 8 + SymbolName: other + Type: IMAGE_REL_ARM64_BRANCH26 + - VirtualAddress: 40 + SymbolName: other + Type: IMAGE_REL_ARM64_BRANCH26 + - Name: .xdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: 0A002010D2C3D0C202E4E3E3 + - Name: .pdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: 000000001500A0001400000000000000 + Relocations: + - VirtualAddress: 0 + SymbolName: .text + Type: IMAGE_REL_ARM64_ADDR32NB + - VirtualAddress: 8 + SymbolName: .text + Type: IMAGE_REL_ARM64_ADDR32NB + - VirtualAddress: 12 + SymbolName: .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: 60 + NumberOfRelocations: 2 + NumberOfLinenumbers: 0 + CheckSum: 2313530660 + 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: 12 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 2034129209 + 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: 16 + NumberOfRelocations: 3 + NumberOfLinenumbers: 0 + CheckSum: 3306336236 + Number: 3 + - Name: func1 + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: other + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: func2 + Value: 20 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/llvm/tools/llvm-readobj/ARMWinEHPrinter.h b/llvm/tools/llvm-readobj/ARMWinEHPrinter.h --- a/llvm/tools/llvm-readobj/ARMWinEHPrinter.h +++ b/llvm/tools/llvm-readobj/ARMWinEHPrinter.h @@ -154,7 +154,8 @@ bool FunctionOnly = false); object::SymbolRef getPreferredSymbol(const object::COFFObjectFile &COFF, - object::SymbolRef Sym); + object::SymbolRef Sym, + uint64_t &SymbolOffset); bool dumpXDataRecord(const object::COFFObjectFile &COFF, const object::SectionRef &Section, diff --git a/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp b/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp --- a/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp +++ b/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp @@ -238,22 +238,27 @@ return inconvertibleErrorCode(); } -SymbolRef Decoder::getPreferredSymbol(const COFFObjectFile &COFF, - SymbolRef Sym) { +SymbolRef Decoder::getPreferredSymbol(const COFFObjectFile &COFF, SymbolRef Sym, + uint64_t &SymbolOffset) { // The symbol resolved by getRelocatedSymbol can be any internal // nondescriptive symbol; try to resolve a more descriptive one. COFFSymbolRef CoffSym = COFF.getCOFFSymbol(Sym); - if (CoffSym.getStorageClass() != COFF::IMAGE_SYM_CLASS_LABEL) + if (CoffSym.getStorageClass() != COFF::IMAGE_SYM_CLASS_LABEL && + CoffSym.getSectionDefinition() == nullptr) return Sym; for (const auto &S : COFF.symbols()) { COFFSymbolRef CS = COFF.getCOFFSymbol(S); if (CS.getSectionNumber() == CoffSym.getSectionNumber() && - CS.getValue() == CoffSym.getValue()) { - if (CS.isExternal()) - return S; - if (CS.getStorageClass() != COFF::IMAGE_SYM_CLASS_LABEL) { + CS.getValue() <= CoffSym.getValue() + SymbolOffset && + CS.getStorageClass() != COFF::IMAGE_SYM_CLASS_LABEL && + CS.getSectionDefinition() == nullptr) { + uint32_t Offset = CoffSym.getValue() + SymbolOffset - CS.getValue(); + if (Offset <= SymbolOffset) { + SymbolOffset = Offset; Sym = S; CoffSym = CS; + if (CS.isExternal() && SymbolOffset == 0) + return Sym; } } } @@ -283,6 +288,9 @@ // 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; + + if (FunctionOnly) // Resolve label/section symbols into function names. + SymOrErr = getPreferredSymbol(COFF, *SymOrErr, SymbolOffset); } else { // No matching relocation found; operating on a linked image. Try to // find a descriptive symbol if possible. The immediate offset contains @@ -292,8 +300,6 @@ SymbolOffset = 0; SymOrErr = getSymbol(COFF, SymbolAddress, FunctionOnly); } - if (SymOrErr && FunctionOnly) // Resolve label symbols into function names - SymOrErr = getPreferredSymbol(COFF, *SymOrErr); return SymOrErr; }