diff options
| author | vvvv <[email protected]> | 2024-02-06 20:01:22 +0300 | 
|---|---|---|
| committer | vvvv <[email protected]> | 2024-02-06 20:22:16 +0300 | 
| commit | 0203b7a9a40828bb2bd4c32029b79ff0ea3d1f8f (patch) | |
| tree | e630d0d5bd0bd29fc8c2d2842ed2cfde781b993a /contrib/libs/llvm16/lib/ObjCopy/wasm/WasmObjcopy.cpp | |
| parent | ba27db76d99d12a4f1c06960b5449423218614c4 (diff) | |
llvm16 targets
Diffstat (limited to 'contrib/libs/llvm16/lib/ObjCopy/wasm/WasmObjcopy.cpp')
| -rw-r--r-- | contrib/libs/llvm16/lib/ObjCopy/wasm/WasmObjcopy.cpp | 162 | 
1 files changed, 162 insertions, 0 deletions
| diff --git a/contrib/libs/llvm16/lib/ObjCopy/wasm/WasmObjcopy.cpp b/contrib/libs/llvm16/lib/ObjCopy/wasm/WasmObjcopy.cpp new file mode 100644 index 00000000000..e5af59f9328 --- /dev/null +++ b/contrib/libs/llvm16/lib/ObjCopy/wasm/WasmObjcopy.cpp @@ -0,0 +1,162 @@ +//===- WasmObjcopy.cpp ----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/ObjCopy/wasm/WasmObjcopy.h" +#include "WasmObject.h" +#include "WasmReader.h" +#include "WasmWriter.h" +#include "llvm/ObjCopy/CommonConfig.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/FileOutputBuffer.h" + +namespace llvm { +namespace objcopy { +namespace wasm { + +using namespace object; +using SectionPred = std::function<bool(const Section &Sec)>; + +static bool isDebugSection(const Section &Sec) { +  return Sec.Name.startswith(".debug"); +} + +static bool isLinkerSection(const Section &Sec) { +  return Sec.Name.startswith("reloc.") || Sec.Name == "linking"; +} + +static bool isNameSection(const Section &Sec) { return Sec.Name == "name"; } + +// Sections which are known to be "comments" or informational and do not affect +// program semantics. +static bool isCommentSection(const Section &Sec) { +  return Sec.Name == "producers"; +} + +static Error dumpSectionToFile(StringRef SecName, StringRef Filename, +                               Object &Obj) { +  for (const Section &Sec : Obj.Sections) { +    if (Sec.Name == SecName) { +      ArrayRef<uint8_t> Contents = Sec.Contents; +      Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr = +          FileOutputBuffer::create(Filename, Contents.size()); +      if (!BufferOrErr) +        return BufferOrErr.takeError(); +      std::unique_ptr<FileOutputBuffer> 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 void removeSections(const CommonConfig &Config, Object &Obj) { +  SectionPred RemovePred = [](const Section &) { return false; }; + +  // Explicitly-requested sections. +  if (!Config.ToRemove.empty()) { +    RemovePred = [&Config](const Section &Sec) { +      return Config.ToRemove.matches(Sec.Name); +    }; +  } + +  if (Config.StripDebug) { +    RemovePred = [RemovePred](const Section &Sec) { +      return RemovePred(Sec) || isDebugSection(Sec); +    }; +  } + +  if (Config.StripAll) { +    RemovePred = [RemovePred](const Section &Sec) { +      return RemovePred(Sec) || isDebugSection(Sec) || isLinkerSection(Sec) || +             isNameSection(Sec) || isCommentSection(Sec); +    }; +  } + +  if (Config.OnlyKeepDebug) { +    RemovePred = [&Config](const Section &Sec) { +      // Keep debug sections, unless explicitly requested to remove. +      // Remove everything else, including known sections. +      return Config.ToRemove.matches(Sec.Name) || !isDebugSection(Sec); +    }; +  } + +  if (!Config.OnlySection.empty()) { +    RemovePred = [&Config](const Section &Sec) { +      // Explicitly keep these sections regardless of previous removes. +      // Remove everything else, inluding known sections. +      return !Config.OnlySection.matches(Sec.Name); +    }; +  } + +  if (!Config.KeepSection.empty()) { +    RemovePred = [&Config, RemovePred](const Section &Sec) { +      // Explicitly keep these sections regardless of previous removes. +      if (Config.KeepSection.matches(Sec.Name)) +        return false; +      // Otherwise defer to RemovePred. +      return RemovePred(Sec); +    }; +  } + +  Obj.removeSections(RemovePred); +} + +static Error handleArgs(const CommonConfig &Config, Object &Obj) { +  // Only support AddSection, DumpSection, RemoveSection for now. +  for (StringRef Flag : Config.DumpSection) { +    StringRef SecName; +    StringRef FileName; +    std::tie(SecName, FileName) = Flag.split("="); +    if (Error E = dumpSectionToFile(SecName, FileName, Obj)) +      return createFileError(FileName, std::move(E)); +  } + +  removeSections(Config, Obj); + +  for (const NewSectionInfo &NewSection : Config.AddSection) { +    Section Sec; +    Sec.SectionType = llvm::wasm::WASM_SEC_CUSTOM; +    Sec.Name = NewSection.SectionName; + +    llvm::StringRef InputData = +        llvm::StringRef(NewSection.SectionData->getBufferStart(), +                        NewSection.SectionData->getBufferSize()); +    std::unique_ptr<MemoryBuffer> BufferCopy = MemoryBuffer::getMemBufferCopy( +        InputData, NewSection.SectionData->getBufferIdentifier()); +    Sec.Contents = ArrayRef<uint8_t>( +        reinterpret_cast<const uint8_t *>(BufferCopy->getBufferStart()), +        BufferCopy->getBufferSize()); + +    Obj.addSectionWithOwnedContents(Sec, std::move(BufferCopy)); +  } + +  return Error::success(); +} + +Error executeObjcopyOnBinary(const CommonConfig &Config, const WasmConfig &, +                             object::WasmObjectFile &In, raw_ostream &Out) { +  Reader TheReader(In); +  Expected<std::unique_ptr<Object>> ObjOrErr = TheReader.create(); +  if (!ObjOrErr) +    return createFileError(Config.InputFilename, ObjOrErr.takeError()); +  Object *Obj = ObjOrErr->get(); +  assert(Obj && "Unable to deserialize Wasm object"); +  if (Error E = handleArgs(Config, *Obj)) +    return E; +  Writer TheWriter(*Obj, Out); +  if (Error E = TheWriter.write()) +    return createFileError(Config.OutputFilename, std::move(E)); +  return Error::success(); +} + +} // end namespace wasm +} // end namespace objcopy +} // end namespace llvm | 
