diff --git a/llvm/test/tools/llvm-objcopy/wasm/add-section.test b/llvm/test/tools/llvm-objcopy/wasm/add-section.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/wasm/add-section.test @@ -0,0 +1,77 @@ +## This actually tests dumping, removal, and addition. +# RUN: yaml2obj %s -o %t +# RUN: llvm-objcopy --dump-section=producers=%t.sec %t +# RUN: llvm-objcopy -R producers %t %t2 +# RUN: llvm-objcopy --add-section=producers=%t.sec %t2 %t3 +# RUN: obj2yaml %t2 | FileCheck --check-prefix=REMOVED %s +# RUN: obj2yaml %t3 | FileCheck %s + +--- !WASM +FileHeader: + Version: 0x00000001 +Sections: + - Type: TYPE + Signatures: + - Index: 0 + ParamTypes: + - I32 + ReturnTypes: + - F32 + - Index: 1 + ParamTypes: + - I32 + - I64 + ReturnTypes: [] + - Type: FUNCTION + FunctionTypes: + - 0 + - 1 + - Type: CODE + Relocations: + - Type: R_WASM_TABLE_INDEX_SLEB + Index: 0 + Offset: 0x00000006 + - Type: R_WASM_FUNCTION_INDEX_LEB + Index: 1 + Offset: 0x00000025 + Functions: + - Index: 0 + Locals: + - Type: I32 + Count: 3 + Body: 418080808000210020002101200111808080800000210220020F0B + - Index: 1 + Locals: + - Type: I32 + Count: 1 + Body: 108180808000210020000F0B + - Type: CUSTOM + Name: linking + Version: 2 + SymbolTable: + - Index: 0 + Kind: FUNCTION + Name: func1 + Flags: [ ] + Function: 0 + - Index: 1 + Kind: FUNCTION + Name: func2 + Flags: [ ] + Function: 1 + - Type: CUSTOM + Name: producers + Tools: + - Name: clang + Version: 9.0.0 + +... + +## Check that the producers section has been removed. +# REMOVED-NOT: producers + +## Check that the producers section has been added back unchanged. +# CHECK: Name: producers +# CHECK-NEXT: Tools: +# CHECK-NEXT: - Name: clang +# CHECK-NEXT: Version: 9.0.0 diff --git a/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp b/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp --- a/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp +++ b/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp @@ -20,8 +20,66 @@ using namespace object; using namespace wasm; +// Adds named custom section with given contents to the object. +static void addSection(Object &Obj, StringRef Name, + ArrayRef Contents) { + Section Sec; + Sec.SectionType = llvm::wasm::WASM_SEC_CUSTOM; + Sec.Name = Name; + Sec.setOwnedContents(Contents); + Obj.addSections(Sec); +} + +static Error dumpSectionToFile(StringRef SecName, StringRef Filename, + Object &Obj) { + for (auto &Sec : Obj.getSections()) { + if (Sec.Name == SecName) { + ArrayRef Contents = Sec.getContents(); + Expected> BufferOrErr = + FileOutputBuffer::create(Filename, Contents.size()); + if (!BufferOrErr) + return BufferOrErr.takeError(); + std::unique_ptr Buf = std::move(*BufferOrErr); + std::copy(Contents.begin(), Contents.end(), Buf->getBufferStart()); + if (Error E = Buf->commit()) + return E; + return Error::success(); + } + } + return createStringError(errc::invalid_argument, "section '%s' not found", + SecName.str().c_str()); +} static Error handleArgs(const CopyConfig &Config, Object &Obj) { + // Only support AddSection, DumpSection, RemoveSection. + // Don't support OnlySection yet because we only operate on custom sections. + Obj.removeSections([&Config](const Section &Sec) { + if (Config.ToRemove.matches(Sec.Name)) + return true; + return false; + }); + + for (const auto &Flag : Config.AddSection) { + StringRef SecName, FileName; + std::tie(SecName, FileName) = Flag.split("="); + auto BufOrErr = MemoryBuffer::getFile(FileName); + if (!BufOrErr) + return createFileError(FileName, errorCodeToError(BufOrErr.getError())); + auto Buf = std::move(*BufOrErr); + addSection( + Obj, SecName, + makeArrayRef(reinterpret_cast(Buf->getBufferStart()), + Buf->getBufferSize())); + } + + for (const auto &Flag : Config.DumpSection) { + StringRef SecName; + StringRef FileName; + std::tie(SecName, FileName) = Flag.split("="); + if (Error E = dumpSectionToFile(SecName, FileName, Obj)) + return E; + } + if (!Config.AddGnuDebugLink.empty() || !Config.BuildIdLinkDir.empty() || Config.BuildIdLinkInput || Config.BuildIdLinkOutput || Config.ExtractPartition || !Config.SplitDWO.empty() || @@ -34,11 +92,10 @@ !Config.UnneededSymbolsToRemove.empty() || !Config.SymbolsToWeaken.empty() || !Config.SymbolsToKeepGlobal.empty() || !Config.SectionsToRename.empty() || !Config.SetSectionAlignment.empty() || - !Config.SetSectionFlags.empty() || !Config.SymbolsToRename.empty() || - !Config.ToRemove.empty() || !Config.DumpSection.empty() || !Config.AddSection.empty()) { + !Config.SetSectionFlags.empty() || !Config.SymbolsToRename.empty()) { return createStringError( llvm::errc::invalid_argument, - "No flags are supported yet other than basic copying"); + "Only add-section, dump-section, and remove-section are supported"); } return Error::success(); }