mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 12:12:47 +01:00
[llvm-objcopy] Refactor CopyConfig structure.
This patch prepares llvm-objcopy to move its implementation into a separate library. To make it possible it is necessary to minimize internal dependencies. Differential Revision: https://reviews.llvm.org/D99055
This commit is contained in:
parent
029935da14
commit
2bc33a6598
@ -22,13 +22,12 @@ tablegen(LLVM StripOpts.inc -gen-opt-parser-defs)
|
||||
add_public_tablegen_target(StripOptsTableGen)
|
||||
|
||||
add_llvm_tool(llvm-objcopy
|
||||
CopyConfig.cpp
|
||||
ConfigManager.cpp
|
||||
llvm-objcopy.cpp
|
||||
COFF/COFFObjcopy.cpp
|
||||
COFF/Object.cpp
|
||||
COFF/Reader.cpp
|
||||
COFF/Writer.cpp
|
||||
ELF/ELFConfig.cpp
|
||||
ELF/ELFObjcopy.cpp
|
||||
ELF/Object.cpp
|
||||
MachO/MachOObjcopy.cpp
|
||||
|
21
tools/llvm-objcopy/COFF/COFFConfig.h
Normal file
21
tools/llvm-objcopy/COFF/COFFConfig.h
Normal file
@ -0,0 +1,21 @@
|
||||
//===- COFFConfig.h ---------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVM_OBJCOPY_COFF_COFFCONFIG_H
|
||||
#define LLVM_TOOLS_LLVM_OBJCOPY_COFF_COFFCONFIG_H
|
||||
|
||||
namespace llvm {
|
||||
namespace objcopy {
|
||||
|
||||
// Coff specific configuration for copying/stripping a single file.
|
||||
struct COFFConfig {};
|
||||
|
||||
} // namespace objcopy
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_TOOLS_LLVM_OBJCOPY_COFF_COFFCONFIG_H
|
@ -7,7 +7,8 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "COFFObjcopy.h"
|
||||
#include "CopyConfig.h"
|
||||
#include "COFFConfig.h"
|
||||
#include "CommonConfig.h"
|
||||
#include "Object.h"
|
||||
#include "Reader.h"
|
||||
#include "Writer.h"
|
||||
@ -130,7 +131,7 @@ static void setSectionFlags(Section &Sec, SectionFlag AllFlags) {
|
||||
Sec.Header.Characteristics = NewCharacteristics;
|
||||
}
|
||||
|
||||
static Error handleArgs(const CopyConfig &Config, Object &Obj) {
|
||||
static Error handleArgs(const CommonConfig &Config, Object &Obj) {
|
||||
// Perform the actual section removals.
|
||||
Obj.removeSections([&Config](const Section &Sec) {
|
||||
// Contrary to --only-keep-debug, --only-section fully removes sections that
|
||||
@ -248,28 +249,11 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
|
||||
if (Error E = addGnuDebugLink(Obj, Config.AddGnuDebugLink))
|
||||
return E;
|
||||
|
||||
if (Config.AllowBrokenLinks || !Config.SplitDWO.empty() ||
|
||||
!Config.SymbolsPrefix.empty() || !Config.AllocSectionsPrefix.empty() ||
|
||||
!Config.DumpSection.empty() || !Config.KeepSection.empty() ||
|
||||
Config.NewSymbolVisibility || !Config.SymbolsToGlobalize.empty() ||
|
||||
!Config.SymbolsToKeep.empty() || !Config.SymbolsToLocalize.empty() ||
|
||||
!Config.SymbolsToWeaken.empty() || !Config.SymbolsToKeepGlobal.empty() ||
|
||||
!Config.SectionsToRename.empty() || !Config.SetSectionAlignment.empty() ||
|
||||
Config.ExtractDWO || Config.LocalizeHidden || Config.PreserveDates ||
|
||||
Config.StripDWO || Config.StripNonAlloc || Config.StripSections ||
|
||||
Config.StripSwiftSymbols || Config.KeepUndefined || Config.Weaken ||
|
||||
Config.DecompressDebugSections ||
|
||||
Config.DiscardMode == DiscardType::Locals ||
|
||||
!Config.SymbolsToAdd.empty() || Config.EntryExpr) {
|
||||
return createStringError(llvm::errc::invalid_argument,
|
||||
"option not supported by llvm-objcopy for COFF");
|
||||
}
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error executeObjcopyOnBinary(const CopyConfig &Config, COFFObjectFile &In,
|
||||
raw_ostream &Out) {
|
||||
Error executeObjcopyOnBinary(const CommonConfig &Config, const COFFConfig &,
|
||||
COFFObjectFile &In, raw_ostream &Out) {
|
||||
COFFReader Reader(In);
|
||||
Expected<std::unique_ptr<Object>> ObjOrErr = Reader.create();
|
||||
if (!ObjOrErr)
|
||||
|
@ -18,10 +18,12 @@ class COFFObjectFile;
|
||||
} // end namespace object
|
||||
|
||||
namespace objcopy {
|
||||
struct CopyConfig;
|
||||
struct CommonConfig;
|
||||
struct COFFConfig;
|
||||
|
||||
namespace coff {
|
||||
Error executeObjcopyOnBinary(const CopyConfig &Config,
|
||||
|
||||
Error executeObjcopyOnBinary(const CommonConfig &Config, const COFFConfig &,
|
||||
object::COFFObjectFile &In, raw_ostream &Out);
|
||||
|
||||
} // end namespace coff
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===- CopyConfig.h -------------------------------------------------------===//
|
||||
//===- CommonConfig.h -------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -6,20 +6,16 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVM_OBJCOPY_COPY_CONFIG_H
|
||||
#define LLVM_TOOLS_LLVM_OBJCOPY_COPY_CONFIG_H
|
||||
#ifndef LLVM_TOOLS_LLVM_OBJCOPY_COMMONCONFIG_H
|
||||
#define LLVM_TOOLS_LLVM_OBJCOPY_COMMONCONFIG_H
|
||||
|
||||
#include "ELF/ELFConfig.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/BitmaskEnum.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Object/ELFTypes.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/GlobPattern.h"
|
||||
#include "llvm/Support/Regex.h"
|
||||
// Necessary for llvm::DebugCompressionType::None
|
||||
@ -99,7 +95,7 @@ enum class MatchStyle {
|
||||
|
||||
class NameOrPattern {
|
||||
StringRef Name;
|
||||
// Regex is shared between multiple CopyConfig instances.
|
||||
// Regex is shared between multiple CommonConfig instances.
|
||||
std::shared_ptr<Regex> R;
|
||||
std::shared_ptr<GlobPattern> G;
|
||||
bool IsPositiveMatch = true;
|
||||
@ -146,10 +142,7 @@ public:
|
||||
};
|
||||
|
||||
// Configuration for copying/stripping a single file.
|
||||
struct CopyConfig {
|
||||
// Format-specific options to be initialized lazily when needed.
|
||||
Optional<elf::ELFCopyConfig> ELF;
|
||||
|
||||
struct CommonConfig {
|
||||
// Main input/output options
|
||||
StringRef InputFilename;
|
||||
FileFormat InputFormat = FileFormat::Unspecified;
|
||||
@ -168,12 +161,10 @@ struct CopyConfig {
|
||||
StringRef SymbolsPrefix;
|
||||
StringRef AllocSectionsPrefix;
|
||||
DiscardType DiscardMode = DiscardType::None;
|
||||
Optional<StringRef> NewSymbolVisibility;
|
||||
|
||||
// Repeated options
|
||||
std::vector<StringRef> AddSection;
|
||||
std::vector<StringRef> DumpSection;
|
||||
std::vector<StringRef> SymbolsToAdd;
|
||||
std::vector<StringRef> RPathToAdd;
|
||||
std::vector<StringRef> RPathToPrepend;
|
||||
DenseMap<StringRef, StringRef> RPathsToUpdate;
|
||||
@ -233,55 +224,9 @@ struct CopyConfig {
|
||||
bool RemoveAllRpaths = false;
|
||||
|
||||
DebugCompressionType CompressionType = DebugCompressionType::None;
|
||||
|
||||
// parseELFConfig performs ELF-specific command-line parsing. Fills `ELF` on
|
||||
// success or returns an Error otherwise.
|
||||
Error parseELFConfig() {
|
||||
if (!ELF) {
|
||||
Expected<elf::ELFCopyConfig> ELFConfig = elf::parseConfig(*this);
|
||||
if (!ELFConfig)
|
||||
return ELFConfig.takeError();
|
||||
ELF = *ELFConfig;
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
};
|
||||
|
||||
// Configuration for the overall invocation of this tool. When invoked as
|
||||
// objcopy, will always contain exactly one CopyConfig. When invoked as strip,
|
||||
// will contain one or more CopyConfigs.
|
||||
struct DriverConfig {
|
||||
SmallVector<CopyConfig, 1> CopyConfigs;
|
||||
BumpPtrAllocator Alloc;
|
||||
};
|
||||
|
||||
// ParseObjcopyOptions returns the config and sets the input arguments. If a
|
||||
// help flag is set then ParseObjcopyOptions will print the help messege and
|
||||
// exit. ErrorCallback is used to handle recoverable errors. An Error returned
|
||||
// by the callback aborts the parsing and is then returned by this function.
|
||||
Expected<DriverConfig>
|
||||
parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
|
||||
llvm::function_ref<Error(Error)> ErrorCallback);
|
||||
|
||||
// ParseInstallNameToolOptions returns the config and sets the input arguments.
|
||||
// If a help flag is set then ParseInstallNameToolOptions will print the help
|
||||
// messege and exit.
|
||||
Expected<DriverConfig>
|
||||
parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr);
|
||||
|
||||
// ParseBitcodeStripOptions returns the config and sets the input arguments.
|
||||
// If a help flag is set then ParseBitcodeStripOptions will print the help
|
||||
// messege and exit.
|
||||
Expected<DriverConfig> parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr);
|
||||
|
||||
// ParseStripOptions returns the config and sets the input arguments. If a
|
||||
// help flag is set then ParseStripOptions will print the help messege and
|
||||
// exit. ErrorCallback is used to handle recoverable errors. An Error returned
|
||||
// by the callback aborts the parsing and is then returned by this function.
|
||||
Expected<DriverConfig>
|
||||
parseStripOptions(ArrayRef<const char *> ArgsArr,
|
||||
llvm::function_ref<Error(Error)> ErrorCallback);
|
||||
} // namespace objcopy
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
#endif // LLVM_TOOLS_LLVM_OBJCOPY_COMMONCONFIG_H
|
@ -1,4 +1,4 @@
|
||||
//===- CopyConfig.cpp -----------------------------------------------------===//
|
||||
//===- ConfigManager.cpp --------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -6,8 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CopyConfig.h"
|
||||
|
||||
#include "ConfigManager.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
@ -18,6 +17,7 @@
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Compression.h"
|
||||
#include "llvm/Support/Errc.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/StringSaver.h"
|
||||
#include <memory>
|
||||
@ -466,6 +466,190 @@ static void printHelp(const opt::OptTable &OptTable, raw_ostream &OS,
|
||||
OS << "\nPass @FILE as argument to read options from FILE.\n";
|
||||
}
|
||||
|
||||
static Expected<NewSymbolInfo> parseNewSymbolInfo(StringRef FlagValue,
|
||||
uint8_t DefaultVisibility) {
|
||||
// Parse value given with --add-symbol option and create the
|
||||
// new symbol if possible. The value format for --add-symbol is:
|
||||
//
|
||||
// <name>=[<section>:]<value>[,<flags>]
|
||||
//
|
||||
// where:
|
||||
// <name> - symbol name, can be empty string
|
||||
// <section> - optional section name. If not given ABS symbol is created
|
||||
// <value> - symbol value, can be decimal or hexadecimal number prefixed
|
||||
// with 0x.
|
||||
// <flags> - optional flags affecting symbol type, binding or visibility:
|
||||
// The following are currently supported:
|
||||
//
|
||||
// global, local, weak, default, hidden, file, section, object,
|
||||
// indirect-function.
|
||||
//
|
||||
// The following flags are ignored and provided for GNU
|
||||
// compatibility only:
|
||||
//
|
||||
// warning, debug, constructor, indirect, synthetic,
|
||||
// unique-object, before=<symbol>.
|
||||
NewSymbolInfo SI;
|
||||
StringRef Value;
|
||||
std::tie(SI.SymbolName, Value) = FlagValue.split('=');
|
||||
if (Value.empty())
|
||||
return createStringError(
|
||||
errc::invalid_argument,
|
||||
"bad format for --add-symbol, missing '=' after '%s'",
|
||||
SI.SymbolName.str().c_str());
|
||||
|
||||
if (Value.contains(':')) {
|
||||
std::tie(SI.SectionName, Value) = Value.split(':');
|
||||
if (SI.SectionName.empty() || Value.empty())
|
||||
return createStringError(
|
||||
errc::invalid_argument,
|
||||
"bad format for --add-symbol, missing section name or symbol value");
|
||||
}
|
||||
|
||||
SmallVector<StringRef, 6> Flags;
|
||||
Value.split(Flags, ',');
|
||||
if (Flags[0].getAsInteger(0, SI.Value))
|
||||
return createStringError(errc::invalid_argument, "bad symbol value: '%s'",
|
||||
Flags[0].str().c_str());
|
||||
|
||||
SI.Visibility = DefaultVisibility;
|
||||
using Functor = std::function<void(void)>;
|
||||
SmallVector<StringRef, 6> UnsupportedFlags;
|
||||
for (size_t I = 1, NumFlags = Flags.size(); I < NumFlags; ++I)
|
||||
static_cast<Functor>(
|
||||
StringSwitch<Functor>(Flags[I])
|
||||
.CaseLower("global", [&SI] { SI.Bind = ELF::STB_GLOBAL; })
|
||||
.CaseLower("local", [&SI] { SI.Bind = ELF::STB_LOCAL; })
|
||||
.CaseLower("weak", [&SI] { SI.Bind = ELF::STB_WEAK; })
|
||||
.CaseLower("default", [&SI] { SI.Visibility = ELF::STV_DEFAULT; })
|
||||
.CaseLower("hidden", [&SI] { SI.Visibility = ELF::STV_HIDDEN; })
|
||||
.CaseLower("protected",
|
||||
[&SI] { SI.Visibility = ELF::STV_PROTECTED; })
|
||||
.CaseLower("file", [&SI] { SI.Type = ELF::STT_FILE; })
|
||||
.CaseLower("section", [&SI] { SI.Type = ELF::STT_SECTION; })
|
||||
.CaseLower("object", [&SI] { SI.Type = ELF::STT_OBJECT; })
|
||||
.CaseLower("function", [&SI] { SI.Type = ELF::STT_FUNC; })
|
||||
.CaseLower("indirect-function",
|
||||
[&SI] { SI.Type = ELF::STT_GNU_IFUNC; })
|
||||
.CaseLower("debug", [] {})
|
||||
.CaseLower("constructor", [] {})
|
||||
.CaseLower("warning", [] {})
|
||||
.CaseLower("indirect", [] {})
|
||||
.CaseLower("synthetic", [] {})
|
||||
.CaseLower("unique-object", [] {})
|
||||
.StartsWithLower("before", [] {})
|
||||
.Default([&] { UnsupportedFlags.push_back(Flags[I]); }))();
|
||||
if (!UnsupportedFlags.empty())
|
||||
return createStringError(errc::invalid_argument,
|
||||
"unsupported flag%s for --add-symbol: '%s'",
|
||||
UnsupportedFlags.size() > 1 ? "s" : "",
|
||||
join(UnsupportedFlags, "', '").c_str());
|
||||
return SI;
|
||||
}
|
||||
|
||||
Expected<const ELFConfig &> ConfigManager::getELFConfig() const {
|
||||
if (!ELF) {
|
||||
if (Common.StripSwiftSymbols || Common.KeepUndefined)
|
||||
return createStringError(llvm::errc::invalid_argument,
|
||||
"option not supported by llvm-objcopy for ELF");
|
||||
|
||||
// Parse lazy options.
|
||||
ELFConfig ResConfig;
|
||||
|
||||
if (NewSymbolVisibility) {
|
||||
const uint8_t Invalid = 0xff;
|
||||
ResConfig.NewSymbolVisibility =
|
||||
StringSwitch<uint8_t>(*NewSymbolVisibility)
|
||||
.Case("default", ELF::STV_DEFAULT)
|
||||
.Case("hidden", ELF::STV_HIDDEN)
|
||||
.Case("internal", ELF::STV_INTERNAL)
|
||||
.Case("protected", ELF::STV_PROTECTED)
|
||||
.Default(Invalid);
|
||||
|
||||
if (ResConfig.NewSymbolVisibility == Invalid)
|
||||
return createStringError(errc::invalid_argument,
|
||||
"'%s' is not a valid symbol visibility",
|
||||
NewSymbolVisibility->str().c_str());
|
||||
}
|
||||
|
||||
for (StringRef Arg : SymbolsToAdd) {
|
||||
Expected<NewSymbolInfo> NSI = parseNewSymbolInfo(
|
||||
Arg,
|
||||
ResConfig.NewSymbolVisibility.getValueOr((uint8_t)ELF::STV_DEFAULT));
|
||||
if (!NSI)
|
||||
return NSI.takeError();
|
||||
ResConfig.SymbolsToAdd.push_back(*NSI);
|
||||
}
|
||||
|
||||
ELF = std::move(ResConfig);
|
||||
}
|
||||
|
||||
return *ELF;
|
||||
}
|
||||
|
||||
Expected<const COFFConfig &> ConfigManager::getCOFFConfig() const {
|
||||
if (Common.AllowBrokenLinks || !Common.SplitDWO.empty() ||
|
||||
!Common.SymbolsPrefix.empty() || !Common.AllocSectionsPrefix.empty() ||
|
||||
!Common.DumpSection.empty() || !Common.KeepSection.empty() ||
|
||||
NewSymbolVisibility || !Common.SymbolsToGlobalize.empty() ||
|
||||
!Common.SymbolsToKeep.empty() || !Common.SymbolsToLocalize.empty() ||
|
||||
!Common.SymbolsToWeaken.empty() || !Common.SymbolsToKeepGlobal.empty() ||
|
||||
!Common.SectionsToRename.empty() || !Common.SetSectionAlignment.empty() ||
|
||||
Common.ExtractDWO || Common.LocalizeHidden || Common.PreserveDates ||
|
||||
Common.StripDWO || Common.StripNonAlloc || Common.StripSections ||
|
||||
Common.StripSwiftSymbols || Common.KeepUndefined || Common.Weaken ||
|
||||
Common.DecompressDebugSections ||
|
||||
Common.DiscardMode == DiscardType::Locals || !SymbolsToAdd.empty() ||
|
||||
Common.EntryExpr) {
|
||||
return createStringError(llvm::errc::invalid_argument,
|
||||
"option not supported by llvm-objcopy for COFF");
|
||||
}
|
||||
|
||||
return COFF;
|
||||
}
|
||||
|
||||
Expected<const MachOConfig &> ConfigManager::getMachOConfig() const {
|
||||
if (Common.AllowBrokenLinks || !Common.SplitDWO.empty() ||
|
||||
!Common.SymbolsPrefix.empty() || !Common.AllocSectionsPrefix.empty() ||
|
||||
!Common.KeepSection.empty() || NewSymbolVisibility ||
|
||||
!Common.SymbolsToGlobalize.empty() || !Common.SymbolsToKeep.empty() ||
|
||||
!Common.SymbolsToLocalize.empty() || !Common.SymbolsToWeaken.empty() ||
|
||||
!Common.SymbolsToKeepGlobal.empty() || !Common.SectionsToRename.empty() ||
|
||||
!Common.UnneededSymbolsToRemove.empty() ||
|
||||
!Common.SetSectionAlignment.empty() || !Common.SetSectionFlags.empty() ||
|
||||
Common.ExtractDWO || Common.LocalizeHidden || Common.PreserveDates ||
|
||||
Common.StripAllGNU || Common.StripDWO || Common.StripNonAlloc ||
|
||||
Common.StripSections || Common.Weaken || Common.DecompressDebugSections ||
|
||||
Common.StripUnneeded || Common.DiscardMode == DiscardType::Locals ||
|
||||
!SymbolsToAdd.empty() || Common.EntryExpr) {
|
||||
return createStringError(llvm::errc::invalid_argument,
|
||||
"option not supported by llvm-objcopy for MachO");
|
||||
}
|
||||
|
||||
return MachO;
|
||||
}
|
||||
|
||||
Expected<const WasmConfig &> ConfigManager::getWasmConfig() const {
|
||||
if (!Common.AddGnuDebugLink.empty() || Common.ExtractPartition ||
|
||||
!Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
|
||||
!Common.AllocSectionsPrefix.empty() ||
|
||||
Common.DiscardMode != DiscardType::None || NewSymbolVisibility ||
|
||||
!SymbolsToAdd.empty() || !Common.RPathToAdd.empty() ||
|
||||
!Common.OnlySection.empty() || !Common.SymbolsToGlobalize.empty() ||
|
||||
!Common.SymbolsToKeep.empty() || !Common.SymbolsToLocalize.empty() ||
|
||||
!Common.SymbolsToRemove.empty() ||
|
||||
!Common.UnneededSymbolsToRemove.empty() ||
|
||||
!Common.SymbolsToWeaken.empty() || !Common.SymbolsToKeepGlobal.empty() ||
|
||||
!Common.SectionsToRename.empty() || !Common.SetSectionAlignment.empty() ||
|
||||
!Common.SetSectionFlags.empty() || !Common.SymbolsToRename.empty()) {
|
||||
return createStringError(
|
||||
llvm::errc::invalid_argument,
|
||||
"only add-section, dump-section, and remove-section are supported");
|
||||
}
|
||||
|
||||
return Wasm;
|
||||
}
|
||||
|
||||
// ParseObjcopyOptions returns the config and sets the input arguments. If a
|
||||
// help flag is set then ParseObjcopyOptions will print the help messege and
|
||||
// exit.
|
||||
@ -519,7 +703,8 @@ parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
|
||||
return createStringError(errc::invalid_argument,
|
||||
"too many positional arguments");
|
||||
|
||||
CopyConfig Config;
|
||||
ConfigManager ConfigMgr;
|
||||
CommonConfig &Config = ConfigMgr.Common;
|
||||
Config.InputFilename = Positional[0];
|
||||
Config.OutputFilename = Positional[Positional.size() == 1 ? 0 : 1];
|
||||
if (InputArgs.hasArg(OBJCOPY_target) &&
|
||||
@ -559,7 +744,7 @@ parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
|
||||
.Default(FileFormat::Unspecified);
|
||||
|
||||
if (InputArgs.hasArg(OBJCOPY_new_symbol_visibility))
|
||||
Config.NewSymbolVisibility =
|
||||
ConfigMgr.NewSymbolVisibility =
|
||||
InputArgs.getLastArgValue(OBJCOPY_new_symbol_visibility);
|
||||
|
||||
Config.OutputFormat = StringSwitch<FileFormat>(OutputFormat)
|
||||
@ -808,7 +993,7 @@ parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
|
||||
SymbolMatchStyle, ErrorCallback))
|
||||
return std::move(E);
|
||||
for (auto Arg : InputArgs.filtered(OBJCOPY_add_symbol))
|
||||
Config.SymbolsToAdd.push_back(Arg->getValue());
|
||||
ConfigMgr.SymbolsToAdd.push_back(Arg->getValue());
|
||||
|
||||
Config.AllowBrokenLinks = InputArgs.hasArg(OBJCOPY_allow_broken_links);
|
||||
|
||||
@ -862,7 +1047,7 @@ parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
|
||||
"cannot specify --extract-partition together with "
|
||||
"--extract-main-partition");
|
||||
|
||||
DC.CopyConfigs.push_back(std::move(Config));
|
||||
DC.CopyConfigs.push_back(std::move(ConfigMgr));
|
||||
return std::move(DC);
|
||||
}
|
||||
|
||||
@ -872,7 +1057,8 @@ parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
|
||||
Expected<DriverConfig>
|
||||
parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) {
|
||||
DriverConfig DC;
|
||||
CopyConfig Config;
|
||||
ConfigManager ConfigMgr;
|
||||
CommonConfig &Config = ConfigMgr.Common;
|
||||
InstallNameToolOptTable T;
|
||||
unsigned MissingArgumentIndex, MissingArgumentCount;
|
||||
llvm::opt::InputArgList InputArgs =
|
||||
@ -996,14 +1182,15 @@ parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) {
|
||||
Config.InputFilename = Positional[0];
|
||||
Config.OutputFilename = Positional[0];
|
||||
|
||||
DC.CopyConfigs.push_back(std::move(Config));
|
||||
DC.CopyConfigs.push_back(std::move(ConfigMgr));
|
||||
return std::move(DC);
|
||||
}
|
||||
|
||||
Expected<DriverConfig>
|
||||
parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr) {
|
||||
DriverConfig DC;
|
||||
CopyConfig Config;
|
||||
ConfigManager ConfigMgr;
|
||||
CommonConfig &Config = ConfigMgr.Common;
|
||||
BitcodeStripOptTable T;
|
||||
unsigned MissingArgumentIndex, MissingArgumentCount;
|
||||
opt::InputArgList InputArgs =
|
||||
@ -1040,7 +1227,7 @@ parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr) {
|
||||
Config.InputFilename = Positional[0];
|
||||
Config.OutputFilename = Positional[0];
|
||||
|
||||
DC.CopyConfigs.push_back(std::move(Config));
|
||||
DC.CopyConfigs.push_back(std::move(ConfigMgr));
|
||||
return std::move(DC);
|
||||
}
|
||||
|
||||
@ -1086,7 +1273,8 @@ parseStripOptions(ArrayRef<const char *> ArgsArr,
|
||||
errc::invalid_argument,
|
||||
"multiple input files cannot be used in combination with -o");
|
||||
|
||||
CopyConfig Config;
|
||||
ConfigManager ConfigMgr;
|
||||
CommonConfig &Config = ConfigMgr.Common;
|
||||
|
||||
if (InputArgs.hasArg(STRIP_regex) && InputArgs.hasArg(STRIP_wildcard))
|
||||
return createStringError(errc::invalid_argument,
|
||||
@ -1159,7 +1347,7 @@ parseStripOptions(ArrayRef<const char *> ArgsArr,
|
||||
Config.InputFilename = Positional[0];
|
||||
Config.OutputFilename =
|
||||
InputArgs.getLastArgValue(STRIP_output, Positional[0]);
|
||||
DC.CopyConfigs.push_back(std::move(Config));
|
||||
DC.CopyConfigs.push_back(std::move(ConfigMgr));
|
||||
} else {
|
||||
StringMap<unsigned> InputFiles;
|
||||
for (StringRef Filename : Positional) {
|
||||
@ -1175,7 +1363,7 @@ parseStripOptions(ArrayRef<const char *> ArgsArr,
|
||||
}
|
||||
Config.InputFilename = Filename;
|
||||
Config.OutputFilename = Filename;
|
||||
DC.CopyConfigs.push_back(Config);
|
||||
DC.CopyConfigs.push_back(ConfigMgr);
|
||||
}
|
||||
}
|
||||
|
84
tools/llvm-objcopy/ConfigManager.h
Normal file
84
tools/llvm-objcopy/ConfigManager.h
Normal file
@ -0,0 +1,84 @@
|
||||
//===- ConfigManager.h ----------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVM_OBJCOPY_CONFIGMANAGER_H
|
||||
#define LLVM_TOOLS_LLVM_OBJCOPY_CONFIGMANAGER_H
|
||||
|
||||
#include "COFF/COFFConfig.h"
|
||||
#include "CommonConfig.h"
|
||||
#include "ELF/ELFConfig.h"
|
||||
#include "MachO/MachOConfig.h"
|
||||
#include "MultiFormatConfig.h"
|
||||
#include "wasm/WasmConfig.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
namespace objcopy {
|
||||
|
||||
// ConfigManager keeps all configurations and prepare
|
||||
// format-specific options.
|
||||
struct ConfigManager : public MultiFormatConfig {
|
||||
virtual ~ConfigManager() {}
|
||||
|
||||
const CommonConfig &getCommonConfig() const override { return Common; }
|
||||
Expected<const ELFConfig &> getELFConfig() const override;
|
||||
Expected<const COFFConfig &> getCOFFConfig() const override;
|
||||
Expected<const MachOConfig &> getMachOConfig() const override;
|
||||
Expected<const WasmConfig &> getWasmConfig() const override;
|
||||
|
||||
// String representation for lazy ELF options.
|
||||
std::vector<StringRef> SymbolsToAdd;
|
||||
Optional<StringRef> NewSymbolVisibility;
|
||||
|
||||
// All configs.
|
||||
CommonConfig Common;
|
||||
mutable Optional<ELFConfig> ELF;
|
||||
COFFConfig COFF;
|
||||
MachOConfig MachO;
|
||||
WasmConfig Wasm;
|
||||
};
|
||||
|
||||
// Configuration for the overall invocation of this tool. When invoked as
|
||||
// objcopy, will always contain exactly one CopyConfig. When invoked as strip,
|
||||
// will contain one or more CopyConfigs.
|
||||
struct DriverConfig {
|
||||
SmallVector<ConfigManager, 1> CopyConfigs;
|
||||
BumpPtrAllocator Alloc;
|
||||
};
|
||||
|
||||
// ParseObjcopyOptions returns the config and sets the input arguments. If a
|
||||
// help flag is set then ParseObjcopyOptions will print the help messege and
|
||||
// exit. ErrorCallback is used to handle recoverable errors. An Error returned
|
||||
// by the callback aborts the parsing and is then returned by this function.
|
||||
Expected<DriverConfig>
|
||||
parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
|
||||
llvm::function_ref<Error(Error)> ErrorCallback);
|
||||
|
||||
// ParseInstallNameToolOptions returns the config and sets the input arguments.
|
||||
// If a help flag is set then ParseInstallNameToolOptions will print the help
|
||||
// messege and exit.
|
||||
Expected<DriverConfig>
|
||||
parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr);
|
||||
|
||||
// ParseBitcodeStripOptions returns the config and sets the input arguments.
|
||||
// If a help flag is set then ParseBitcodeStripOptions will print the help
|
||||
// messege and exit.
|
||||
Expected<DriverConfig> parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr);
|
||||
|
||||
// ParseStripOptions returns the config and sets the input arguments. If a
|
||||
// help flag is set then ParseStripOptions will print the help messege and
|
||||
// exit. ErrorCallback is used to handle recoverable errors. An Error returned
|
||||
// by the callback aborts the parsing and is then returned by this function.
|
||||
Expected<DriverConfig>
|
||||
parseStripOptions(ArrayRef<const char *> ArgsArr,
|
||||
llvm::function_ref<Error(Error)> ErrorCallback);
|
||||
} // namespace objcopy
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_TOOLS_LLVM_OBJCOPY_CONFIGMANAGER_H
|
@ -1,133 +0,0 @@
|
||||
//===- ELFConfig.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 "CopyConfig.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Support/Errc.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace objcopy {
|
||||
namespace elf {
|
||||
|
||||
static Expected<NewSymbolInfo> parseNewSymbolInfo(StringRef FlagValue,
|
||||
uint8_t DefaultVisibility) {
|
||||
// Parse value given with --add-symbol option and create the
|
||||
// new symbol if possible. The value format for --add-symbol is:
|
||||
//
|
||||
// <name>=[<section>:]<value>[,<flags>]
|
||||
//
|
||||
// where:
|
||||
// <name> - symbol name, can be empty string
|
||||
// <section> - optional section name. If not given ABS symbol is created
|
||||
// <value> - symbol value, can be decimal or hexadecimal number prefixed
|
||||
// with 0x.
|
||||
// <flags> - optional flags affecting symbol type, binding or visibility:
|
||||
// The following are currently supported:
|
||||
//
|
||||
// global, local, weak, default, hidden, file, section, object,
|
||||
// indirect-function.
|
||||
//
|
||||
// The following flags are ignored and provided for GNU
|
||||
// compatibility only:
|
||||
//
|
||||
// warning, debug, constructor, indirect, synthetic,
|
||||
// unique-object, before=<symbol>.
|
||||
NewSymbolInfo SI;
|
||||
StringRef Value;
|
||||
std::tie(SI.SymbolName, Value) = FlagValue.split('=');
|
||||
if (Value.empty())
|
||||
return createStringError(
|
||||
errc::invalid_argument,
|
||||
"bad format for --add-symbol, missing '=' after '%s'",
|
||||
SI.SymbolName.str().c_str());
|
||||
|
||||
if (Value.contains(':')) {
|
||||
std::tie(SI.SectionName, Value) = Value.split(':');
|
||||
if (SI.SectionName.empty() || Value.empty())
|
||||
return createStringError(
|
||||
errc::invalid_argument,
|
||||
"bad format for --add-symbol, missing section name or symbol value");
|
||||
}
|
||||
|
||||
SmallVector<StringRef, 6> Flags;
|
||||
Value.split(Flags, ',');
|
||||
if (Flags[0].getAsInteger(0, SI.Value))
|
||||
return createStringError(errc::invalid_argument, "bad symbol value: '%s'",
|
||||
Flags[0].str().c_str());
|
||||
|
||||
SI.Visibility = DefaultVisibility;
|
||||
|
||||
using Functor = std::function<void(void)>;
|
||||
SmallVector<StringRef, 6> UnsupportedFlags;
|
||||
for (size_t I = 1, NumFlags = Flags.size(); I < NumFlags; ++I)
|
||||
static_cast<Functor>(
|
||||
StringSwitch<Functor>(Flags[I])
|
||||
.CaseLower("global", [&SI] { SI.Bind = ELF::STB_GLOBAL; })
|
||||
.CaseLower("local", [&SI] { SI.Bind = ELF::STB_LOCAL; })
|
||||
.CaseLower("weak", [&SI] { SI.Bind = ELF::STB_WEAK; })
|
||||
.CaseLower("default", [&SI] { SI.Visibility = ELF::STV_DEFAULT; })
|
||||
.CaseLower("hidden", [&SI] { SI.Visibility = ELF::STV_HIDDEN; })
|
||||
.CaseLower("protected",
|
||||
[&SI] { SI.Visibility = ELF::STV_PROTECTED; })
|
||||
.CaseLower("file", [&SI] { SI.Type = ELF::STT_FILE; })
|
||||
.CaseLower("section", [&SI] { SI.Type = ELF::STT_SECTION; })
|
||||
.CaseLower("object", [&SI] { SI.Type = ELF::STT_OBJECT; })
|
||||
.CaseLower("function", [&SI] { SI.Type = ELF::STT_FUNC; })
|
||||
.CaseLower("indirect-function",
|
||||
[&SI] { SI.Type = ELF::STT_GNU_IFUNC; })
|
||||
.CaseLower("debug", [] {})
|
||||
.CaseLower("constructor", [] {})
|
||||
.CaseLower("warning", [] {})
|
||||
.CaseLower("indirect", [] {})
|
||||
.CaseLower("synthetic", [] {})
|
||||
.CaseLower("unique-object", [] {})
|
||||
.StartsWithLower("before", [] {})
|
||||
.Default([&] { UnsupportedFlags.push_back(Flags[I]); }))();
|
||||
if (!UnsupportedFlags.empty())
|
||||
return createStringError(errc::invalid_argument,
|
||||
"unsupported flag%s for --add-symbol: '%s'",
|
||||
UnsupportedFlags.size() > 1 ? "s" : "",
|
||||
join(UnsupportedFlags, "', '").c_str());
|
||||
return SI;
|
||||
}
|
||||
|
||||
Expected<ELFCopyConfig> parseConfig(const CopyConfig &Config) {
|
||||
ELFCopyConfig ELFConfig;
|
||||
if (Config.NewSymbolVisibility) {
|
||||
const uint8_t Invalid = 0xff;
|
||||
ELFConfig.NewSymbolVisibility =
|
||||
StringSwitch<uint8_t>(*Config.NewSymbolVisibility)
|
||||
.Case("default", ELF::STV_DEFAULT)
|
||||
.Case("hidden", ELF::STV_HIDDEN)
|
||||
.Case("internal", ELF::STV_INTERNAL)
|
||||
.Case("protected", ELF::STV_PROTECTED)
|
||||
.Default(Invalid);
|
||||
|
||||
if (ELFConfig.NewSymbolVisibility == Invalid)
|
||||
return createStringError(errc::invalid_argument,
|
||||
"'%s' is not a valid symbol visibility",
|
||||
Config.NewSymbolVisibility->str().c_str());
|
||||
}
|
||||
|
||||
for (StringRef Arg : Config.SymbolsToAdd) {
|
||||
Expected<elf::NewSymbolInfo> NSI = parseNewSymbolInfo(
|
||||
Arg,
|
||||
ELFConfig.NewSymbolVisibility.getValueOr((uint8_t)ELF::STV_DEFAULT));
|
||||
if (!NSI)
|
||||
return NSI.takeError();
|
||||
ELFConfig.SymbolsToAdd.push_back(*NSI);
|
||||
}
|
||||
|
||||
return ELFConfig;
|
||||
}
|
||||
|
||||
} // end namespace elf
|
||||
} // end namespace objcopy
|
||||
} // end namespace llvm
|
@ -6,20 +6,16 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_OBJCOPY_ELFCONFIG_H
|
||||
#define LLVM_TOOLS_OBJCOPY_ELFCONFIG_H
|
||||
#ifndef LLVM_TOOLS_LLVM_OBJCOPY_ELF_ELFCONFIG_H
|
||||
#define LLVM_TOOLS_LLVM_OBJCOPY_ELF_ELFCONFIG_H
|
||||
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Object/ELFTypes.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
namespace objcopy {
|
||||
struct CopyConfig;
|
||||
|
||||
namespace elf {
|
||||
|
||||
struct NewSymbolInfo {
|
||||
StringRef SymbolName;
|
||||
@ -30,15 +26,13 @@ struct NewSymbolInfo {
|
||||
uint8_t Visibility = ELF::STV_DEFAULT;
|
||||
};
|
||||
|
||||
struct ELFCopyConfig {
|
||||
// ELF specific configuration for copying/stripping a single file.
|
||||
struct ELFConfig {
|
||||
Optional<uint8_t> NewSymbolVisibility;
|
||||
std::vector<NewSymbolInfo> SymbolsToAdd;
|
||||
};
|
||||
|
||||
Expected<ELFCopyConfig> parseConfig(const CopyConfig &Config);
|
||||
|
||||
} // namespace elf
|
||||
} // namespace objcopy
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
#endif // LLVM_TOOLS_LLVM_OBJCOPY_ELF_ELFCONFIG_H
|
||||
|
@ -7,7 +7,8 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ELFObjcopy.h"
|
||||
#include "CopyConfig.h"
|
||||
#include "CommonConfig.h"
|
||||
#include "ELFConfig.h"
|
||||
#include "Object.h"
|
||||
#include "llvm-objcopy.h"
|
||||
#include "llvm/ADT/BitmaskEnum.h"
|
||||
@ -132,7 +133,7 @@ static ElfType getOutputElfType(const MachineInfo &MI) {
|
||||
return MI.IsLittleEndian ? ELFT_ELF32LE : ELFT_ELF32BE;
|
||||
}
|
||||
|
||||
static std::unique_ptr<Writer> createELFWriter(const CopyConfig &Config,
|
||||
static std::unique_ptr<Writer> createELFWriter(const CommonConfig &Config,
|
||||
Object &Obj, raw_ostream &Out,
|
||||
ElfType OutputElfType) {
|
||||
// Depending on the initial ELFT and OutputFormat we need a different Writer.
|
||||
@ -153,7 +154,7 @@ static std::unique_ptr<Writer> createELFWriter(const CopyConfig &Config,
|
||||
llvm_unreachable("Invalid output format");
|
||||
}
|
||||
|
||||
static std::unique_ptr<Writer> createWriter(const CopyConfig &Config,
|
||||
static std::unique_ptr<Writer> createWriter(const CommonConfig &Config,
|
||||
Object &Obj, raw_ostream &Out,
|
||||
ElfType OutputElfType) {
|
||||
switch (Config.OutputFormat) {
|
||||
@ -243,7 +244,7 @@ static bool isUnneededSymbol(const Symbol &Sym) {
|
||||
Sym.Type != STT_SECTION;
|
||||
}
|
||||
|
||||
static Error updateAndRemoveSymbols(const CopyConfig &Config, Object &Obj) {
|
||||
static Error updateAndRemoveSymbols(const CommonConfig &Config, Object &Obj) {
|
||||
// TODO: update or remove symbols only if there is an option that affects
|
||||
// them.
|
||||
if (!Obj.SymbolTable)
|
||||
@ -338,7 +339,7 @@ static Error updateAndRemoveSymbols(const CopyConfig &Config, Object &Obj) {
|
||||
return Obj.removeSymbols(RemoveSymbolsPred);
|
||||
}
|
||||
|
||||
static Error replaceAndRemoveSections(const CopyConfig &Config, Object &Obj) {
|
||||
static Error replaceAndRemoveSections(const CommonConfig &Config, Object &Obj) {
|
||||
SectionPred RemovePred = [](const SectionBase &) { return false; };
|
||||
|
||||
// Removes:
|
||||
@ -506,11 +507,8 @@ static Error replaceAndRemoveSections(const CopyConfig &Config, Object &Obj) {
|
||||
// any previous removals. Lastly whether or not something is removed shouldn't
|
||||
// depend a) on the order the options occur in or b) on some opaque priority
|
||||
// system. The only priority is that keeps/copies overrule removes.
|
||||
static Error handleArgs(const CopyConfig &Config, Object &Obj) {
|
||||
if (Config.StripSwiftSymbols || Config.KeepUndefined)
|
||||
return createStringError(llvm::errc::invalid_argument,
|
||||
"option not supported by llvm-objcopy for ELF");
|
||||
|
||||
static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
|
||||
Object &Obj) {
|
||||
if (Config.OutputArch) {
|
||||
Obj.Machine = Config.OutputArch.getValue().EMachine;
|
||||
Obj.OSABI = Config.OutputArch.getValue().OSABI;
|
||||
@ -635,11 +633,11 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
|
||||
|
||||
// If the symbol table was previously removed, we need to create a new one
|
||||
// before adding new symbols.
|
||||
if (!Obj.SymbolTable && !Config.ELF->SymbolsToAdd.empty())
|
||||
if (!Obj.SymbolTable && !ELFConfig.SymbolsToAdd.empty())
|
||||
if (Error E = Obj.addNewSymbolTable())
|
||||
return E;
|
||||
|
||||
for (const NewSymbolInfo &SI : Config.ELF->SymbolsToAdd) {
|
||||
for (const NewSymbolInfo &SI : ELFConfig.SymbolsToAdd) {
|
||||
SectionBase *Sec = Obj.findSection(SI.SectionName);
|
||||
uint64_t Value = Sec ? Sec->Addr + SI.Value : SI.Value;
|
||||
Obj.SymbolTable->addSymbol(
|
||||
@ -663,7 +661,7 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
static Error writeOutput(const CopyConfig &Config, Object &Obj,
|
||||
static Error writeOutput(const CommonConfig &Config, Object &Obj,
|
||||
raw_ostream &Out, ElfType OutputElfType) {
|
||||
std::unique_ptr<Writer> Writer =
|
||||
createWriter(Config, Obj, Out, OutputElfType);
|
||||
@ -672,7 +670,8 @@ static Error writeOutput(const CopyConfig &Config, Object &Obj,
|
||||
return Writer->write();
|
||||
}
|
||||
|
||||
Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In,
|
||||
Error executeObjcopyOnIHex(const CommonConfig &Config,
|
||||
const ELFConfig &ELFConfig, MemoryBuffer &In,
|
||||
raw_ostream &Out) {
|
||||
IHexReader Reader(&In);
|
||||
Expected<std::unique_ptr<Object>> Obj = Reader.create(true);
|
||||
@ -681,15 +680,16 @@ Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In,
|
||||
|
||||
const ElfType OutputElfType =
|
||||
getOutputElfType(Config.OutputArch.getValueOr(MachineInfo()));
|
||||
if (Error E = handleArgs(Config, **Obj))
|
||||
if (Error E = handleArgs(Config, ELFConfig, **Obj))
|
||||
return E;
|
||||
return writeOutput(Config, **Obj, Out, OutputElfType);
|
||||
}
|
||||
|
||||
Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In,
|
||||
Error executeObjcopyOnRawBinary(const CommonConfig &Config,
|
||||
const ELFConfig &ELFConfig, MemoryBuffer &In,
|
||||
raw_ostream &Out) {
|
||||
uint8_t NewSymbolVisibility =
|
||||
Config.ELF->NewSymbolVisibility.getValueOr((uint8_t)ELF::STV_DEFAULT);
|
||||
ELFConfig.NewSymbolVisibility.getValueOr((uint8_t)ELF::STV_DEFAULT);
|
||||
BinaryReader Reader(&In, NewSymbolVisibility);
|
||||
Expected<std::unique_ptr<Object>> Obj = Reader.create(true);
|
||||
if (!Obj)
|
||||
@ -699,16 +699,17 @@ Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In,
|
||||
// (-B<arch>).
|
||||
const ElfType OutputElfType =
|
||||
getOutputElfType(Config.OutputArch.getValueOr(MachineInfo()));
|
||||
if (Error E = handleArgs(Config, **Obj))
|
||||
if (Error E = handleArgs(Config, ELFConfig, **Obj))
|
||||
return E;
|
||||
return writeOutput(Config, **Obj, Out, OutputElfType);
|
||||
}
|
||||
|
||||
Error executeObjcopyOnBinary(const CopyConfig &Config,
|
||||
Error executeObjcopyOnBinary(const CommonConfig &Config,
|
||||
const ELFConfig &ELFConfig,
|
||||
object::ELFObjectFileBase &In, raw_ostream &Out) {
|
||||
ELFReader Reader(&In, Config.ExtractPartition);
|
||||
Expected<std::unique_ptr<Object>> Obj =
|
||||
Reader.create(!Config.SymbolsToAdd.empty());
|
||||
Reader.create(!ELFConfig.SymbolsToAdd.empty());
|
||||
if (!Obj)
|
||||
return Obj.takeError();
|
||||
// Prefer OutputArch (-O<format>) if set, otherwise infer it from the input.
|
||||
@ -716,7 +717,7 @@ Error executeObjcopyOnBinary(const CopyConfig &Config,
|
||||
Config.OutputArch ? getOutputElfType(Config.OutputArch.getValue())
|
||||
: getOutputElfType(In);
|
||||
|
||||
if (Error E = handleArgs(Config, **Obj))
|
||||
if (Error E = handleArgs(Config, ELFConfig, **Obj))
|
||||
return createFileError(Config.InputFilename, std::move(E));
|
||||
|
||||
if (Error E = writeOutput(Config, **Obj, Out, OutputElfType))
|
||||
|
@ -19,14 +19,18 @@ class ELFObjectFileBase;
|
||||
} // end namespace object
|
||||
|
||||
namespace objcopy {
|
||||
struct CopyConfig;
|
||||
struct CommonConfig;
|
||||
struct ELFConfig;
|
||||
|
||||
namespace elf {
|
||||
Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In,
|
||||
Error executeObjcopyOnIHex(const CommonConfig &Config,
|
||||
const ELFConfig &ELFConfig, MemoryBuffer &In,
|
||||
raw_ostream &Out);
|
||||
Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In,
|
||||
Error executeObjcopyOnRawBinary(const CommonConfig &Config,
|
||||
const ELFConfig &ELFConfig, MemoryBuffer &In,
|
||||
raw_ostream &Out);
|
||||
Error executeObjcopyOnBinary(const CopyConfig &Config,
|
||||
Error executeObjcopyOnBinary(const CommonConfig &Config,
|
||||
const ELFConfig &ELFConfig,
|
||||
object::ELFObjectFileBase &In, raw_ostream &Out);
|
||||
|
||||
} // end namespace elf
|
||||
|
@ -9,7 +9,7 @@
|
||||
#ifndef LLVM_TOOLS_OBJCOPY_OBJECT_H
|
||||
#define LLVM_TOOLS_OBJCOPY_OBJECT_H
|
||||
|
||||
#include "CopyConfig.h"
|
||||
#include "CommonConfig.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
|
21
tools/llvm-objcopy/MachO/MachOConfig.h
Normal file
21
tools/llvm-objcopy/MachO/MachOConfig.h
Normal file
@ -0,0 +1,21 @@
|
||||
//===- MachOConfig.h --------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVM_OBJCOPY_MACHO_MACHOCONFIG_H
|
||||
#define LLVM_TOOLS_LLVM_OBJCOPY_MACHO_MACHOCONFIG_H
|
||||
|
||||
namespace llvm {
|
||||
namespace objcopy {
|
||||
|
||||
// Mach-O specific configuration for copying/stripping a single file.
|
||||
struct MachOConfig {};
|
||||
|
||||
} // namespace objcopy
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_TOOLS_LLVM_OBJCOPY_MACHO_MACHOCONFIG_H
|
@ -7,10 +7,11 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MachOObjcopy.h"
|
||||
#include "../CopyConfig.h"
|
||||
#include "../llvm-objcopy.h"
|
||||
#include "CommonConfig.h"
|
||||
#include "MachOReader.h"
|
||||
#include "MachOWriter.h"
|
||||
#include "MultiFormatConfig.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/Object/ArchiveWriter.h"
|
||||
#include "llvm/Object/MachOUniversal.h"
|
||||
@ -48,7 +49,7 @@ static StringRef getPayloadString(const LoadCommand &LC) {
|
||||
.rtrim('\0');
|
||||
}
|
||||
|
||||
static Error removeSections(const CopyConfig &Config, Object &Obj) {
|
||||
static Error removeSections(const CommonConfig &Config, Object &Obj) {
|
||||
SectionPred RemovePred = [](const std::unique_ptr<Section> &) {
|
||||
return false;
|
||||
};
|
||||
@ -79,14 +80,14 @@ static Error removeSections(const CopyConfig &Config, Object &Obj) {
|
||||
return Obj.removeSections(RemovePred);
|
||||
}
|
||||
|
||||
static void markSymbols(const CopyConfig &Config, Object &Obj) {
|
||||
static void markSymbols(const CommonConfig &, Object &Obj) {
|
||||
// Symbols referenced from the indirect symbol table must not be removed.
|
||||
for (IndirectSymbolEntry &ISE : Obj.IndirectSymTable.Symbols)
|
||||
if (ISE.Symbol)
|
||||
(*ISE.Symbol)->Referenced = true;
|
||||
}
|
||||
|
||||
static void updateAndRemoveSymbols(const CopyConfig &Config, Object &Obj) {
|
||||
static void updateAndRemoveSymbols(const CommonConfig &Config, Object &Obj) {
|
||||
for (SymbolEntry &Sym : Obj.SymTable) {
|
||||
auto I = Config.SymbolsToRename.find(Sym.Name);
|
||||
if (I != Config.SymbolsToRename.end())
|
||||
@ -136,7 +137,7 @@ static LoadCommand buildRPathLoadCommand(StringRef Path) {
|
||||
return LC;
|
||||
}
|
||||
|
||||
static Error processLoadCommands(const CopyConfig &Config, Object &Obj) {
|
||||
static Error processLoadCommands(const CommonConfig &Config, Object &Obj) {
|
||||
// Remove RPaths.
|
||||
DenseSet<StringRef> RPathsToRemove(Config.RPathsToRemove.begin(),
|
||||
Config.RPathsToRemove.end());
|
||||
@ -330,24 +331,7 @@ static Error isValidMachOCannonicalName(StringRef Name) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
static Error handleArgs(const CopyConfig &Config, Object &Obj) {
|
||||
if (Config.AllowBrokenLinks || !Config.SplitDWO.empty() ||
|
||||
!Config.SymbolsPrefix.empty() || !Config.AllocSectionsPrefix.empty() ||
|
||||
!Config.KeepSection.empty() || Config.NewSymbolVisibility ||
|
||||
!Config.SymbolsToGlobalize.empty() || !Config.SymbolsToKeep.empty() ||
|
||||
!Config.SymbolsToLocalize.empty() || !Config.SymbolsToWeaken.empty() ||
|
||||
!Config.SymbolsToKeepGlobal.empty() || !Config.SectionsToRename.empty() ||
|
||||
!Config.UnneededSymbolsToRemove.empty() ||
|
||||
!Config.SetSectionAlignment.empty() || !Config.SetSectionFlags.empty() ||
|
||||
Config.ExtractDWO || Config.LocalizeHidden || Config.PreserveDates ||
|
||||
Config.StripAllGNU || Config.StripDWO || Config.StripNonAlloc ||
|
||||
Config.StripSections || Config.Weaken || Config.DecompressDebugSections ||
|
||||
Config.StripUnneeded || Config.DiscardMode == DiscardType::Locals ||
|
||||
!Config.SymbolsToAdd.empty() || Config.EntryExpr) {
|
||||
return createStringError(llvm::errc::invalid_argument,
|
||||
"option not supported by llvm-objcopy for MachO");
|
||||
}
|
||||
|
||||
static Error handleArgs(const CommonConfig &Config, Object &Obj) {
|
||||
// Dump sections before add/remove for compatibility with GNU objcopy.
|
||||
for (StringRef Flag : Config.DumpSection) {
|
||||
StringRef SectionName;
|
||||
@ -387,7 +371,7 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error executeObjcopyOnBinary(const CopyConfig &Config,
|
||||
Error executeObjcopyOnBinary(const CommonConfig &Config, const MachOConfig &,
|
||||
object::MachOObjectFile &In, raw_ostream &Out) {
|
||||
MachOReader Reader(In);
|
||||
Expected<std::unique_ptr<Object>> O = Reader.create();
|
||||
@ -416,7 +400,7 @@ Error executeObjcopyOnBinary(const CopyConfig &Config,
|
||||
return Writer.write();
|
||||
}
|
||||
|
||||
Error executeObjcopyOnMachOUniversalBinary(CopyConfig &Config,
|
||||
Error executeObjcopyOnMachOUniversalBinary(const MultiFormatConfig &Config,
|
||||
const MachOUniversalBinary &In,
|
||||
raw_ostream &Out) {
|
||||
SmallVector<OwningBinary<Binary>, 2> Binaries;
|
||||
@ -431,7 +415,7 @@ Error executeObjcopyOnMachOUniversalBinary(CopyConfig &Config,
|
||||
Expected<std::unique_ptr<MemoryBuffer>> OutputBufferOrErr =
|
||||
writeArchiveToBuffer(*NewArchiveMembersOrErr,
|
||||
(*ArOrErr)->hasSymbolTable(), (*ArOrErr)->kind(),
|
||||
Config.DeterministicArchives,
|
||||
Config.getCommonConfig().DeterministicArchives,
|
||||
(*ArOrErr)->isThin());
|
||||
if (!OutputBufferOrErr)
|
||||
return OutputBufferOrErr.takeError();
|
||||
@ -455,18 +439,24 @@ Error executeObjcopyOnMachOUniversalBinary(CopyConfig &Config,
|
||||
Expected<std::unique_ptr<MachOObjectFile>> ObjOrErr = O.getAsObjectFile();
|
||||
if (!ObjOrErr) {
|
||||
consumeError(ObjOrErr.takeError());
|
||||
return createStringError(std::errc::invalid_argument,
|
||||
"slice for '%s' of the universal Mach-O binary "
|
||||
"'%s' is not a Mach-O object or an archive",
|
||||
O.getArchFlagName().c_str(),
|
||||
Config.InputFilename.str().c_str());
|
||||
return createStringError(
|
||||
std::errc::invalid_argument,
|
||||
"slice for '%s' of the universal Mach-O binary "
|
||||
"'%s' is not a Mach-O object or an archive",
|
||||
O.getArchFlagName().c_str(),
|
||||
Config.getCommonConfig().InputFilename.str().c_str());
|
||||
}
|
||||
std::string ArchFlagName = O.getArchFlagName();
|
||||
|
||||
SmallVector<char, 0> Buffer;
|
||||
raw_svector_ostream MemStream(Buffer);
|
||||
|
||||
if (Error E = executeObjcopyOnBinary(Config, **ObjOrErr, MemStream))
|
||||
Expected<const MachOConfig &> MachO = Config.getMachOConfig();
|
||||
if (!MachO)
|
||||
return MachO.takeError();
|
||||
|
||||
if (Error E = executeObjcopyOnBinary(Config.getCommonConfig(), *MachO,
|
||||
**ObjOrErr, MemStream))
|
||||
return E;
|
||||
|
||||
std::unique_ptr<MemoryBuffer> MB =
|
||||
|
@ -19,15 +19,16 @@ class MachOUniversalBinary;
|
||||
} // end namespace object
|
||||
|
||||
namespace objcopy {
|
||||
struct CopyConfig;
|
||||
class Buffer;
|
||||
struct CommonConfig;
|
||||
struct MachOConfig;
|
||||
class MultiFormatConfig;
|
||||
|
||||
namespace macho {
|
||||
Error executeObjcopyOnBinary(const CopyConfig &Config,
|
||||
Error executeObjcopyOnBinary(const CommonConfig &Config, const MachOConfig &,
|
||||
object::MachOObjectFile &In, raw_ostream &Out);
|
||||
|
||||
Error executeObjcopyOnMachOUniversalBinary(
|
||||
CopyConfig &Config, const object::MachOUniversalBinary &In,
|
||||
const MultiFormatConfig &Config, const object::MachOUniversalBinary &In,
|
||||
raw_ostream &Out);
|
||||
|
||||
} // end namespace macho
|
||||
|
37
tools/llvm-objcopy/MultiFormatConfig.h
Normal file
37
tools/llvm-objcopy/MultiFormatConfig.h
Normal file
@ -0,0 +1,37 @@
|
||||
//===- MultiFormatConfig.h --------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVM_OBJCOPY_MULTIFORMATCONFIG_H
|
||||
#define LLVM_TOOLS_LLVM_OBJCOPY_MULTIFORMATCONFIG_H
|
||||
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace objcopy {
|
||||
|
||||
struct CommonConfig;
|
||||
struct ELFConfig;
|
||||
struct COFFConfig;
|
||||
struct MachOConfig;
|
||||
struct WasmConfig;
|
||||
|
||||
class MultiFormatConfig {
|
||||
public:
|
||||
virtual ~MultiFormatConfig() {}
|
||||
|
||||
virtual const CommonConfig &getCommonConfig() const = 0;
|
||||
virtual Expected<const ELFConfig &> getELFConfig() const = 0;
|
||||
virtual Expected<const COFFConfig &> getCOFFConfig() const = 0;
|
||||
virtual Expected<const MachOConfig &> getMachOConfig() const = 0;
|
||||
virtual Expected<const WasmConfig &> getWasmConfig() const = 0;
|
||||
};
|
||||
|
||||
} // namespace objcopy
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_TOOLS_LLVM_OBJCOPY_MULTIFORMATCONFIG_H
|
@ -7,10 +7,15 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm-objcopy.h"
|
||||
#include "COFF/COFFConfig.h"
|
||||
#include "COFF/COFFObjcopy.h"
|
||||
#include "CopyConfig.h"
|
||||
#include "CommonConfig.h"
|
||||
#include "ConfigManager.h"
|
||||
#include "ELF/ELFConfig.h"
|
||||
#include "ELF/ELFObjcopy.h"
|
||||
#include "MachO/MachOConfig.h"
|
||||
#include "MachO/MachOObjcopy.h"
|
||||
#include "wasm/WasmConfig.h"
|
||||
#include "wasm/WasmObjcopy.h"
|
||||
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
@ -133,18 +138,22 @@ static Error deepWriteArchive(StringRef ArcName,
|
||||
|
||||
/// The function executeObjcopyOnIHex does the dispatch based on the format
|
||||
/// of the output specified by the command line options.
|
||||
static Error executeObjcopyOnIHex(CopyConfig &Config, MemoryBuffer &In,
|
||||
static Error executeObjcopyOnIHex(ConfigManager &ConfigMgr, MemoryBuffer &In,
|
||||
raw_ostream &Out) {
|
||||
// TODO: support output formats other than ELF.
|
||||
if (Error E = Config.parseELFConfig())
|
||||
return E;
|
||||
return elf::executeObjcopyOnIHex(Config, In, Out);
|
||||
Expected<const ELFConfig &> ELFConfig = ConfigMgr.getELFConfig();
|
||||
if (!ELFConfig)
|
||||
return ELFConfig.takeError();
|
||||
|
||||
return elf::executeObjcopyOnIHex(ConfigMgr.getCommonConfig(), *ELFConfig, In,
|
||||
Out);
|
||||
}
|
||||
|
||||
/// The function executeObjcopyOnRawBinary does the dispatch based on the format
|
||||
/// of the output specified by the command line options.
|
||||
static Error executeObjcopyOnRawBinary(CopyConfig &Config, MemoryBuffer &In,
|
||||
raw_ostream &Out) {
|
||||
static Error executeObjcopyOnRawBinary(ConfigManager &ConfigMgr,
|
||||
MemoryBuffer &In, raw_ostream &Out) {
|
||||
const CommonConfig &Config = ConfigMgr.getCommonConfig();
|
||||
switch (Config.OutputFormat) {
|
||||
case FileFormat::ELF:
|
||||
// FIXME: Currently, we call elf::executeObjcopyOnRawBinary even if the
|
||||
@ -153,9 +162,11 @@ static Error executeObjcopyOnRawBinary(CopyConfig &Config, MemoryBuffer &In,
|
||||
case FileFormat::Binary:
|
||||
case FileFormat::IHex:
|
||||
case FileFormat::Unspecified:
|
||||
if (Error E = Config.parseELFConfig())
|
||||
return E;
|
||||
return elf::executeObjcopyOnRawBinary(Config, In, Out);
|
||||
Expected<const ELFConfig &> ELFConfig = ConfigMgr.getELFConfig();
|
||||
if (!ELFConfig)
|
||||
return ELFConfig.takeError();
|
||||
|
||||
return elf::executeObjcopyOnRawBinary(Config, *ELFConfig, In, Out);
|
||||
}
|
||||
|
||||
llvm_unreachable("unsupported output format");
|
||||
@ -163,23 +174,41 @@ static Error executeObjcopyOnRawBinary(CopyConfig &Config, MemoryBuffer &In,
|
||||
|
||||
/// The function executeObjcopyOnBinary does the dispatch based on the format
|
||||
/// of the input binary (ELF, MachO or COFF).
|
||||
static Error executeObjcopyOnBinary(CopyConfig &Config, object::Binary &In,
|
||||
raw_ostream &Out) {
|
||||
static Error executeObjcopyOnBinary(const MultiFormatConfig &Config,
|
||||
object::Binary &In, raw_ostream &Out) {
|
||||
if (auto *ELFBinary = dyn_cast<object::ELFObjectFileBase>(&In)) {
|
||||
if (Error E = Config.parseELFConfig())
|
||||
return E;
|
||||
return elf::executeObjcopyOnBinary(Config, *ELFBinary, Out);
|
||||
} else if (auto *COFFBinary = dyn_cast<object::COFFObjectFile>(&In))
|
||||
return coff::executeObjcopyOnBinary(Config, *COFFBinary, Out);
|
||||
else if (auto *MachOBinary = dyn_cast<object::MachOObjectFile>(&In))
|
||||
return macho::executeObjcopyOnBinary(Config, *MachOBinary, Out);
|
||||
else if (auto *MachOUniversalBinary =
|
||||
dyn_cast<object::MachOUniversalBinary>(&In))
|
||||
Expected<const ELFConfig &> ELFConfig = Config.getELFConfig();
|
||||
if (!ELFConfig)
|
||||
return ELFConfig.takeError();
|
||||
|
||||
return elf::executeObjcopyOnBinary(Config.getCommonConfig(), *ELFConfig,
|
||||
*ELFBinary, Out);
|
||||
} else if (auto *COFFBinary = dyn_cast<object::COFFObjectFile>(&In)) {
|
||||
Expected<const COFFConfig &> COFFConfig = Config.getCOFFConfig();
|
||||
if (!COFFConfig)
|
||||
return COFFConfig.takeError();
|
||||
|
||||
return coff::executeObjcopyOnBinary(Config.getCommonConfig(), *COFFConfig,
|
||||
*COFFBinary, Out);
|
||||
} else if (auto *MachOBinary = dyn_cast<object::MachOObjectFile>(&In)) {
|
||||
Expected<const MachOConfig &> MachOConfig = Config.getMachOConfig();
|
||||
if (!MachOConfig)
|
||||
return MachOConfig.takeError();
|
||||
|
||||
return macho::executeObjcopyOnBinary(Config.getCommonConfig(), *MachOConfig,
|
||||
*MachOBinary, Out);
|
||||
} else if (auto *MachOUniversalBinary =
|
||||
dyn_cast<object::MachOUniversalBinary>(&In)) {
|
||||
return macho::executeObjcopyOnMachOUniversalBinary(
|
||||
Config, *MachOUniversalBinary, Out);
|
||||
else if (auto *WasmBinary = dyn_cast<object::WasmObjectFile>(&In))
|
||||
return objcopy::wasm::executeObjcopyOnBinary(Config, *WasmBinary, Out);
|
||||
else
|
||||
} else if (auto *WasmBinary = dyn_cast<object::WasmObjectFile>(&In)) {
|
||||
Expected<const WasmConfig &> WasmConfig = Config.getWasmConfig();
|
||||
if (!WasmConfig)
|
||||
return WasmConfig.takeError();
|
||||
|
||||
return objcopy::wasm::executeObjcopyOnBinary(Config.getCommonConfig(),
|
||||
*WasmConfig, *WasmBinary, Out);
|
||||
} else
|
||||
return createStringError(object_error::invalid_file_type,
|
||||
"unsupported object file format");
|
||||
}
|
||||
@ -188,7 +217,7 @@ namespace llvm {
|
||||
namespace objcopy {
|
||||
|
||||
Expected<std::vector<NewArchiveMember>>
|
||||
createNewArchiveMembers(CopyConfig &Config, const Archive &Ar) {
|
||||
createNewArchiveMembers(const MultiFormatConfig &Config, const Archive &Ar) {
|
||||
std::vector<NewArchiveMember> NewArchiveMembers;
|
||||
Error Err = Error::success();
|
||||
for (const Archive::Child &Child : Ar.children(Err)) {
|
||||
@ -207,8 +236,8 @@ createNewArchiveMembers(CopyConfig &Config, const Archive &Ar) {
|
||||
if (Error E = executeObjcopyOnBinary(Config, *ChildOrErr->get(), MemStream))
|
||||
return std::move(E);
|
||||
|
||||
Expected<NewArchiveMember> Member =
|
||||
NewArchiveMember::getOldMember(Child, Config.DeterministicArchives);
|
||||
Expected<NewArchiveMember> Member = NewArchiveMember::getOldMember(
|
||||
Child, Config.getCommonConfig().DeterministicArchives);
|
||||
if (!Member)
|
||||
return createFileError(Ar.getFileName(), Member.takeError());
|
||||
|
||||
@ -218,19 +247,21 @@ createNewArchiveMembers(CopyConfig &Config, const Archive &Ar) {
|
||||
NewArchiveMembers.push_back(std::move(*Member));
|
||||
}
|
||||
if (Err)
|
||||
return createFileError(Config.InputFilename, std::move(Err));
|
||||
return createFileError(Config.getCommonConfig().InputFilename,
|
||||
std::move(Err));
|
||||
return std::move(NewArchiveMembers);
|
||||
}
|
||||
|
||||
} // end namespace objcopy
|
||||
} // end namespace llvm
|
||||
|
||||
static Error executeObjcopyOnArchive(CopyConfig &Config,
|
||||
static Error executeObjcopyOnArchive(const ConfigManager &ConfigMgr,
|
||||
const object::Archive &Ar) {
|
||||
Expected<std::vector<NewArchiveMember>> NewArchiveMembersOrErr =
|
||||
createNewArchiveMembers(Config, Ar);
|
||||
createNewArchiveMembers(ConfigMgr, Ar);
|
||||
if (!NewArchiveMembersOrErr)
|
||||
return NewArchiveMembersOrErr.takeError();
|
||||
const CommonConfig &Config = ConfigMgr.getCommonConfig();
|
||||
return deepWriteArchive(Config.OutputFilename, *NewArchiveMembersOrErr,
|
||||
Ar.hasSymbolTable(), Ar.kind(),
|
||||
Config.DeterministicArchives, Ar.isThin());
|
||||
@ -238,8 +269,9 @@ static Error executeObjcopyOnArchive(CopyConfig &Config,
|
||||
|
||||
static Error restoreStatOnFile(StringRef Filename,
|
||||
const sys::fs::file_status &Stat,
|
||||
const CopyConfig &Config) {
|
||||
const ConfigManager &ConfigMgr) {
|
||||
int FD;
|
||||
const CommonConfig &Config = ConfigMgr.getCommonConfig();
|
||||
|
||||
// Writing to stdout should not be treated as an error here, just
|
||||
// do not set access/modification times or permissions.
|
||||
@ -285,7 +317,9 @@ static Error restoreStatOnFile(StringRef Filename,
|
||||
/// The function executeObjcopy does the higher level dispatch based on the type
|
||||
/// of input (raw binary, archive or single object file) and takes care of the
|
||||
/// format-agnostic modifications, i.e. preserving dates.
|
||||
static Error executeObjcopy(CopyConfig &Config) {
|
||||
static Error executeObjcopy(ConfigManager &ConfigMgr) {
|
||||
CommonConfig &Config = ConfigMgr.Common;
|
||||
|
||||
sys::fs::file_status Stat;
|
||||
if (Config.InputFilename != "-") {
|
||||
if (auto EC = sys::fs::status(Config.InputFilename, Stat))
|
||||
@ -310,12 +344,13 @@ static Error executeObjcopy(CopyConfig &Config) {
|
||||
if (Config.InputFormat == FileFormat::Binary)
|
||||
ObjcopyFunc = [&](raw_ostream &OutFile) -> Error {
|
||||
// Handle FileFormat::Binary.
|
||||
return executeObjcopyOnRawBinary(Config, *MemoryBufferHolder, OutFile);
|
||||
return executeObjcopyOnRawBinary(ConfigMgr, *MemoryBufferHolder,
|
||||
OutFile);
|
||||
};
|
||||
else
|
||||
ObjcopyFunc = [&](raw_ostream &OutFile) -> Error {
|
||||
// Handle FileFormat::IHex.
|
||||
return executeObjcopyOnIHex(Config, *MemoryBufferHolder, OutFile);
|
||||
return executeObjcopyOnIHex(ConfigMgr, *MemoryBufferHolder, OutFile);
|
||||
};
|
||||
} else {
|
||||
Expected<OwningBinary<llvm::object::Binary>> BinaryOrErr =
|
||||
@ -326,12 +361,12 @@ static Error executeObjcopy(CopyConfig &Config) {
|
||||
|
||||
if (Archive *Ar = dyn_cast<Archive>(BinaryHolder.getBinary())) {
|
||||
// Handle Archive.
|
||||
if (Error E = executeObjcopyOnArchive(Config, *Ar))
|
||||
if (Error E = executeObjcopyOnArchive(ConfigMgr, *Ar))
|
||||
return E;
|
||||
} else {
|
||||
// Handle llvm::object::Binary.
|
||||
ObjcopyFunc = [&](raw_ostream &OutFile) -> Error {
|
||||
return executeObjcopyOnBinary(Config, *BinaryHolder.getBinary(),
|
||||
return executeObjcopyOnBinary(ConfigMgr, *BinaryHolder.getBinary(),
|
||||
OutFile);
|
||||
};
|
||||
}
|
||||
@ -360,12 +395,12 @@ static Error executeObjcopy(CopyConfig &Config) {
|
||||
}
|
||||
}
|
||||
|
||||
if (Error E = restoreStatOnFile(Config.OutputFilename, Stat, Config))
|
||||
if (Error E = restoreStatOnFile(Config.OutputFilename, Stat, ConfigMgr))
|
||||
return E;
|
||||
|
||||
if (!Config.SplitDWO.empty()) {
|
||||
Stat.permissions(static_cast<sys::fs::perms>(0666));
|
||||
if (Error E = restoreStatOnFile(Config.SplitDWO, Stat, Config))
|
||||
if (Error E = restoreStatOnFile(Config.SplitDWO, Stat, ConfigMgr))
|
||||
return E;
|
||||
}
|
||||
|
||||
@ -401,8 +436,8 @@ int main(int argc, char **argv) {
|
||||
WithColor::error(errs(), ToolName));
|
||||
return 1;
|
||||
}
|
||||
for (CopyConfig &CopyConfig : DriverConfig->CopyConfigs) {
|
||||
if (Error E = executeObjcopy(CopyConfig)) {
|
||||
for (ConfigManager &ConfigMgr : DriverConfig->CopyConfigs) {
|
||||
if (Error E = executeObjcopy(ConfigMgr)) {
|
||||
logAllUnhandledErrors(std::move(E), WithColor::error(errs(), ToolName));
|
||||
return 1;
|
||||
}
|
||||
|
@ -23,9 +23,10 @@ class Archive;
|
||||
} // end namespace object
|
||||
|
||||
namespace objcopy {
|
||||
struct CopyConfig;
|
||||
class MultiFormatConfig;
|
||||
Expected<std::vector<NewArchiveMember>>
|
||||
createNewArchiveMembers(CopyConfig &Config, const object::Archive &Ar);
|
||||
createNewArchiveMembers(const MultiFormatConfig &Config,
|
||||
const object::Archive &Ar);
|
||||
|
||||
} // end namespace objcopy
|
||||
} // end namespace llvm
|
||||
|
21
tools/llvm-objcopy/wasm/WasmConfig.h
Normal file
21
tools/llvm-objcopy/wasm/WasmConfig.h
Normal file
@ -0,0 +1,21 @@
|
||||
//===- WasmConfig.h ---------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVM_OBJCOPY_WASM_WASMCONFIG_H
|
||||
#define LLVM_TOOLS_LLVM_OBJCOPY_WASM_WASMCONFIG_H
|
||||
|
||||
namespace llvm {
|
||||
namespace objcopy {
|
||||
|
||||
// Wasm specific configuration for copying/stripping a single file.
|
||||
struct WasmConfig {};
|
||||
|
||||
} // namespace objcopy
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_TOOLS_LLVM_OBJCOPY_WASM_WASMCONFIG_H
|
@ -7,7 +7,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "WasmObjcopy.h"
|
||||
#include "CopyConfig.h"
|
||||
#include "CommonConfig.h"
|
||||
#include "Object.h"
|
||||
#include "Reader.h"
|
||||
#include "Writer.h"
|
||||
@ -39,7 +39,7 @@ static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
|
||||
return createStringError(errc::invalid_argument, "section '%s' not found",
|
||||
SecName.str().c_str());
|
||||
}
|
||||
static Error handleArgs(const CopyConfig &Config, Object &Obj) {
|
||||
static Error handleArgs(const CommonConfig &Config, Object &Obj) {
|
||||
// Only support AddSection, DumpSection, RemoveSection for now.
|
||||
for (StringRef Flag : Config.DumpSection) {
|
||||
StringRef SecName;
|
||||
@ -72,26 +72,10 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
|
||||
Obj.addSectionWithOwnedContents(Sec, std::move(Buf));
|
||||
}
|
||||
|
||||
if (!Config.AddGnuDebugLink.empty() || Config.ExtractPartition ||
|
||||
!Config.SplitDWO.empty() || !Config.SymbolsPrefix.empty() ||
|
||||
!Config.AllocSectionsPrefix.empty() ||
|
||||
Config.DiscardMode != DiscardType::None || Config.NewSymbolVisibility ||
|
||||
!Config.SymbolsToAdd.empty() || !Config.RPathToAdd.empty() ||
|
||||
!Config.OnlySection.empty() || !Config.SymbolsToGlobalize.empty() ||
|
||||
!Config.SymbolsToKeep.empty() || !Config.SymbolsToLocalize.empty() ||
|
||||
!Config.SymbolsToRemove.empty() ||
|
||||
!Config.UnneededSymbolsToRemove.empty() ||
|
||||
!Config.SymbolsToWeaken.empty() || !Config.SymbolsToKeepGlobal.empty() ||
|
||||
!Config.SectionsToRename.empty() || !Config.SetSectionAlignment.empty() ||
|
||||
!Config.SetSectionFlags.empty() || !Config.SymbolsToRename.empty()) {
|
||||
return createStringError(
|
||||
llvm::errc::invalid_argument,
|
||||
"only add-section, dump-section, and remove-section are supported");
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error executeObjcopyOnBinary(const CopyConfig &Config,
|
||||
Error executeObjcopyOnBinary(const CommonConfig &Config, const WasmConfig &,
|
||||
object::WasmObjectFile &In, raw_ostream &Out) {
|
||||
Reader TheReader(In);
|
||||
Expected<std::unique_ptr<Object>> ObjOrErr = TheReader.create();
|
||||
|
@ -18,10 +18,11 @@ class WasmObjectFile;
|
||||
} // end namespace object
|
||||
|
||||
namespace objcopy {
|
||||
struct CopyConfig;
|
||||
struct CommonConfig;
|
||||
struct WasmConfig;
|
||||
|
||||
namespace wasm {
|
||||
Error executeObjcopyOnBinary(const CopyConfig &Config,
|
||||
Error executeObjcopyOnBinary(const CommonConfig &Config, const WasmConfig &,
|
||||
object::WasmObjectFile &In, raw_ostream &Out);
|
||||
|
||||
} // end namespace wasm
|
||||
|
Loading…
Reference in New Issue
Block a user