LLVM 23.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
17namespace llvm {
18namespace objcopy {
19namespace wasm {
20
21using namespace object;
22using SectionPred = std::function<bool(const Section &Sec)>;
23
24static bool isDebugSection(const Section &Sec) {
25 return Sec.Name.starts_with(".debug") || Sec.Name.starts_with("reloc..debug");
26}
27
28static bool isEngineInterpretedSection(const Section &Sec) {
30 Sec.Name.starts_with("metadata.code.");
31}
32
35 for (const Section &Sec : Obj.Sections) {
36 if (Sec.Name == SecName) {
37 ArrayRef<uint8_t> Contents = Sec.Contents;
40 if (!BufferOrErr)
41 return createFileError(Filename, BufferOrErr.takeError());
42 std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr);
43 llvm::copy(Contents, Buf->getBufferStart());
44 if (Error E = Buf->commit())
45 return createFileError(Filename, std::move(E));
46 return Error::success();
47 }
48 }
50 "section '%s' not found", SecName.str().c_str());
51}
52
53static void removeSections(const CommonConfig &Config, Object &Obj) {
54 SectionPred RemovePred = [](const Section &) { return false; };
55
56 // Explicitly-requested sections.
57 if (!Config.ToRemove.empty()) {
58 RemovePred = [&Config](const Section &Sec) {
59 return Config.ToRemove.matches(Sec.Name);
60 };
61 }
62
63 if (Config.StripDebug) {
64 RemovePred = [RemovePred](const Section &Sec) {
65 return RemovePred(Sec) || isDebugSection(Sec);
66 };
67 }
68
69 if (Config.StripAll) {
70 RemovePred = [RemovePred](const Section &Sec) {
71 return RemovePred(Sec) || !isEngineInterpretedSection(Sec);
72 };
73 }
74
75 if (Config.OnlyKeepDebug) {
76 RemovePred = [&Config](const Section &Sec) {
77 // Keep debug sections, unless explicitly requested to remove.
78 // Remove everything else, including known sections.
79 return Config.ToRemove.matches(Sec.Name) || !isDebugSection(Sec);
80 };
81 }
82
83 if (!Config.OnlySection.empty()) {
84 RemovePred = [&Config](const Section &Sec) {
85 // Explicitly keep these sections regardless of previous removes.
86 // Remove everything else, inluding known sections.
87 return !Config.OnlySection.matches(Sec.Name);
88 };
89 }
90
91 if (!Config.KeepSection.empty()) {
92 RemovePred = [&Config, RemovePred](const Section &Sec) {
93 // Explicitly keep these sections regardless of previous removes.
94 if (Config.KeepSection.matches(Sec.Name))
95 return false;
96 // Otherwise defer to RemovePred.
97 return RemovePred(Sec);
98 };
99 }
100
101 Obj.removeSections(RemovePred);
102}
103
104static Error handleArgs(const CommonConfig &Config, Object &Obj) {
105 // Only support AddSection, DumpSection, RemoveSection for now.
106 for (StringRef Flag : Config.DumpSection) {
107 StringRef SecName;
108 StringRef FileName;
109 std::tie(SecName, FileName) = Flag.split("=");
110 if (Error E =
111 dumpSectionToFile(SecName, FileName, Config.InputFilename, Obj))
112 return E;
113 }
114
115 removeSections(Config, Obj);
116
117 for (const NewSectionInfo &NewSection : Config.AddSection) {
118 Section Sec;
120 Sec.Name = NewSection.SectionName;
121
122 llvm::StringRef InputData =
123 llvm::StringRef(NewSection.SectionData->getBufferStart(),
124 NewSection.SectionData->getBufferSize());
125 std::unique_ptr<MemoryBuffer> BufferCopy = MemoryBuffer::getMemBufferCopy(
126 InputData, NewSection.SectionData->getBufferIdentifier());
128 reinterpret_cast<const uint8_t *>(BufferCopy->getBufferStart()),
129 BufferCopy->getBufferSize());
130
131 Obj.addSectionWithOwnedContents(Sec, std::move(BufferCopy));
132 }
133
134 return Error::success();
135}
136
139 Reader TheReader(In);
140 Expected<std::unique_ptr<Object>> ObjOrErr = TheReader.create();
141 if (!ObjOrErr)
142 return createFileError(Config.InputFilename, ObjOrErr.takeError());
143 Object *Obj = ObjOrErr->get();
144 assert(Obj && "Unable to deserialize Wasm object");
145 if (Error E = handleArgs(Config, *Obj))
146 return E;
147 Writer TheWriter(*Obj, Out);
148 if (Error E = TheWriter.write())
149 return createFileError(Config.OutputFilename, std::move(E));
150 return Error::success();
151}
152
153} // end namespace wasm
154} // end namespace objcopy
155} // end namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static cl::opt< std::string > InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"))
static constexpr StringLiteral Filename
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
size - Get the array size.
Definition ArrayRef.h:142
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
reference get()
Returns a reference to the stored T value.
Definition Error.h:582
static LLVM_ABI 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...
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.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
std::string str() const
str - Get the contents as an std::string.
Definition StringRef.h:222
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
bool matches(StringRef S) const
Expected< std::unique_ptr< Object > > create() const
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
static void removeSections(const CommonConfig &Config, Object &Obj)
static bool isEngineInterpretedSection(const Section &Sec)
static Error handleArgs(const CommonConfig &Config, Object &Obj)
static bool isDebugSection(const Section &Sec)
static Error dumpSectionToFile(StringRef SecName, StringRef Filename, StringRef InputFilename, Object &Obj)
LLVM_ABI 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.
std::function< bool(const Section &Sec)> SectionPred
@ WASM_SEC_CUSTOM
Definition Wasm.h:37
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
Definition Error.h:1399
@ invalid_argument
Definition Errc.h:56
OutputIt copy(R &&Range, OutputIt Out)
Definition STLExtras.h:1885
SmallVector< StringRef, 0 > DumpSection
SmallVector< NewSectionInfo, 0 > AddSection
std::shared_ptr< MemoryBuffer > SectionData
ArrayRef< uint8_t > Contents
Definition WasmObject.h:28