diff options
author | Eli Friedman <efriedma@quicinc.com> | 2019-06-20 00:29:40 +0000 |
---|---|---|
committer | Eli Friedman <efriedma@quicinc.com> | 2019-06-20 00:29:40 +0000 |
commit | d88e28d13e66dfd9bd9dc22e21d82793161c5391 (patch) | |
tree | 85fe6a154b7a07454b0b9cfe10a182568a1e7f02 /llvm/tools/llvm-objdump | |
parent | e4c2e9b016c411cb75d3c1877007bace03d3b37f (diff) | |
download | bcm5719-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.cpp | 109 |
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) { |