Skip to content

Commit

Permalink
[llvm-objdump][XCOFF] Use symbol index+symbol name + storage mapping …
Browse files Browse the repository at this point in the history
…class as label for -D

SUMMARY:

For the llvm-objdump -D, the symbol name is used as a label in the disassembly for the specific address (when a symbol address is equal to the virtual address in the dump).

In XCOFF, multiple symbols may have the same name, being differentiated by their storage mapping class. It is helpful to print the QualName and not just the name when forming the output label for a csect symbol. The symbol index further removes any ambiguity caused by duplicate names.

To maintain compatibility with the binutils objdump, the XCOFF-specific --symbol-description option is added to enable the enhanced format.

Reviewers: hubert.reinterpretcast, James Henderson, Jason Liu ,daltenty
Subscribers: wuzish, nemanjai, hiraditya

Differential Revision: https://reviews.llvm.org/D72973
  • Loading branch information
diggerlin committed Apr 6, 2020
1 parent 9072df8 commit a26a441
Show file tree
Hide file tree
Showing 10 changed files with 287 additions and 57 deletions.
7 changes: 7 additions & 0 deletions llvm/docs/CommandGuide/llvm-objdump.rst
Expand Up @@ -325,6 +325,13 @@ MACH-O ONLY OPTIONS AND COMMANDS

Display weak binding information.

XCOFF ONLY OPTIONS AND COMMANDS
---------------------------------

.. option:: --symbol-description

Add symbol description to disassembly output.

BUGS
----

Expand Down
48 changes: 38 additions & 10 deletions llvm/include/llvm/MC/MCDisassembler/MCDisassembler.h
Expand Up @@ -9,31 +9,59 @@
#ifndef LLVM_MC_MCDISASSEMBLER_MCDISASSEMBLER_H
#define LLVM_MC_MCDISASSEMBLER_MCDISASSEMBLER_H

#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/XCOFF.h"
#include "llvm/MC/MCDisassembler/MCSymbolizer.h"
#include <cstdint>
#include <memory>
#include <vector>

