summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-objdump
diff options
context:
space:
mode:
authorEli Friedman <efriedma@quicinc.com>2019-06-20 00:29:40 +0000
committerEli Friedman <efriedma@quicinc.com>2019-06-20 00:29:40 +0000
commitd88e28d13e66dfd9bd9dc22e21d82793161c5391 (patch)
tree85fe6a154b7a07454b0b9cfe10a182568a1e7f02 /llvm/tools/llvm-objdump
parente4c2e9b016c411cb75d3c1877007bace03d3b37f (diff)
downloadbcm5719-llvm-d88e28d13e66dfd9bd9dc22e21d82793161c5391.tar.gz
bcm5719-llvm-d88e28d13e66dfd9bd9dc22e21d82793161c5391.zip
[llvm-objdump] Switch between ARM/Thumb based on mapping symbols.
The ARMDisassembler changes allow changing between ARM and Thumb mode based on the MCSubtargetInfo, rather than the Target, which simplifies the other changes a bit. I'm not really happy with adding more target-specific logic to tools/llvm-objdump/, but there isn't any easy way around it: the logic in question specifically applies to disassembling an object file, and that code simply isn't located in lib/Target, at least at the moment. Differential Revision: https://reviews.llvm.org/D60927 llvm-svn: 363903
Diffstat (limited to 'llvm/tools/llvm-objdump')
-rw-r--r--llvm/tools/llvm-objdump/llvm-objdump.cpp109
1 files changed, 80 insertions, 29 deletions
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
index 22167f15e14..4e841827892 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -603,13 +603,18 @@ void SourcePrinter::printSourceLine(raw_ostream &OS,
OldLineInfo = LineInfo;
}
+static bool isAArch64Elf(const ObjectFile *Obj) {
+ const auto *Elf = dyn_cast<ELFObjectFileBase>(Obj);
+ return Elf && Elf->getEMachine() == ELF::EM_AARCH64;
+}
+
static bool isArmElf(const ObjectFile *Obj) {
- return (Obj->isELF() &&
- (Obj->getArch() == Triple::aarch64 ||
- Obj->getArch() == Triple::aarch64_be ||
- Obj->getArch() == Triple::arm || Obj->getArch() == Triple::armeb ||
- Obj->getArch() == Triple::thumb ||
- Obj->getArch() == Triple::thumbeb));
+ const auto *Elf = dyn_cast<ELFObjectFileBase>(Obj);
+ return Elf && Elf->getEMachine() == ELF::EM_ARM;
+}
+
+static bool hasMappingSymbols(const ObjectFile *Obj) {
+ return isArmElf(Obj) || isAArch64Elf(Obj);
}
static void printRelocation(const RelocationRef &Rel, uint64_t Address,
@@ -954,10 +959,24 @@ static bool shouldAdjustVA(const SectionRef &Section) {
return false;
}
+
+typedef std::pair<uint64_t, char> MappingSymbolPair;
+static char getMappingSymbolKind(ArrayRef<MappingSymbolPair> MappingSymbols,
+ uint64_t Address) {
+ auto Sym = bsearch(MappingSymbols, [Address](const MappingSymbolPair &Val) {
+ return Val.first > Address;
+ });
+ // Return zero for any address before the first mapping symbol; this means
+ // we should use the default disassembly mode, depending on the target.
+ if (Sym == MappingSymbols.begin())
+ return '\x00';
+ return (Sym - 1)->second;
+}
+
static uint64_t
dumpARMELFData(uint64_t SectionAddr, uint64_t Index, uint64_t End,
const ObjectFile *Obj, ArrayRef<uint8_t> Bytes,
- const std::vector<uint64_t> &TextMappingSymsAddr) {
+ ArrayRef<MappingSymbolPair> MappingSymbols) {
support::endianness Endian =
Obj->isLittleEndian() ? support::little : support::big;
while (Index < End) {
@@ -981,8 +1000,7 @@ dumpARMELFData(uint64_t SectionAddr, uint64_t Index, uint64_t End,
++Index;
}
outs() << "\n";
- if (std::binary_search(TextMappingSymsAddr.begin(),
- TextMappingSymsAddr.end(), Index))
+ if (getMappingSymbolKind(MappingSymbols, Index) != 'd')
break;
}
return Index;
@@ -1023,10 +1041,19 @@ static void dumpELFData(uint64_t SectionAddr, uint64_t Index, uint64_t End,
}
static void disassembleObject(const Target *TheTarget, const ObjectFile *Obj,
- MCContext &Ctx, MCDisassembler *DisAsm,
+ MCContext &Ctx, MCDisassembler *PrimaryDisAsm,
+ MCDisassembler *SecondaryDisAsm,
const MCInstrAnalysis *MIA, MCInstPrinter *IP,
- const MCSubtargetInfo *STI, PrettyPrinter &PIP,
+ const MCSubtargetInfo *PrimarySTI,
+ const MCSubtargetInfo *SecondarySTI,
+ PrettyPrinter &PIP,
SourcePrinter &SP, bool InlineRelocs) {
+ const MCSubtargetInfo *STI = PrimarySTI;
+ MCDisassembler *DisAsm = PrimaryDisAsm;
+ bool PrimaryIsThumb = false;
+ if (isArmElf(Obj))
+ PrimaryIsThumb = STI->checkFeatures("+thumb-mode");
+
std::map<SectionRef, std::vector<RelocationRef>> RelocMap;
if (InlineRelocs)
RelocMap = getRelocsMap(*Obj);
@@ -1113,25 +1140,23 @@ static void disassembleObject(const Target *TheTarget, const ObjectFile *Obj,
// Get the list of all the symbols in this section.
SectionSymbolsTy &Symbols = AllSymbols[Section];
- std::vector<uint64_t> DataMappingSymsAddr;
- std::vector<uint64_t> TextMappingSymsAddr;
- if (isArmElf(Obj)) {
+ std::vector<MappingSymbolPair> MappingSymbols;
+ if (hasMappingSymbols(Obj)) {
for (const auto &Symb : Symbols) {
uint64_t Address = std::get<0>(Symb);
StringRef Name = std::get<1>(Symb);
if (Name.startswith("$d"))
- DataMappingSymsAddr.push_back(Address - SectionAddr);
+ MappingSymbols.emplace_back(Address - SectionAddr, 'd');
if (Name.startswith("$x"))
- TextMappingSymsAddr.push_back(Address - SectionAddr);
+ MappingSymbols.emplace_back(Address - SectionAddr, 'x');
if (Name.startswith("$a"))
- TextMappingSymsAddr.push_back(Address - SectionAddr);
+ MappingSymbols.emplace_back(Address - SectionAddr, 'a');
if (Name.startswith("$t"))
- TextMappingSymsAddr.push_back(Address - SectionAddr);
+ MappingSymbols.emplace_back(Address - SectionAddr, 't');
}
}
- llvm::sort(DataMappingSymsAddr);
- llvm::sort(TextMappingSymsAddr);
+ llvm::sort(MappingSymbols);
if (Obj->isELF() && Obj->getArch() == Triple::amdgcn) {
// AMDGPU disassembler uses symbolizer for printing labels
@@ -1269,19 +1294,18 @@ static void disassembleObject(const Target *TheTarget, const ObjectFile *Obj,
Index = End;
}
- bool CheckARMELFData = isArmElf(Obj) &&
+ bool CheckARMELFData = hasMappingSymbols(Obj) &&
std::get<2>(Symbols[SI]) != ELF::STT_OBJECT &&
!DisassembleAll;
while (Index < End) {
- // AArch64 ELF binaries can interleave data and text in the same
- // section. We rely on the markers introduced to understand what we
- // need to dump. If the data marker is within a function, it is
+ // ARM and AArch64 ELF binaries can interleave data and text in the
+ // same section. We rely on the markers introduced to understand what
+ // we need to dump. If the data marker is within a function, it is
// denoted as a word/short etc.
if (CheckARMELFData &&
- std::binary_search(DataMappingSymsAddr.begin(),
- DataMappingSymsAddr.end(), Index)) {
+ getMappingSymbolKind(MappingSymbols, Index) == 'd') {
Index = dumpARMELFData(SectionAddr, Index, End, Obj, Bytes,
- TextMappingSymsAddr);
+ MappingSymbols);
continue;
}
@@ -1302,6 +1326,16 @@ static void disassembleObject(const Target *TheTarget, const ObjectFile *Obj,
}
}
+ if (SecondarySTI) {
+ if (getMappingSymbolKind(MappingSymbols, Index) == 'a') {
+ STI = PrimaryIsThumb ? SecondarySTI : PrimarySTI;
+ DisAsm = PrimaryIsThumb ? SecondaryDisAsm : PrimaryDisAsm;
+ } else if (getMappingSymbolKind(MappingSymbols, Index) == 't') {
+ STI = PrimaryIsThumb ? PrimarySTI : SecondarySTI;
+ DisAsm = PrimaryIsThumb ? PrimaryDisAsm : SecondaryDisAsm;
+ }
+ }
+
// Disassemble a real instruction or a data when disassemble all is
// provided
MCInst Inst;
@@ -1459,6 +1493,22 @@ static void disassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
report_error(Obj->getFileName(),
"no disassembler for target " + TripleName);
+ // If we have an ARM object file, we need a second disassembler, because
+ // ARM CPUs have two different instruction sets: ARM mode, and Thumb mode.
+ // We use mapping symbols to switch between the two assemblers, where
+ // appropriate.
+ std::unique_ptr<MCDisassembler> SecondaryDisAsm;
+ std::unique_ptr<const MCSubtargetInfo> SecondarySTI;
+ if (isArmElf(Obj) && !STI->checkFeatures("+mclass")) {
+ if (STI->checkFeatures("+thumb-mode"))
+ Features.AddFeature("-thumb-mode");
+ else
+ Features.AddFeature("+thumb-mode");
+ SecondarySTI.reset(TheTarget->createMCSubtargetInfo(TripleName, MCPU,
+ Features.getString()));
+ SecondaryDisAsm.reset(TheTarget->createMCDisassembler(*SecondarySTI, Ctx));
+ }
+
std::unique_ptr<const MCInstrAnalysis> MIA(
TheTarget->createMCInstrAnalysis(MII.get()));
@@ -1477,8 +1527,9 @@ static void disassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
if (!IP->applyTargetSpecificCLOption(Opt))
error("Unrecognized disassembler option: " + Opt);
- disassembleObject(TheTarget, Obj, Ctx, DisAsm.get(), MIA.get(), IP.get(),
- STI.get(), PIP, SP, InlineRelocs);
+ disassembleObject(TheTarget, Obj, Ctx, DisAsm.get(), SecondaryDisAsm.get(),
+ MIA.get(), IP.get(), STI.get(), SecondarySTI.get(), PIP,
+ SP, InlineRelocs);
}
void printRelocations(const ObjectFile *Obj) {
OpenPOWER on IntegriCloud