WasmObjcopy.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. //===- WasmObjcopy.cpp ----------------------------------------------------===//
  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. #include "llvm/ObjCopy/wasm/WasmObjcopy.h"
  9. #include "WasmObject.h"
  10. #include "WasmReader.h"
  11. #include "WasmWriter.h"
  12. #include "llvm/ObjCopy/CommonConfig.h"
  13. #include "llvm/Support/Errc.h"
  14. #include "llvm/Support/FileOutputBuffer.h"
  15. namespace llvm {
  16. namespace objcopy {
  17. namespace wasm {
  18. using namespace object;
  19. using SectionPred = std::function<bool(const Section &Sec)>;
  20. static bool isDebugSection(const Section &Sec) {
  21. return Sec.Name.startswith(".debug");
  22. }
  23. static bool isLinkerSection(const Section &Sec) {
  24. return Sec.Name.startswith("reloc.") || Sec.Name == "linking";
  25. }
  26. static bool isNameSection(const Section &Sec) { return Sec.Name == "name"; }
  27. // Sections which are known to be "comments" or informational and do not affect
  28. // program semantics.
  29. static bool isCommentSection(const Section &Sec) {
  30. return Sec.Name == "producers";
  31. }
  32. static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
  33. Object &Obj) {
  34. for (const Section &Sec : Obj.Sections) {
  35. if (Sec.Name == SecName) {
  36. ArrayRef<uint8_t> Contents = Sec.Contents;
  37. Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
  38. FileOutputBuffer::create(Filename, Contents.size());
  39. if (!BufferOrErr)
  40. return BufferOrErr.takeError();
  41. std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr);
  42. std::copy(Contents.begin(), Contents.end(), Buf->getBufferStart());
  43. if (Error E = Buf->commit())
  44. return E;
  45. return Error::success();
  46. }
  47. }
  48. return createStringError(errc::invalid_argument, "section '%s' not found",
  49. SecName.str().c_str());
  50. }
  51. static void removeSections(const CommonConfig &Config, Object &Obj) {
  52. SectionPred RemovePred = [](const Section &) { return false; };
  53. // Explicitly-requested sections.
  54. if (!Config.ToRemove.empty()) {
  55. RemovePred = [&Config](const Section &Sec) {
  56. return Config.ToRemove.matches(Sec.Name);
  57. };
  58. }
  59. if (Config.StripDebug) {
  60. RemovePred = [RemovePred](const Section &Sec) {
  61. return RemovePred(Sec) || isDebugSection(Sec);
  62. };
  63. }
  64. if (Config.StripAll) {
  65. RemovePred = [RemovePred](const Section &Sec) {
  66. return RemovePred(Sec) || isDebugSection(Sec) || isLinkerSection(Sec) ||
  67. isNameSection(Sec) || isCommentSection(Sec);
  68. };
  69. }
  70. if (Config.OnlyKeepDebug) {
  71. RemovePred = [&Config](const Section &Sec) {
  72. // Keep debug sections, unless explicitly requested to remove.
  73. // Remove everything else, including known sections.
  74. return Config.ToRemove.matches(Sec.Name) || !isDebugSection(Sec);
  75. };
  76. }
  77. if (!Config.OnlySection.empty()) {
  78. RemovePred = [&Config](const Section &Sec) {
  79. // Explicitly keep these sections regardless of previous removes.
  80. // Remove everything else, inluding known sections.
  81. return !Config.OnlySection.matches(Sec.Name);
  82. };
  83. }
  84. if (!Config.KeepSection.empty()) {
  85. RemovePred = [&Config, RemovePred](const Section &Sec) {
  86. // Explicitly keep these sections regardless of previous removes.
  87. if (Config.KeepSection.matches(Sec.Name))
  88. return false;
  89. // Otherwise defer to RemovePred.
  90. return RemovePred(Sec);
  91. };
  92. }
  93. Obj.removeSections(RemovePred);
  94. }
  95. static Error handleArgs(const CommonConfig &Config, Object &Obj) {
  96. // Only support AddSection, DumpSection, RemoveSection for now.
  97. for (StringRef Flag : Config.DumpSection) {
  98. StringRef SecName;
  99. StringRef FileName;
  100. std::tie(SecName, FileName) = Flag.split("=");
  101. if (Error E = dumpSectionToFile(SecName, FileName, Obj))
  102. return createFileError(FileName, std::move(E));
  103. }
  104. removeSections(Config, Obj);
  105. for (const NewSectionInfo &NewSection : Config.AddSection) {
  106. Section Sec;
  107. Sec.SectionType = llvm::wasm::WASM_SEC_CUSTOM;
  108. Sec.Name = NewSection.SectionName;
  109. llvm::StringRef InputData =
  110. llvm::StringRef(NewSection.SectionData->getBufferStart(),
  111. NewSection.SectionData->getBufferSize());
  112. std::unique_ptr<MemoryBuffer> BufferCopy = MemoryBuffer::getMemBufferCopy(
  113. InputData, NewSection.SectionData->getBufferIdentifier());
  114. Sec.Contents = ArrayRef<uint8_t>(
  115. reinterpret_cast<const uint8_t *>(BufferCopy->getBufferStart()),
  116. BufferCopy->getBufferSize());
  117. Obj.addSectionWithOwnedContents(Sec, std::move(BufferCopy));
  118. }
  119. return Error::success();
  120. }
  121. Error executeObjcopyOnBinary(const CommonConfig &Config, const WasmConfig &,
  122. object::WasmObjectFile &In, raw_ostream &Out) {
  123. Reader TheReader(In);
  124. Expected<std::unique_ptr<Object>> ObjOrErr = TheReader.create();
  125. if (!ObjOrErr)
  126. return createFileError(Config.InputFilename, ObjOrErr.takeError());
  127. Object *Obj = ObjOrErr->get();
  128. assert(Obj && "Unable to deserialize Wasm object");
  129. if (Error E = handleArgs(Config, *Obj))
  130. return E;
  131. Writer TheWriter(*Obj, Out);
  132. if (Error E = TheWriter.write())
  133. return createFileError(Config.OutputFilename, std::move(E));
  134. return Error::success();
  135. }
  136. } // end namespace wasm
  137. } // end namespace objcopy
  138. } // end namespace llvm