LLVM  15.0.0git
WasmObjcopy.cpp
Go to the documentation of this file.
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 
10 #include "WasmObject.h"
11 #include "WasmReader.h"
12 #include "WasmWriter.h"
14 #include "llvm/Support/Errc.h"
16 
17 namespace llvm {
18 namespace objcopy {
19 namespace wasm {
20 
21 using namespace object;
22 using SectionPred = std::function<bool(const Section &Sec)>;
23 
24 static bool isDebugSection(const Section &Sec) {
25  return Sec.Name.startswith(".debug");
26 }
27 
28 static bool isLinkerSection(const Section &Sec) {
29  return Sec.Name.startswith("reloc.") || Sec.Name == "linking";
30 }
31 
32 static bool isNameSection(const Section &Sec) { return Sec.Name == "name"; }
33 
34 // Sections which are known to be "comments" or informational and do not affect
35 // program semantics.
36 static bool isCommentSection(const Section &Sec) {
37  return Sec.Name == "producers";
38 }
39 
40 static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
41  Object &Obj) {
42  for (const Section &Sec : Obj.Sections) {
43  if (Sec.Name == SecName) {
44  ArrayRef<uint8_t> Contents = Sec.Contents;
46  FileOutputBuffer::create(Filename, Contents.size());
47  if (!BufferOrErr)
48  return BufferOrErr.takeError();
49  std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr);
50  std::copy(Contents.begin(), Contents.end(), Buf->getBufferStart());
51  if (Error E = Buf->commit())
52  return E;
53  return Error::success();
54  }
55  }
56  return createStringError(errc::invalid_argument, "section '%s' not found",
57  SecName.str().c_str());
58 }
59 
60 static void removeSections(const CommonConfig &Config, Object &Obj) {
61  SectionPred RemovePred = [](const Section &) { return false; };
62 
63  // Explicitly-requested sections.
64  if (!Config.ToRemove.empty()) {
65  RemovePred = [&Config](const Section &Sec) {
66  return Config.ToRemove.matches(Sec.Name);
67  };
68  }
69 
70  if (Config.StripDebug) {
71  RemovePred = [RemovePred](const Section &Sec) {
72  return RemovePred(Sec) || isDebugSection(Sec);
73  };
74  }
75 
76  if (Config.StripAll) {
77  RemovePred = [RemovePred](const Section &Sec) {
78  return RemovePred(Sec) || isDebugSection(Sec) || isLinkerSection(Sec) ||
79  isNameSection(Sec) || isCommentSection(Sec);
80  };
81  }
82 
83  if (Config.OnlyKeepDebug) {
84  RemovePred = [&Config](const Section &Sec) {
85  // Keep debug sections, unless explicitly requested to remove.
86  // Remove everything else, including known sections.
87  return Config.ToRemove.matches(Sec.Name) || !isDebugSection(Sec);
88  };
89  }
90 
91  if (!Config.OnlySection.empty()) {
92  RemovePred = [&Config](const Section &Sec) {
93  // Explicitly keep these sections regardless of previous removes.
94  // Remove everything else, inluding known sections.
95  return !Config.OnlySection.matches(Sec.Name);
96  };
97  }
98 
99  if (!Config.KeepSection.empty()) {
100  RemovePred = [&Config, RemovePred](const Section &Sec) {
101  // Explicitly keep these sections regardless of previous removes.
102  if (Config.KeepSection.matches(Sec.Name))
103  return false;
104  // Otherwise defer to RemovePred.
105  return RemovePred(Sec);
106  };
107  }
108 
109  Obj.removeSections(RemovePred);
110 }
111 
112 static Error handleArgs(const CommonConfig &Config, Object &Obj) {
113  // Only support AddSection, DumpSection, RemoveSection for now.
114  for (StringRef Flag : Config.DumpSection) {
115  StringRef SecName;
116  StringRef FileName;
117  std::tie(SecName, FileName) = Flag.split("=");
118  if (Error E = dumpSectionToFile(SecName, FileName, Obj))
119  return createFileError(FileName, std::move(E));
120  }
121 
122  removeSections(Config, Obj);
123 
124  for (const NewSectionInfo &NewSection : Config.AddSection) {
125  Section Sec;
127  Sec.Name = NewSection.SectionName;
128 
129  std::unique_ptr<MemoryBuffer> BufferCopy = MemoryBuffer::getMemBufferCopy(
130  NewSection.SectionData->getBufferStart(),
131  NewSection.SectionData->getBufferIdentifier());
132  Sec.Contents = makeArrayRef<uint8_t>(
133  reinterpret_cast<const uint8_t *>(BufferCopy->getBufferStart()),
134  BufferCopy->getBufferSize());
135 
136  Obj.addSectionWithOwnedContents(Sec, std::move(BufferCopy));
137  }
138 
139  return Error::success();
140 }
141 
144  Reader TheReader(In);
145  Expected<std::unique_ptr<Object>> ObjOrErr = TheReader.create();
146  if (!ObjOrErr)
147  return createFileError(Config.InputFilename, ObjOrErr.takeError());
148  Object *Obj = ObjOrErr->get();
149  assert(Obj && "Unable to deserialize Wasm object");
150  if (Error E = handleArgs(Config, *Obj))
151  return E;
152  Writer TheWriter(*Obj, Out);
153  if (Error E = TheWriter.write())
154  return createFileError(Config.OutputFilename, std::move(E));
155  return Error::success();
156 }
157 
158 } // end namespace wasm
159 } // end namespace objcopy
160 } // end namespace llvm
llvm::objcopy::wasm::Object::removeSections
void removeSections(function_ref< bool(const Section &)> ToRemove)
Definition: WasmObject.cpp:27
llvm::errc::invalid_argument
@ invalid_argument
llvm::StringRef::startswith
LLVM_NODISCARD bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:290
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::objcopy::wasm::executeObjcopyOnBinary
Error executeObjcopyOnBinary(const CommonConfig &Config, const WasmConfig &, object::WasmObjectFile &In, raw_ostream &Out)
Apply the transformations described by Config and WasmConfig to In and writes the result into Out.
Definition: WasmObjcopy.cpp:142
llvm::objcopy::CommonConfig::OutputFilename
StringRef OutputFilename
Definition: CommonConfig.h:205
llvm::objcopy::CommonConfig::InputFilename
StringRef InputFilename
Definition: CommonConfig.h:203
llvm::objcopy::wasm::Section::Contents
ArrayRef< uint8_t > Contents
Definition: WasmObject.h:27
llvm::objcopy::NewSectionInfo::SectionName
StringRef SectionName
Definition: CommonConfig.h:196
llvm::objcopy::wasm::Object::addSectionWithOwnedContents
void addSectionWithOwnedContents(Section NewSection, std::unique_ptr< MemoryBuffer > &&Content)
Definition: WasmObject.cpp:21
llvm::objcopy::wasm::SectionPred
std::function< bool(const Section &Sec)> SectionPred
Definition: WasmObjcopy.cpp:22
llvm::objcopy::NameMatcher::matches
bool matches(StringRef S) const
Definition: CommonConfig.h:150
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
Errc.h
FileOutputBuffer.h
WasmWriter.h
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:41
llvm::objcopy::wasm::Object::Sections
std::vector< Section > Sections
Definition: WasmObject.h:33
llvm::objcopy::wasm::Reader
Definition: WasmReader.h:18
llvm::wasm::WASM_SEC_CUSTOM
@ WASM_SEC_CUSTOM
Definition: Wasm.h:242
llvm::objcopy::CommonConfig::OnlySection
NameMatcher OnlySection
Definition: CommonConfig.h:228
llvm::createFileError
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
Definition: Error.h:1320
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::objcopy::NewSectionInfo
Definition: CommonConfig.h:191
llvm::object::WasmObjectFile
Definition: Wasm.h:120
llvm::objcopy::CommonConfig::AddSection
std::vector< NewSectionInfo > AddSection
Definition: CommonConfig.h:222
llvm::objcopy::CommonConfig::KeepSection
NameMatcher KeepSection
Definition: CommonConfig.h:227
llvm::objcopy::CommonConfig::DumpSection
std::vector< StringRef > DumpSection
Definition: CommonConfig.h:223
WasmObjcopy.h
llvm::MCID::Flag
Flag
These should be considered private to the implementation of the MCInstrDesc class.
Definition: MCInstrDesc.h:147
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:54
CommonConfig.h
llvm::StringRef::str
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:249
llvm::objcopy::wasm::isDebugSection
static bool isDebugSection(const Section &Sec)
Definition: WasmObjcopy.cpp:24
llvm::objcopy::NewSectionInfo::SectionData
std::shared_ptr< MemoryBuffer > SectionData
Definition: CommonConfig.h:197
llvm::objcopy::wasm::isLinkerSection
static bool isLinkerSection(const Section &Sec)
Definition: WasmObjcopy.cpp:28
llvm::objcopy::NameMatcher::empty
bool empty() const
Definition: CommonConfig.h:155
llvm::tgtok::In
@ In
Definition: TGLexer.h:51
llvm::objcopy::wasm::Section
Definition: WasmObject.h:22
object
bar al al movzbl eax ret Missed when stored in a memory object
Definition: README.txt:1411
llvm::objcopy::wasm::dumpSectionToFile
static Error dumpSectionToFile(StringRef SecName, StringRef Filename, Object &Obj)
Definition: WasmObjcopy.cpp:40
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::objcopy::CommonConfig::StripDebug
bool StripDebug
Definition: CommonConfig.h:258
function
print Print MemDeps of function
Definition: MemDepPrinter.cpp:82
llvm::objcopy::wasm::Object
Definition: WasmObject.h:30
llvm::ArrayRef< uint8_t >
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::Expected::get
reference get()
Returns a reference to the stored T value.
Definition: Error.h:567
llvm::objcopy::wasm::Reader::create
Expected< std::unique_ptr< Object > > create() const
Definition: WasmReader.cpp:18
llvm::objcopy::WasmConfig
Definition: WasmConfig.h:16
llvm::FileOutputBuffer::create
static Expected< std::unique_ptr< FileOutputBuffer > > create(StringRef FilePath, size_t Size, unsigned Flags=0)
Factory method to create an OutputBuffer object which manages a read/write buffer of the specified si...
Definition: FileOutputBuffer.cpp:156
llvm::objcopy::wasm::removeSections
static void removeSections(const CommonConfig &Config, Object &Obj)
Definition: WasmObjcopy.cpp:60
llvm::createStringError
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1239
llvm::ArrayRef::begin
iterator begin() const
Definition: ArrayRef.h:152
llvm::objcopy::wasm::handleArgs
static Error handleArgs(const CommonConfig &Config, Object &Obj)
Definition: WasmObjcopy.cpp:112
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
llvm::objcopy::wasm::Section::SectionType
uint8_t SectionType
Definition: WasmObject.h:25
llvm::objcopy::wasm::isNameSection
static bool isNameSection(const Section &Sec)
Definition: WasmObjcopy.cpp:32
llvm::objcopy::CommonConfig::StripAll
bool StripAll
Definition: CommonConfig.h:255
WasmReader.h
llvm::objcopy::wasm::Writer
Definition: WasmWriter.h:20
llvm::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition: Error.h:597
llvm::objcopy::wasm::Section::Name
StringRef Name
Definition: WasmObject.h:26
llvm::objcopy::wasm::isCommentSection
static bool isCommentSection(const Section &Sec)
Definition: WasmObjcopy.cpp:36
llvm::objcopy::wasm::Writer::write
Error write()
Definition: WasmWriter.cpp:57
llvm::ArrayRef::size
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:164
llvm::objcopy::CommonConfig::ToRemove
NameMatcher ToRemove
Definition: CommonConfig.h:229
llvm::objcopy::CommonConfig
Definition: CommonConfig.h:201
llvm::MemoryBuffer::getMemBufferCopy
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
Definition: MemoryBuffer.cpp:138
copy
we should consider alternate ways to model stack dependencies Lots of things could be done in WebAssemblyTargetTransformInfo cpp there are numerous optimization related hooks that can be overridden in WebAssemblyTargetLowering Instead of the OptimizeReturned which should consider preserving the returned attribute through to MachineInstrs and extending the MemIntrinsicResults pass to do this optimization on calls too That would also let the WebAssemblyPeephole pass clean up dead defs for such as it does for stores Consider implementing and or getMachineCombinerPatterns Find a clean way to fix the problem which leads to the Shrink Wrapping pass being run after the WebAssembly PEI pass When setting multiple variables to the same we currently get code like const It could be done with a smaller encoding like local tee $pop5 local copy
Definition: README.txt:101
WasmObject.h
llvm::ArrayRef::end
iterator end() const
Definition: ArrayRef.h:153
llvm::objcopy::CommonConfig::OnlyKeepDebug
bool OnlyKeepDebug
Definition: CommonConfig.h:253