diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
--- a/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -1299,15 +1299,107 @@
   return std::move(*DebugBinary);
 }
 
-static void disassembleObject(const Target *TheTarget, ObjectFile &Obj,
-                              const ObjectFile &DbgObj, MCContext &Ctx,
-                              MCDisassembler *PrimaryDisAsm,
-                              MCDisassembler *SecondaryDisAsm,
-                              const MCInstrAnalysis *MIA, MCInstPrinter *IP,
-                              const MCSubtargetInfo *PrimarySTI,
-                              const MCSubtargetInfo *SecondarySTI,
-                              PrettyPrinter &PIP, SourcePrinter &SP,
-                              bool InlineRelocs) {
+class DisassemblerTarget {
+public:
+  const Target *Target;
+  std::unique_ptr<const MCSubtargetInfo> SubtargetInfo;
+  std::unique_ptr<MCDisassembler> DisAsm;
+  MCContext *Context;
+  const MCInstrAnalysis *InstrAnalysis;
+  MCInstPrinter *InstPrinter;
+  PrettyPrinter *PrettyPrinter;
+
+  DisassemblerTarget(const class Target *TheTarget, ObjectFile &Obj,
+                     std::string TripleName, std::string MCPU,
+                     SubtargetFeatures &Features);
+  DisassemblerTarget(DisassemblerTarget &Other, SubtargetFeatures &Features);
+
+private:
+  MCTargetOptions Options;
+  std::unique_ptr<const MCRegisterInfo> RegisterInfo;
+  std::unique_ptr<const MCAsmInfo> AsmInfo;
+  std::unique_ptr<const MCInstrInfo> InstrInfo;
+  std::unique_ptr<MCContext> ContextPtr;
+  std::unique_ptr<MCObjectFileInfo> ObjectFileInfo;
+  std::unique_ptr<const MCInstrAnalysis> InstrAnalysisPtr;
+  std::unique_ptr<MCInstPrinter> InstPrinterPtr;
+};
+
+DisassemblerTarget::DisassemblerTarget(const class Target *TheTarget,
+                                       ObjectFile &Obj, std::string TripleName,
+                                       std::string MCPU,
+                                       SubtargetFeatures &Features) {
+  Target = TheTarget;
+  PrettyPrinter = &selectPrettyPrinter(Triple(TripleName));
+
+  RegisterInfo.reset(Target->createMCRegInfo(TripleName));
+  if (!RegisterInfo)
+    reportError(Obj.getFileName(), "no register info for target " + TripleName);
+
+  // Set up disassembler.
+  AsmInfo.reset(Target->createMCAsmInfo(*RegisterInfo, TripleName, Options));
+  if (!AsmInfo)
+    reportError(Obj.getFileName(), "no assembly info for target " + TripleName);
+
+  SubtargetInfo.reset(
+      Target->createMCSubtargetInfo(TripleName, MCPU, Features.getString()));
+  if (!SubtargetInfo)
+    reportError(Obj.getFileName(),
+                "no subtarget info for target " + TripleName);
+  InstrInfo.reset(Target->createMCInstrInfo());
+  if (!InstrInfo)
+    reportError(Obj.getFileName(),
+                "no instruction info for target " + TripleName);
+  ContextPtr =
+      std::make_unique<MCContext>(Triple(TripleName), AsmInfo.get(),
+                                  RegisterInfo.get(), SubtargetInfo.get());
+  Context = ContextPtr.get();
+
+  // FIXME: for now initialize MCObjectFileInfo with default values
+  ObjectFileInfo.reset(Target->createMCObjectFileInfo(*Context, /*PIC=*/false));
+  Context->setObjectFileInfo(ObjectFileInfo.get());
+
+  DisAsm.reset(Target->createMCDisassembler(*SubtargetInfo, *Context));
+  if (!DisAsm)
+    reportError(Obj.getFileName(), "no disassembler for target " + TripleName);
+
+  InstrAnalysisPtr.reset(Target->createMCInstrAnalysis(InstrInfo.get()));
+  InstrAnalysis = InstrAnalysisPtr.get();
+
+  int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
+  InstPrinterPtr.reset(Target->createMCInstPrinter(Triple(TripleName),
+                                                   AsmPrinterVariant, *AsmInfo,
+                                                   *InstrInfo, *RegisterInfo));
+  if (!InstPrinterPtr)
+    reportError(Obj.getFileName(),
+                "no instruction printer for target " + TripleName);
+  InstPrinter = InstPrinterPtr.get();
+  InstPrinter->setPrintImmHex(PrintImmHex);
+  InstPrinter->setPrintBranchImmAsAddress(true);
+  InstPrinter->setSymbolizeOperands(SymbolizeOperands);
+  InstPrinter->setMCInstrAnalysis(InstrAnalysis);
+}
+
+DisassemblerTarget::DisassemblerTarget(DisassemblerTarget &Other,
+                                       SubtargetFeatures &Features) {
+  Target = Other.Target;
+  Context = Other.Context;
+  InstrAnalysis = Other.InstrAnalysis;
+  InstPrinter = Other.InstPrinter;
+  SubtargetInfo.reset(
+      Target->createMCSubtargetInfo(TripleName, MCPU, Features.getString()));
+  DisAsm.reset(Target->createMCDisassembler(*SubtargetInfo, *Context));
+  PrettyPrinter = Other.PrettyPrinter;
+}
+
+static void
+disassembleObject(const Target *TheTarget, ObjectFile &Obj,
+                  const ObjectFile &DbgObj, MCContext &Ctx,
+                  MCDisassembler *PrimaryDisAsm,
+                  std::optional<DisassemblerTarget> &SecondaryTarget,
+                  const MCInstrAnalysis *MIA, MCInstPrinter *IP,
+                  const MCSubtargetInfo *PrimarySTI, PrettyPrinter &PIP,
+                  SourcePrinter &SP, bool InlineRelocs) {
   const MCSubtargetInfo *STI = PrimarySTI;
   MCDisassembler *DisAsm = PrimaryDisAsm;
   bool PrimaryIsThumb = false;
@@ -1757,13 +1849,17 @@
         if (!MappingSymbols.empty()) {
           char Kind = getMappingSymbolKind(MappingSymbols, Index);
           DumpARMELFData = Kind == 'd';
-          if (SecondarySTI) {
+          if (SecondaryTarget) {
             if (Kind == 'a') {
-              STI = PrimaryIsThumb ? SecondarySTI : PrimarySTI;
-              DisAsm = PrimaryIsThumb ? SecondaryDisAsm : PrimaryDisAsm;
+              STI = PrimaryIsThumb ? SecondaryTarget->SubtargetInfo.get()
+                                   : PrimarySTI;
+              DisAsm = PrimaryIsThumb ? SecondaryTarget->DisAsm.get()
+                                      : PrimaryDisAsm;
             } else if (Kind == 't') {
-              STI = PrimaryIsThumb ? PrimarySTI : SecondarySTI;
-              DisAsm = PrimaryIsThumb ? PrimaryDisAsm : SecondaryDisAsm;
+              STI = PrimaryIsThumb ? PrimarySTI
+                                   : SecondaryTarget->SubtargetInfo.get();
+              DisAsm = PrimaryIsThumb ? PrimaryDisAsm
+                                      : SecondaryTarget->DisAsm.get();
             }
           }
         }
@@ -2022,20 +2118,6 @@
     Features.AddFeature("+all");
   }
 
-  std::unique_ptr<const MCRegisterInfo> MRI(
-      TheTarget->createMCRegInfo(TripleName));
-  if (!MRI)
-    reportError(Obj->getFileName(),
-                "no register info for target " + TripleName);
-
-  // Set up disassembler.
-  MCTargetOptions MCOptions;
-  std::unique_ptr<const MCAsmInfo> AsmInfo(
-      TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
-  if (!AsmInfo)
-    reportError(Obj->getFileName(),
-                "no assembly info for target " + TripleName);
-
   if (MCPU.empty())
     MCPU = Obj->tryGetCPUName().value_or("").str();
 
@@ -2062,57 +2144,23 @@
     }
   }
 
-  std::unique_ptr<const MCSubtargetInfo> STI(
-      TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features.getString()));
-  if (!STI)
-    reportError(Obj->getFileName(),
-                "no subtarget info for target " + TripleName);
-  std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
-  if (!MII)
-    reportError(Obj->getFileName(),
-                "no instruction info for target " + TripleName);
-  MCContext Ctx(Triple(TripleName), AsmInfo.get(), MRI.get(), STI.get());
-  // FIXME: for now initialize MCObjectFileInfo with default values
-  std::unique_ptr<MCObjectFileInfo> MOFI(
-      TheTarget->createMCObjectFileInfo(Ctx, /*PIC=*/false));
-  Ctx.setObjectFileInfo(MOFI.get());
-
-  std::unique_ptr<MCDisassembler> DisAsm(
-      TheTarget->createMCDisassembler(*STI, Ctx));
-  if (!DisAsm)
-    reportError(Obj->getFileName(), "no disassembler for target " + TripleName);
+  DisassemblerTarget PrimaryTarget(TheTarget, *Obj, TripleName, MCPU, Features);
 
   // 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::optional<DisassemblerTarget> SecondaryTarget;
 
