Skip to content

Commit 6c48f57

Browse files
committed
[llvm-objdump] [NFC] Factor out DisassemblerTarget class.
This is a preparation for ARM64EC/ARM64X binaries, which may contain both ARM64 and x86_64 code in the same file. llvm-objdump already has partial support for mixing disassemblers for ARM thumb mode support. However, for ARM64EC we can't share MCContext, MCInstrAnalysis and PrettyPrinter instances. This patch provides additional abstraction which makes adding mixed code support later in the series easier. Reviewed By: jhenderson, MaskRay Differential Revision: https://reviews.llvm.org/D149093
1 parent 992fa7b commit 6c48f57

File tree

1 file changed

+121
-77
lines changed

1 file changed

+121
-77
lines changed

llvm/tools/llvm-objdump/llvm-objdump.cpp

Lines changed: 121 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,92 @@ PrettyPrinter &selectPrettyPrinter(Triple const &Triple) {
836836
return AArch64PrettyPrinterInst;
837837
}
838838
}
839+
840+
class DisassemblerTarget {
841+
public:
842+
const Target *TheTarget;
843+
std::unique_ptr<const MCSubtargetInfo> SubtargetInfo;
844+
std::shared_ptr<MCContext> Context;
845+
std::unique_ptr<MCDisassembler> DisAsm;
846+
std::shared_ptr<const MCInstrAnalysis> InstrAnalysis;
847+
std::shared_ptr<MCInstPrinter> InstPrinter;
848+
PrettyPrinter *PrettyPrinter;
849+
850+
DisassemblerTarget(const Target *TheTarget, ObjectFile &Obj,
851+
StringRef TripleName, StringRef MCPU,
852+
SubtargetFeatures &Features);
853+
DisassemblerTarget(DisassemblerTarget &Other, SubtargetFeatures &Features);
854+
855+
private:
856+
MCTargetOptions Options;
857+
std::shared_ptr<const MCRegisterInfo> RegisterInfo;
858+
std::shared_ptr<const MCAsmInfo> AsmInfo;
859+
std::shared_ptr<const MCInstrInfo> InstrInfo;
860+
std::shared_ptr<MCObjectFileInfo> ObjectFileInfo;
861+
};
862+
863+
DisassemblerTarget::DisassemblerTarget(const Target *TheTarget, ObjectFile &Obj,
864+
StringRef TripleName, StringRef MCPU,
865+
SubtargetFeatures &Features)
866+
: TheTarget(TheTarget),
867+
PrettyPrinter(&selectPrettyPrinter(Triple(TripleName))),
868+
RegisterInfo(TheTarget->createMCRegInfo(TripleName)) {
869+
if (!RegisterInfo)
870+
reportError(Obj.getFileName(), "no register info for target " + TripleName);
871+
872+
// Set up disassembler.
873+
AsmInfo.reset(TheTarget->createMCAsmInfo(*RegisterInfo, TripleName, Options));
874+
if (!AsmInfo)
875+
reportError(Obj.getFileName(), "no assembly info for target " + TripleName);
876+
877+
SubtargetInfo.reset(
878+
TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features.getString()));
879+
if (!SubtargetInfo)
880+
reportError(Obj.getFileName(),
881+
"no subtarget info for target " + TripleName);
882+
InstrInfo.reset(TheTarget->createMCInstrInfo());
883+
if (!InstrInfo)
884+
reportError(Obj.getFileName(),
885+
"no instruction info for target " + TripleName);
886+
Context =
887+
std::make_shared<MCContext>(Triple(TripleName), AsmInfo.get(),
888+
RegisterInfo.get(), SubtargetInfo.get());
889+
890+
// FIXME: for now initialize MCObjectFileInfo with default values
891+
ObjectFileInfo.reset(
892+
TheTarget->createMCObjectFileInfo(*Context, /*PIC=*/false));
893+
Context->setObjectFileInfo(ObjectFileInfo.get());
894+
895+
DisAsm.reset(TheTarget->createMCDisassembler(*SubtargetInfo, *Context));
896+
if (!DisAsm)
897+
reportError(Obj.getFileName(), "no disassembler for target " + TripleName);
898+
899+
InstrAnalysis.reset(TheTarget->createMCInstrAnalysis(InstrInfo.get()));
900+
901+
int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
902+
InstPrinter.reset(TheTarget->createMCInstPrinter(Triple(TripleName),
903+
AsmPrinterVariant, *AsmInfo,
904+
*InstrInfo, *RegisterInfo));
905+
if (!InstPrinter)
906+
reportError(Obj.getFileName(),
907+
"no instruction printer for target " + TripleName);
908+
InstPrinter->setPrintImmHex(PrintImmHex);
909+
InstPrinter->setPrintBranchImmAsAddress(true);
910+
InstPrinter->setSymbolizeOperands(SymbolizeOperands);
911+
InstPrinter->setMCInstrAnalysis(InstrAnalysis.get());
912+
}
913+
914+
DisassemblerTarget::DisassemblerTarget(DisassemblerTarget &Other,
915+
SubtargetFeatures &Features)
916+
: TheTarget(Other.TheTarget),
917+
SubtargetInfo(TheTarget->createMCSubtargetInfo(TripleName, MCPU,
918+
Features.getString())),
919+
Context(Other.Context),
920+
DisAsm(TheTarget->createMCDisassembler(*SubtargetInfo, *Context)),
921+
InstrAnalysis(Other.InstrAnalysis), InstPrinter(Other.InstPrinter),
922+
PrettyPrinter(Other.PrettyPrinter), RegisterInfo(Other.RegisterInfo),
923+
AsmInfo(Other.AsmInfo), InstrInfo(Other.InstrInfo),
924+
ObjectFileInfo(Other.ObjectFileInfo) {}
839925
} // namespace
840926

