llvm-dwp.cpp 7.5 KB

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