namespace llvm {

struct XCOFFSymbolInfo {
Optional<XCOFF::StorageMappingClass> StorageMappingClass;
Optional<uint32_t> Index;
bool IsLabel;
XCOFFSymbolInfo(Optional<XCOFF::StorageMappingClass> Smc,
Optional<uint32_t> Idx, bool Label)
: StorageMappingClass(Smc), Index(Idx), IsLabel(Label) {}
};

struct SymbolInfoTy {
uint64_t Addr;
StringRef Name;
uint8_t Type;
uint64_t Addr;
StringRef Name;
union {
uint8_t Type;
XCOFFSymbolInfo XCOFFSymInfo;
};

private:
bool IsXCOFF;

SymbolInfoTy(uint64_t Addr, StringRef Name, uint8_t Type)
: Addr(Addr), Name(Name), Type(Type){};
public:
SymbolInfoTy(uint64_t Addr, StringRef Name,
Optional<XCOFF::StorageMappingClass> Smc, Optional<uint32_t> Idx,
bool Label)
: Addr(Addr), Name(Name), XCOFFSymInfo(Smc, Idx, Label), IsXCOFF(true) {}
SymbolInfoTy(uint64_t Addr, StringRef Name, uint8_t Type)
: Addr(Addr), Name(Name), Type(Type), IsXCOFF(false) {}
bool isXCOFF() const { return IsXCOFF; }

friend bool operator<(const SymbolInfoTy &P1, const SymbolInfoTy &P2) {
return std::tie(P1.Addr, P1.Name, P1.Type) <
std::tie(P2.Addr, P2.Name, P2.Type);
}
private:
friend bool operator<(const SymbolInfoTy &P1, const SymbolInfoTy &P2) {
assert(P1.IsXCOFF == P2.IsXCOFF &&
"P1.IsXCOFF should be equal to P2.IsXCOFF.");
if (P1.IsXCOFF)
return std::tie(P1.Addr, P1.Name) < std::tie(P2.Addr, P2.Name);
else
return std::tie(P1.Addr, P1.Name, P1.Type) <
std::tie(P2.Addr, P2.Name, P2.Type);
}
};

using SectionSymbolsTy = std::vector<SymbolInfoTy>;


template <typename T> class ArrayRef;
class MCContext;
class MCInst;
Expand Down
8 changes: 8 additions & 0 deletions llvm/include/llvm/Object/XCOFFObjectFile.h
Expand Up @@ -129,6 +129,8 @@ struct XCOFFStringTable {
};

struct XCOFFCsectAuxEnt32 {
static constexpr uint8_t SymbolTypeMask = 0x07;

support::ubig32_t
SectionOrLength; // If the symbol type is XTY_SD or XTY_CM, the csect
// length.
Expand All @@ -141,6 +143,12 @@ struct XCOFFCsectAuxEnt32 {
XCOFF::StorageMappingClass StorageMappingClass;
support::ubig32_t StabInfoIndex;
support::ubig16_t StabSectNum;

uint8_t getSymbolType() const {
return SymbolAlignmentAndType & SymbolTypeMask;
};

bool isLabel() const { return getSymbolType() == XCOFF::XTY_LD; }
};

struct XCOFFFileAuxEnt {
Expand Down
46 changes: 28 additions & 18 deletions llvm/lib/BinaryFormat/XCOFF.cpp
Expand Up @@ -10,27 +10,37 @@

using namespace llvm;

#define SMC_CASE(A) \
case XCOFF::XMC_##A: \
return #A;
StringRef XCOFF::getMappingClassString(XCOFF::StorageMappingClass SMC) {
switch (SMC) {
case XCOFF::XMC_DS:
return "DS";
case XCOFF::XMC_RW:
return "RW";
case XCOFF::XMC_PR:
return "PR";
case XCOFF::XMC_TC0:
return "TC0";
case XCOFF::XMC_BS:
return "BS";
case XCOFF::XMC_RO:
return "RO";
case XCOFF::XMC_UA:
return "UA";
case XCOFF::XMC_TC:
return "TC";
default:
report_fatal_error("Unhandled storage-mapping class.");
SMC_CASE(PR)
SMC_CASE(RO)
SMC_CASE(DB)
SMC_CASE(GL)
SMC_CASE(XO)
SMC_CASE(SV)
SMC_CASE(SV64)
SMC_CASE(SV3264)
SMC_CASE(TI)
SMC_CASE(TB)
SMC_CASE(RW)
SMC_CASE(TC0)
SMC_CASE(TC)
SMC_CASE(TD)
SMC_CASE(DS)
SMC_CASE(UA)
SMC_CASE(BS)
SMC_CASE(UC)
SMC_CASE(TL)
SMC_CASE(UL)
SMC_CASE(TE)
#undef SMC_CASE
}

// TODO: need to add a test case for "Unknown" and other SMC.
return "Unknown";
}

#define RELOC_CASE(A) \
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Object/XCOFFObjectFile.cpp
Expand Up @@ -766,6 +766,8 @@ uint8_t XCOFFSymbolRef::getNumberOfAuxEntries() const {
return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->NumberOfAuxEntries;
}

// TODO: The function needs to return an error if there is no csect auxiliary
// entry.
const XCOFFCsectAuxEnt32 *XCOFFSymbolRef::getXCOFFCsectAuxEnt32() const {
assert(!OwningObjectPtr->is64Bit() &&
"32-bit interface called on 64-bit object file.");
Expand All @@ -791,6 +793,8 @@ int16_t XCOFFSymbolRef::getSectionNumber() const {
return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SectionNumber;
}

// TODO: The function name needs to be changed to express the purpose of the
// function.
bool XCOFFSymbolRef::hasCsectAuxEnt() const {
XCOFF::StorageClass SC = getStorageClass();
return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT ||
Expand Down
@@ -0,0 +1,72 @@
# REQUIRES: powerpc-registered-target

# RUN: llvm-objdump -D %p/Inputs/xcoff-section-headers.o | \
# RUN: FileCheck --check-prefixes=COMMON,PLAIN %s

# RUN: llvm-objdump -D --symbol-description %p/Inputs/xcoff-section-headers.o | \
# RUN: FileCheck --check-prefixes=COMMON,DESC %s

# xcoff-section-headers.o Compiled with IBM XL C/C++ for AIX, V16.1.0
# compiler command: xlc -qtls -o xcoff-section-headers.o -c test.c

## test.c:
## int a;
## int b = 12345;
## __thread int c;
## __thread double d = 3.14159;
##
## int func(void) {
## return a;
## }

COMMON: Inputs/xcoff-section-headers.o: file format aixcoff-rs6000
COMMON: Disassembly of section .text:
PLAIN: 00000000 <.text>:
DESC: 00000000 (idx: 4) .text:
COMMON-NEXT: 0: 80 62 00 04 lwz 3, 4(2)
COMMON-NEXT: 4: 80 63 00 00 lwz 3, 0(3)
COMMON-NEXT: 8: 4e 80 00 20 blr
COMMON-NEXT: c: 00 00 00 00 <unknown>
COMMON-NEXT: 10: 00 00 20 40 <unknown>
COMMON-NEXT: 14: 00 00 00 01 <unknown>
COMMON-NEXT: 18: 00 00 00 0c <unknown>
COMMON-NEXT: 1c: 00 04 66 75 <unknown>
COMMON-NEXT: 20: 6e 63 00 00 xoris 3, 19, 0
COMMON-NEXT: ...
COMMON: Disassembly of section .data:
PLAIN: 00000080 <func>:
DESC: 00000080 (idx: 22) func[TC]:
COMMON-NEXT: 80: 00 00 00 94 <unknown>
PLAIN: 00000084 <a>:
DESC: 00000084 (idx: 26) a[TC]:
COMMON-NEXT: 84: 00 00 00 a4 <unknown>
PLAIN: 00000088 <b>:
DESC: 00000088 (idx: 30) b[TC]:
COMMON-NEXT: 88: 00 00 00 a0 <unknown>
PLAIN: 0000008c <c>:
DESC: 0000008c (idx: 34) c[TC]:
COMMON-NEXT: 8c: 00 00 00 08 <unknown>
PLAIN: 00000090 <d>:
DESC: 00000090 (idx: 38) d[TC]:
COMMON-NEXT: 90: 00 00 00 00 <unknown>
PLAIN: 00000094 <func>:
DESC: 00000094 (idx: 20) func[DS]:
COMMON-NEXT: 94: 00 00 00 00 <unknown>
COMMON-NEXT: 98: 00 00 00 80 <unknown>
COMMON-NEXT: 9c: 00 00 00 00 <unknown>
PLAIN: 000000a0 <b>:
DESC: 000000a0 (idx: 28) b[RW]:
COMMON-NEXT: a0: 00 00 30 39 <unknown>
COMMON: Disassembly of section .bss:
PLAIN: 000000a4 <a>:
DESC: 000000a4 (idx: 24) a[RW]:
COMMON-NEXT: ...
COMMON: Disassembly of section .tdata:
PLAIN: 00000000 <d>:
DESC: 00000000 (idx: 36) d[TL]:
COMMON-NEXT: 0: 40 09 21 f9 bdnzfl 9, 0x21f8
COMMON-NEXT: 4: f0 1b 86 6e <unknown>
COMMON: Disassembly of section .tbss:
PLAIN: 00000008 <c>:
DESC: 00000008 (idx: 32) c[UL]:
COMMON-NEXT: ...
52 changes: 46 additions & 6 deletions llvm/tools/llvm-objdump/XCOFFDump.cpp
@@ -1,4 +1,4 @@
//===-- XCOFFDump.cpp - XCOFF-specific dumper -------------------*- C++ -*-===//
//===-- XCOFFDump.cpp - XCOFF-specific dumper -----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
Expand All @@ -11,14 +11,15 @@
///
//===----------------------------------------------------------------------===//

#include "llvm-objdump.h"
#include "llvm/Object/XCOFFObjectFile.h"
#include "XCOFFDump.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"

using namespace llvm;
using namespace llvm::object;

llvm::Error llvm::getXCOFFRelocationValueString(const XCOFFObjectFile *Obj,
const RelocationRef &Rel,
SmallVectorImpl<char> &Result) {
Error objdump::getXCOFFRelocationValueString(const XCOFFObjectFile *Obj,
const RelocationRef &Rel,
SmallVectorImpl<char> &Result) {
symbol_iterator SymI = Rel.getSymbol();
if (SymI == Obj->symbol_end())
return make_error<GenericBinaryError>(
Expand All @@ -32,3 +33,42 @@ llvm::Error llvm::getXCOFFRelocationValueString(const XCOFFObjectFile *Obj,
Result.append(SymName.begin(), SymName.end());
return Error::success();
}

Optional<XCOFF::StorageMappingClass>
objdump::getXCOFFSymbolCsectSMC(const XCOFFObjectFile *Obj,
const SymbolRef &Sym) {
XCOFFSymbolRef SymRef(Sym.getRawDataRefImpl(), Obj);

if (SymRef.hasCsectAuxEnt())
return SymRef.getXCOFFCsectAuxEnt32()->StorageMappingClass;

return None;
}

bool objdump::isLabel(const XCOFFObjectFile *Obj, const SymbolRef &Sym) {

XCOFFSymbolRef SymRef(Sym.getRawDataRefImpl(), Obj);

if (SymRef.hasCsectAuxEnt())
return SymRef.getXCOFFCsectAuxEnt32()->isLabel();

return false;
}

void objdump::printXCOFFSymbolDescription(const SymbolInfoTy &SymbolInfo,
StringRef SymbolName) {
assert(SymbolInfo.isXCOFF() && "Must be a XCOFFSymInfo.");

// Dummy symbols have no symbol index.
if (SymbolInfo.XCOFFSymInfo.Index)
outs() << "(idx: " << SymbolInfo.XCOFFSymInfo.Index.getValue() << ") ";

outs() << SymbolName;

if (SymbolInfo.XCOFFSymInfo.StorageMappingClass &&
!SymbolInfo.XCOFFSymInfo.IsLabel) {
const XCOFF::StorageMappingClass Smc =
SymbolInfo.XCOFFSymInfo.StorageMappingClass.getValue();
outs() << "[" << XCOFF::getMappingClassString(Smc) << "]";
}
}
33 changes: 33 additions & 0 deletions llvm/tools/llvm-objdump/XCOFFDump.h
@@ -0,0 +1,33 @@
//===-- XCOFFDump.h ---------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_TOOLS_LLVM_OBJDUMP_XCOFFDUMP_H
#define LLVM_TOOLS_LLVM_OBJDUMP_XCOFFDUMP_H

#include "llvm/Object/XCOFFObjectFile.h"

namespace llvm {

class SymbolInfoTy;

namespace objdump {
Optional<XCOFF::StorageMappingClass>
getXCOFFSymbolCsectSMC(const object::XCOFFObjectFile *Obj,
const object::SymbolRef &Sym);

bool isLabel(const object::XCOFFObjectFile *Obj, const object::SymbolRef &Sym);

void printXCOFFSymbolDescription(const SymbolInfoTy &SymbolInfo,
StringRef SymbolName);

Error getXCOFFRelocationValueString(const object::XCOFFObjectFile *Obj,
const object::RelocationRef &RelRef,
llvm::SmallVectorImpl<char> &Result);
} // namespace objdump
} // namespace llvm
#endif

0 comments on commit a26a441

Please sign in to comment.