llvm-dwp.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. //===-- llvm-dwp.cpp - Split DWARF merging tool for llvm ------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // A utility for merging DWARF 5 Split DWARF .dwo files into .dwp (DWARF
  10. // package files).
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/DWP/DWP.h"
  14. #include "llvm/DWP/DWPError.h"
  15. #include "llvm/DWP/DWPStringPool.h"
  16. #include "llvm/MC/MCAsmBackend.h"
  17. #include "llvm/MC/MCAsmInfo.h"
  18. #include "llvm/MC/MCCodeEmitter.h"
  19. #include "llvm/MC/MCContext.h"
  20. #include "llvm/MC/MCInstrInfo.h"
  21. #include "llvm/MC/MCObjectWriter.h"
  22. #include "llvm/MC/MCTargetOptionsCommandFlags.h"
  23. #include "llvm/MC/TargetRegistry.h"
  24. #include "llvm/Support/CommandLine.h"
  25. #include "llvm/Support/FileSystem.h"
  26. #include "llvm/Support/InitLLVM.h"
  27. #include "llvm/Support/TargetSelect.h"
  28. #include "llvm/Support/ToolOutputFile.h"
  29. using namespace llvm;
  30. using namespace llvm::object;
  31. static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags;
  32. cl::OptionCategory DwpCategory("Specific Options");
  33. static cl::list<std::string> InputFiles(cl::Positional, cl::ZeroOrMore,
  34. cl::desc("<input files>"),
  35. cl::cat(DwpCategory));
  36. static cl::list<std::string> ExecFilenames(
  37. "e", cl::ZeroOrMore,
  38. cl::desc("Specify the executable/library files to get the list of *.dwo from"),
  39. cl::value_desc("filename"), cl::cat(DwpCategory));
  40. static cl::opt<std::string> OutputFilename(cl::Required, "o",
  41. cl::desc("Specify the output file."),
  42. cl::value_desc("filename"),
  43. cl::cat(DwpCategory));
  44. static Expected<SmallVector<std::string, 16>>
  45. getDWOFilenames(StringRef ExecFilename) {
  46. auto ErrOrObj = object::ObjectFile::createObjectFile(ExecFilename);
  47. if (!ErrOrObj)
  48. return ErrOrObj.takeError();
  49. const ObjectFile &Obj = *ErrOrObj.get().getBinary();
  50. std::unique_ptr<DWARFContext> DWARFCtx = DWARFContext::create(Obj);
  51. SmallVector<std::string, 16> DWOPaths;
  52. for (const auto &CU : DWARFCtx->compile_units()) {
  53. const DWARFDie &Die = CU->getUnitDIE();
  54. std::string DWOName = dwarf::toString(
  55. Die.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");
  56. if (DWOName.empty())
  57. continue;
  58. std::string DWOCompDir =
  59. dwarf::toString(Die.find(dwarf::DW_AT_comp_dir), "");
  60. if (!DWOCompDir.empty()) {
  61. SmallString<16> DWOPath(std::move(DWOName));
  62. sys::fs::make_absolute(DWOCompDir, DWOPath);
  63. DWOPaths.emplace_back(DWOPath.data(), DWOPath.size());
  64. } else {
  65. DWOPaths.push_back(std::move(DWOName));
  66. }
  67. }
  68. return std::move(DWOPaths);
  69. }
  70. static int error(const Twine &Error, const Twine &Context) {
  71. errs() << Twine("while processing ") + Context + ":\n";
  72. errs() << Twine("error: ") + Error + "\n";
  73. return 1;
  74. }
  75. static Expected<Triple> readTargetTriple(StringRef FileName) {
  76. auto ErrOrObj = object::ObjectFile::createObjectFile(FileName);
  77. if (!ErrOrObj)
  78. return ErrOrObj.takeError();
  79. return ErrOrObj->getBinary()->makeTriple();
  80. }
  81. int main(int argc, char **argv) {
  82. InitLLVM X(argc, argv);
  83. cl::HideUnrelatedOptions({&DwpCategory, &getColorCategory()});
  84. cl::ParseCommandLineOptions(argc, argv, "merge split dwarf (.dwo) files\n");
  85. llvm::InitializeAllTargetInfos();
  86. llvm::InitializeAllTargetMCs();
  87. llvm::InitializeAllTargets();
  88. llvm::InitializeAllAsmPrinters();
  89. std::vector<std::string> DWOFilenames = InputFiles;
  90. for (const auto &ExecFilename : ExecFilenames) {
  91. auto DWOs = getDWOFilenames(ExecFilename);
  92. if (!DWOs) {
  93. logAllUnhandledErrors(DWOs.takeError(), WithColor::error());
  94. return 1;
  95. }
  96. DWOFilenames.insert(DWOFilenames.end(),
  97. std::make_move_iterator(DWOs->begin()),
  98. std::make_move_iterator(DWOs->end()));
  99. }
  100. if (DWOFilenames.empty())
  101. return 0;
  102. std::string ErrorStr;
  103. StringRef Context = "dwarf streamer init";
  104. auto ErrOrTriple = readTargetTriple(DWOFilenames.front());
  105. if (!ErrOrTriple) {
  106. logAllUnhandledErrors(ErrOrTriple.takeError(), WithColor::error());
  107. return 1;
  108. }
  109. // Get the target.
  110. const Target *TheTarget =
  111. TargetRegistry::lookupTarget("", *ErrOrTriple, ErrorStr);
  112. if (!TheTarget)
  113. return error(ErrorStr, Context);
  114. std::string TripleName = ErrOrTriple->getTriple();
  115. // Create all the MC Objects.
  116. std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
  117. if (!MRI)
  118. return error(Twine("no register info for target ") + TripleName, Context);
  119. MCTargetOptions MCOptions = llvm::mc::InitMCTargetOptionsFromFlags();
  120. std::unique_ptr<MCAsmInfo> MAI(
  121. TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
  122. if (!MAI)
  123. return error("no asm info for target " + TripleName, Context);
  124. std::unique_ptr<MCSubtargetInfo> MSTI(
  125. TheTarget->createMCSubtargetInfo(TripleName, "", ""));
  126. if (!MSTI)
  127. return error("no subtarget info for target " + TripleName, Context);
  128. MCContext MC(*ErrOrTriple, MAI.get(), MRI.get(), MSTI.get());
  129. std::unique_ptr<MCObjectFileInfo> MOFI(
  130. TheTarget->createMCObjectFileInfo(MC, /*PIC=*/false));
  131. MC.setObjectFileInfo(MOFI.get());
  132. MCTargetOptions Options;
  133. auto MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, Options);
  134. if (!MAB)
  135. return error("no asm backend for target " + TripleName, Context);
  136. std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo());
  137. if (!MII)
  138. return error("no instr info info for target " + TripleName, Context);
  139. MCCodeEmitter *MCE = TheTarget->createMCCodeEmitter(*MII, *MRI, MC);
  140. if (!MCE)
  141. return error("no code emitter for target " + TripleName, Context);
  142. // Create the output file.
  143. std::error_code EC;
  144. ToolOutputFile OutFile(OutputFilename, EC, sys::fs::OF_None);
  145. Optional<buffer_ostream> BOS;
  146. raw_pwrite_stream *OS;
  147. if (EC)
  148. return error(Twine(OutputFilename) + ": " + EC.message(), Context);
  149. if (OutFile.os().supportsSeeking()) {
  150. OS = &OutFile.os();
  151. } else {
  152. BOS.emplace(OutFile.os());
  153. OS = BOS.getPointer();
  154. }
  155. std::unique_ptr<MCStreamer> MS(TheTarget->createMCObjectStreamer(
  156. *ErrOrTriple, MC, std::unique_ptr<MCAsmBackend>(MAB),
  157. MAB->createObjectWriter(*OS), std::unique_ptr<MCCodeEmitter>(MCE), *MSTI,
  158. MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
  159. /*DWARFMustBeAtTheEnd*/ false));
  160. if (!MS)
  161. return error("no object streamer for target " + TripleName, Context);
  162. if (auto Err = write(*MS, DWOFilenames)) {
  163. logAllUnhandledErrors(std::move(Err), WithColor::error());
  164. return 1;
  165. }
  166. MS->Finish();
  167. OutFile.keep();
  168. return 0;
  169. }