Path: blob/main/contrib/llvm-project/llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp
35266 views
//===- WasmObjcopy.cpp ----------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#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"1516namespace llvm {17namespace objcopy {18namespace wasm {1920using namespace object;21using SectionPred = std::function<bool(const Section &Sec)>;2223static bool isDebugSection(const Section &Sec) {24return Sec.Name.starts_with(".debug");25}2627static bool isLinkerSection(const Section &Sec) {28return Sec.Name.starts_with("reloc.") || Sec.Name == "linking";29}3031static bool isNameSection(const Section &Sec) { return Sec.Name == "name"; }3233// Sections which are known to be "comments" or informational and do not affect34// program semantics.35static bool isCommentSection(const Section &Sec) {36return Sec.Name == "producers";37}3839static Error dumpSectionToFile(StringRef SecName, StringRef Filename,40Object &Obj) {41for (const Section &Sec : Obj.Sections) {42if (Sec.Name == SecName) {43ArrayRef<uint8_t> Contents = Sec.Contents;44Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =45FileOutputBuffer::create(Filename, Contents.size());46if (!BufferOrErr)47return BufferOrErr.takeError();48std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr);49std::copy(Contents.begin(), Contents.end(), Buf->getBufferStart());50if (Error E = Buf->commit())51return E;52return Error::success();53}54}55return createStringError(errc::invalid_argument, "section '%s' not found",56SecName.str().c_str());57}5859static void removeSections(const CommonConfig &Config, Object &Obj) {60SectionPred RemovePred = [](const Section &) { return false; };6162// Explicitly-requested sections.63if (!Config.ToRemove.empty()) {64RemovePred = [&Config](const Section &Sec) {65return Config.ToRemove.matches(Sec.Name);66};67}6869if (Config.StripDebug) {70RemovePred = [RemovePred](const Section &Sec) {71return RemovePred(Sec) || isDebugSection(Sec);72};73}7475if (Config.StripAll) {76RemovePred = [RemovePred](const Section &Sec) {77return RemovePred(Sec) || isDebugSection(Sec) || isLinkerSection(Sec) ||78isNameSection(Sec) || isCommentSection(Sec);79};80}8182if (Config.OnlyKeepDebug) {83RemovePred = [&Config](const Section &Sec) {84// Keep debug sections, unless explicitly requested to remove.85// Remove everything else, including known sections.86return Config.ToRemove.matches(Sec.Name) || !isDebugSection(Sec);87};88}8990if (!Config.OnlySection.empty()) {91RemovePred = [&Config](const Section &Sec) {92// Explicitly keep these sections regardless of previous removes.93// Remove everything else, inluding known sections.94return !Config.OnlySection.matches(Sec.Name);95};96}9798if (!Config.KeepSection.empty()) {99RemovePred = [&Config, RemovePred](const Section &Sec) {100// Explicitly keep these sections regardless of previous removes.101if (Config.KeepSection.matches(Sec.Name))102return false;103// Otherwise defer to RemovePred.104return RemovePred(Sec);105};106}107108Obj.removeSections(RemovePred);109}110111static Error handleArgs(const CommonConfig &Config, Object &Obj) {112// Only support AddSection, DumpSection, RemoveSection for now.113for (StringRef Flag : Config.DumpSection) {114StringRef SecName;115StringRef FileName;116std::tie(SecName, FileName) = Flag.split("=");117if (Error E = dumpSectionToFile(SecName, FileName, Obj))118return createFileError(FileName, std::move(E));119}120121removeSections(Config, Obj);122123for (const NewSectionInfo &NewSection : Config.AddSection) {124Section Sec;125Sec.SectionType = llvm::wasm::WASM_SEC_CUSTOM;126Sec.Name = NewSection.SectionName;127128llvm::StringRef InputData =129llvm::StringRef(NewSection.SectionData->getBufferStart(),130NewSection.SectionData->getBufferSize());131std::unique_ptr<MemoryBuffer> BufferCopy = MemoryBuffer::getMemBufferCopy(132InputData, NewSection.SectionData->getBufferIdentifier());133Sec.Contents = ArrayRef<uint8_t>(134reinterpret_cast<const uint8_t *>(BufferCopy->getBufferStart()),135BufferCopy->getBufferSize());136137Obj.addSectionWithOwnedContents(Sec, std::move(BufferCopy));138}139140return Error::success();141}142143Error executeObjcopyOnBinary(const CommonConfig &Config, const WasmConfig &,144object::WasmObjectFile &In, raw_ostream &Out) {145Reader TheReader(In);146Expected<std::unique_ptr<Object>> ObjOrErr = TheReader.create();147if (!ObjOrErr)148return createFileError(Config.InputFilename, ObjOrErr.takeError());149Object *Obj = ObjOrErr->get();150assert(Obj && "Unable to deserialize Wasm object");151if (Error E = handleArgs(Config, *Obj))152return E;153Writer TheWriter(*Obj, Out);154if (Error E = TheWriter.write())155return createFileError(Config.OutputFilename, std::move(E));156return Error::success();157}158159} // end namespace wasm160} // end namespace objcopy161} // end namespace llvm162163164