Commit 63784b9a authored by Martin Storsjö's avatar Martin Storsjö
Browse files

[llvm-readobj] [COFF] Resolve relocations pointing at section symbols for arm64 too

This syncs parts from the x86 implementation to the ARMWinEH
implementation.

Currently, neither of the compilers targeting COFF/arm64 (MSVC, LLVM)
produce such relocations, but LLVM might after a later patch.

Differential Revision: https://reviews.llvm.org/D109650
parent 197084fc
Loading
Loading
Loading
Loading
+99 −0
Original line number Diff line number Diff line
## 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
...
+15 −9
Original line number Diff line number Diff line
@@ -238,22 +238,27 @@ ErrorOr<SymbolRef> Decoder::getRelocatedSymbol(const COFFObjectFile &,
  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 @@ ErrorOr<SymbolRef> Decoder::getSymbolForLocation(
    // 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 @@ ErrorOr<SymbolRef> Decoder::getSymbolForLocation(
    SymbolOffset = 0;
    SymOrErr = getSymbol(COFF, SymbolAddress, FunctionOnly);
  }
  if (SymOrErr && FunctionOnly) // Resolve label symbols into function names
    SymOrErr = getPreferredSymbol(COFF, *SymOrErr);
  return SymOrErr;
}

+2 −1
Original line number Diff line number Diff line
@@ -154,7 +154,8 @@ class Decoder {
                       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,