-  std::unique_ptr<const MCInstrAnalysis> MIA(
-      TheTarget->createMCInstrAnalysis(MII.get()));
-
-  int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
-  std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
-      Triple(TripleName), AsmPrinterVariant, *AsmInfo, *MII, *MRI));
-  if (!IP)
-    reportError(Obj->getFileName(),
-                "no instruction printer for target " + TripleName);
-  IP->setPrintImmHex(PrintImmHex);
-  IP->setPrintBranchImmAsAddress(true);
-  IP->setSymbolizeOperands(SymbolizeOperands);
-  IP->setMCInstrAnalysis(MIA.get());
-
-  PrettyPrinter &PIP = selectPrettyPrinter(Triple(TripleName));
+  if (isArmElf(*Obj)) {
+    if (!PrimaryTarget.SubtargetInfo->checkFeatures("+mclass")) {
+      if (PrimaryTarget.SubtargetInfo->checkFeatures("+thumb-mode"))
+        Features.AddFeature("-thumb-mode");
+      else
+        Features.AddFeature("+thumb-mode");
+      SecondaryTarget.emplace(PrimaryTarget, Features);
+    }
+  }
 
   const ObjectFile *DbgObj = Obj;
   if (!FetchedBinary.getBinary() && !Obj->hasDebugInfo()) {
@@ -2142,13 +2190,15 @@
   SourcePrinter SP(DbgObj, TheTarget->getName());
 
   for (StringRef Opt : DisassemblerOptions)
-    if (!IP->applyTargetSpecificCLOption(Opt))
+    if (!PrimaryTarget.InstPrinter->applyTargetSpecificCLOption(Opt))
       reportError(Obj->getFileName(),
                   "Unrecognized disassembler option: " + Opt);
 
-  disassembleObject(TheTarget, *Obj, *DbgObj, Ctx, DisAsm.get(),
-                    SecondaryDisAsm.get(), MIA.get(), IP.get(), STI.get(),
-                    SecondarySTI.get(), PIP, SP, InlineRelocs);
+  disassembleObject(TheTarget, *Obj, *DbgObj, *PrimaryTarget.Context,
+                    PrimaryTarget.DisAsm.get(), SecondaryTarget,
+                    PrimaryTarget.InstrAnalysis, PrimaryTarget.InstPrinter,
+                    PrimaryTarget.SubtargetInfo.get(),
+                    *PrimaryTarget.PrettyPrinter, SP, InlineRelocs);
 }
 
 void objdump::printRelocations(const ObjectFile *Obj) {