841927
static uint8_t getElfSymbolType(const ObjectFile &Obj, const SymbolRef &Sym) {
@@ -1326,15 +1412,14 @@ fetchBinaryByBuildID(const ObjectFile &Obj) {
13261412
return std::move(*DebugBinary);
13271413
}
13281414

1329-
static void disassembleObject(const Target *TheTarget, ObjectFile &Obj,
1330-
const ObjectFile &DbgObj, MCContext &Ctx,
1331-
MCDisassembler *PrimaryDisAsm,
1332-
MCDisassembler *SecondaryDisAsm,
1333-
const MCInstrAnalysis *MIA, MCInstPrinter *IP,
1334-
const MCSubtargetInfo *PrimarySTI,
1335-
const MCSubtargetInfo *SecondarySTI,
1336-
PrettyPrinter &PIP, SourcePrinter &SP,
1337-
bool InlineRelocs) {
1415+
static void
1416+
disassembleObject(const Target *TheTarget, ObjectFile &Obj,
1417+
const ObjectFile &DbgObj, MCContext &Ctx,
1418+
MCDisassembler *PrimaryDisAsm,
1419+
std::optional<DisassemblerTarget> &SecondaryTarget,
1420+
const MCInstrAnalysis *MIA, MCInstPrinter *IP,
1421+
const MCSubtargetInfo *PrimarySTI, PrettyPrinter &PIP,
1422+
SourcePrinter &SP, bool InlineRelocs) {
13381423
const MCSubtargetInfo *STI = PrimarySTI;
13391424
MCDisassembler *DisAsm = PrimaryDisAsm;
13401425
bool PrimaryIsThumb = false;
@@ -1790,13 +1875,17 @@ static void disassembleObject(const Target *TheTarget, ObjectFile &Obj,
17901875
if (!MappingSymbols.empty()) {
17911876
char Kind = getMappingSymbolKind(MappingSymbols, Index);
17921877
DumpARMELFData = Kind == 'd';
1793-
if (SecondarySTI) {
1878+
if (SecondaryTarget) {
17941879
if (Kind == 'a') {
1795-
STI = PrimaryIsThumb ? SecondarySTI : PrimarySTI;
1796-
DisAsm = PrimaryIsThumb ? SecondaryDisAsm : PrimaryDisAsm;
1880+
STI = PrimaryIsThumb ? SecondaryTarget->SubtargetInfo.get()
1881+
: PrimarySTI;
1882+
DisAsm = PrimaryIsThumb ? SecondaryTarget->DisAsm.get()
1883+
: PrimaryDisAsm;
17971884
} else if (Kind == 't') {
1798-
STI = PrimaryIsThumb ? PrimarySTI : SecondarySTI;
1799-
DisAsm = PrimaryIsThumb ? PrimaryDisAsm : SecondaryDisAsm;
1885+
STI = PrimaryIsThumb ? PrimarySTI
1886+
: SecondaryTarget->SubtargetInfo.get();
1887+
DisAsm = PrimaryIsThumb ? PrimaryDisAsm
1888+
: SecondaryTarget->DisAsm.get();
18001889
}
18011890
}
18021891
}
@@ -2064,20 +2153,6 @@ static void disassembleObject(ObjectFile *Obj, bool InlineRelocs) {
20642153
Features.AddFeature("+all");
20652154
}
20662155

2067-
std::unique_ptr<const MCRegisterInfo> MRI(
2068-
TheTarget->createMCRegInfo(TripleName));
2069-
if (!MRI)
2070-
reportError(Obj->getFileName(),
2071-
"no register info for target " + TripleName);
2072-
2073-
// Set up disassembler.
2074-
MCTargetOptions MCOptions;
2075-
std::unique_ptr<const MCAsmInfo> AsmInfo(
2076-
TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
2077-
if (!AsmInfo)
2078-
reportError(Obj->getFileName(),
2079-
"no assembly info for target " + TripleName);
2080-
20812156
if (MCPU.empty())
20822157
MCPU = Obj->tryGetCPUName().value_or("").str();
20832158

@@ -2104,57 +2179,23 @@ static void disassembleObject(ObjectFile *Obj, bool InlineRelocs) {
21042179
}
21052180
}
21062181

2107-
std::unique_ptr<const MCSubtargetInfo> STI(
2108-
TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features.getString()));
2109-
if (!STI)
2110-
reportError(Obj->getFileName(),
2111-
"no subtarget info for target " + TripleName);
2112-
std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
2113-
if (!MII)
2114-
reportError(Obj->getFileName(),
2115-
"no instruction info for target " + TripleName);
2116-
MCContext Ctx(Triple(TripleName), AsmInfo.get(), MRI.get(), STI.get());
2117-
// FIXME: for now initialize MCObjectFileInfo with default values
2118-
std::unique_ptr<MCObjectFileInfo> MOFI(
2119-
TheTarget->createMCObjectFileInfo(Ctx, /*PIC=*/false));
2120-
Ctx.setObjectFileInfo(MOFI.get());
2121-
2122-
std::unique_ptr<MCDisassembler> DisAsm(
2123-
TheTarget->createMCDisassembler(*STI, Ctx));
2124-
if (!DisAsm)
2125-
reportError(Obj->getFileName(), "no disassembler for target " + TripleName);
2182+
DisassemblerTarget PrimaryTarget(TheTarget, *Obj, TripleName, MCPU, Features);
21262183

21272184
// If we have an ARM object file, we need a second disassembler, because
21282185
// ARM CPUs have two different instruction sets: ARM mode, and Thumb mode.
21292186
// We use mapping symbols to switch between the two assemblers, where
21302187
// appropriate.
2131-
std::unique_ptr<MCDisassembler> SecondaryDisAsm;
2132-
std::unique_ptr<const MCSubtargetInfo> SecondarySTI;
2133-
if (isArmElf(*Obj) && !STI->checkFeatures("+mclass")) {
2134-
if (STI->checkFeatures("+thumb-mode"))
2135-
Features.AddFeature("-thumb-mode");
2136-
else
2137-
Features.AddFeature("+thumb-mode");
2138-
SecondarySTI.reset(TheTarget->createMCSubtargetInfo(TripleName, MCPU,
2139-
Features.getString()));
2140-
SecondaryDisAsm.reset(TheTarget->createMCDisassembler(*SecondarySTI, Ctx));
2141-
}
2142-
2143-
std::unique_ptr<const MCInstrAnalysis> MIA(
2144-
TheTarget->createMCInstrAnalysis(MII.get()));
2145-
2146-
int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
2147-
std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
2148-
Triple(TripleName), AsmPrinterVariant, *AsmInfo, *MII, *MRI));
2149-
if (!IP)
2150-
reportError(Obj->getFileName(),
2151-
"no instruction printer for target " + TripleName);
2152-
IP->setPrintImmHex(PrintImmHex);
2153-
IP->setPrintBranchImmAsAddress(true);
2154-
IP->setSymbolizeOperands(SymbolizeOperands);
2155-
IP->setMCInstrAnalysis(MIA.get());
2188+
std::optional<DisassemblerTarget> SecondaryTarget;
21562189

2157-
PrettyPrinter &PIP = selectPrettyPrinter(Triple(TripleName));
2190+
if (isArmElf(*Obj)) {
2191+
if (!PrimaryTarget.SubtargetInfo->checkFeatures("+mclass")) {
2192+
if (PrimaryTarget.SubtargetInfo->checkFeatures("+thumb-mode"))
2193+
Features.AddFeature("-thumb-mode");
2194+
else
2195+
Features.AddFeature("+thumb-mode");
2196+
SecondaryTarget.emplace(PrimaryTarget, Features);
2197+
}
2198+
}
21582199

21592200
const ObjectFile *DbgObj = Obj;
21602201
if (!FetchedBinary.getBinary() && !Obj->hasDebugInfo()) {
@@ -2184,13 +2225,16 @@ static void disassembleObject(ObjectFile *Obj, bool InlineRelocs) {
21842225
SourcePrinter SP(DbgObj, TheTarget->getName());
21852226

21862227
for (StringRef Opt : DisassemblerOptions)
2187-
if (!IP->applyTargetSpecificCLOption(Opt))
2228+
if (!PrimaryTarget.InstPrinter->applyTargetSpecificCLOption(Opt))
21882229
reportError(Obj->getFileName(),
21892230
"Unrecognized disassembler option: " + Opt);
21902231

2191-
disassembleObject(TheTarget, *Obj, *DbgObj, Ctx, DisAsm.get(),
2192-
SecondaryDisAsm.get(), MIA.get(), IP.get(), STI.get(),
2193-
SecondarySTI.get(), PIP, SP, InlineRelocs);
2232+
disassembleObject(TheTarget, *Obj, *DbgObj, *PrimaryTarget.Context.get(),
2233+
PrimaryTarget.DisAsm.get(), SecondaryTarget,
2234+
PrimaryTarget.InstrAnalysis.get(),
2235+
PrimaryTarget.InstPrinter.get(),
2236+
PrimaryTarget.SubtargetInfo.get(),
2237+
*PrimaryTarget.PrettyPrinter, SP, InlineRelocs);
21942238
}
21952239

21962240
void Dumper::printRelocations() {

0 commit comments

Comments
 (0)