forked from OSchip/llvm-project
[ifs] Switch to using OptTable
Differential revision: https://reviews.llvm.org/D125658
This commit is contained in:
parent
aed49eac87
commit
480dcdc897
|
@ -1,6 +1,5 @@
|
|||
# RUN: llvm-ifs --help | FileCheck %s --check-prefix HELP --implicit-check-not='{{[Oo]}}ptions:'
|
||||
|
||||
# HELP: USAGE
|
||||
# HELP: Color Options
|
||||
# HELP: Generic Options
|
||||
# HELP: Ifs Options
|
||||
# HELP: OVERVIEW:
|
||||
# HELP: USAGE:
|
||||
# HELP: OPTIONS:
|
||||
|
|
|
@ -5,9 +5,17 @@ set(LLVM_LINK_COMPONENTS
|
|||
Support
|
||||
TextAPI
|
||||
ObjectYAML
|
||||
Option
|
||||
)
|
||||
|
||||
set(LLVM_TARGET_DEFINITIONS Opts.td)
|
||||
tablegen(LLVM Opts.inc -gen-opt-parser-defs)
|
||||
add_public_tablegen_target(IFSOptsTableGen)
|
||||
|
||||
add_llvm_tool(llvm-ifs
|
||||
ErrorCollector.cpp
|
||||
llvm-ifs.cpp
|
||||
|
||||
DEPENDS
|
||||
IFSOptsTableGen
|
||||
)
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
include "llvm/Option/OptParser.td"
|
||||
|
||||
class F<string letter, string help> : Flag<["-"], letter>, HelpText<help>;
|
||||
class FF<string name, string help> : Flag<["--"], name>, HelpText<help>;
|
||||
|
||||
multiclass Eq<string name, string help> {
|
||||
def NAME #_EQ : Joined<["--"], name #"=">, HelpText<help>;
|
||||
def : Separate<["--"], name>, Alias<!cast<Joined>(NAME #_EQ)>;
|
||||
}
|
||||
|
||||
defm arch : Eq<"arch", "Specify the architecture, e.g. x86_64">;
|
||||
defm bitwidth : Eq<"bitwidth", "Specify the bit width">;
|
||||
defm endianness : Eq<"endianness", "Specify the endianness">;
|
||||
defm exclude : Eq<"exclude", "Remove symbols which match the pattern. Can be specified multiple times">;
|
||||
def help : FF<"help", "Display this help">;
|
||||
def : F<"h", "Alias for --help">, Alias<help>;
|
||||
defm hint_ifs_target : Eq<"hint-ifs-target", "When --output-format is 'IFS', this flag will hint the expected target triple for IFS output">;
|
||||
defm input : Eq<"input", "input">;
|
||||
defm input_format : Eq<"input-format", "Specify the input file format">;
|
||||
defm output : Eq<"output", "Output file **DEPRECATED**">;
|
||||
def : Separate<["-"], "o">, HelpText<"Alias for --output">, Alias<output_EQ>;
|
||||
defm output_elf : Eq<"output-elf", "Output path for ELF file">;
|
||||
defm output_format : Eq<"output-format", "Specify the output file format **DEPRECATED**">;
|
||||
defm output_ifs : Eq<"output-ifs", "Output path for IFS file">;
|
||||
defm output_tbd : Eq<"output-tbd", "Output path for TBD file">;
|
||||
defm soname : Eq<"soname", "name">;
|
||||
def strip_ifs_arch : FF<"strip-ifs-arch", "Strip target architecture information away from IFS output">;
|
||||
def strip_ifs_bitwidth : FF<"strip-ifs-bitwidth", "Strip target bit width information away from IFS output">;
|
||||
def strip_ifs_endianness : FF<"strip-ifs-endianness", "Strip target endianness information away from IFS output">;
|
||||
def strip_ifs_target : FF<"strip-ifs-target", "Strip all target information away from IFS output">;
|
||||
def strip_needed : FF<"strip-needed", "Strip needed libs from output">;
|
||||
def strip_size : FF<"strip-size", "Remove object size from the output">;
|
||||
def strip_undefined : FF<"strip-undefined", "Strip undefined symbols from IFS output">;
|
||||
defm target : Eq<"target", "Specify the target triple, e.g. x86_64-linux-gnu">;
|
||||
def version : FF<"version", "Display the version">;
|
||||
def : F<"V", "Alias for --version">, Alias<version>;
|
||||
def write_if_changed : FF<"write-if-changed", "Write the output file only if it is new or has changed">;
|
|
@ -15,6 +15,9 @@
|
|||
#include "llvm/InterfaceStub/IFSHandler.h"
|
||||
#include "llvm/InterfaceStub/IFSStub.h"
|
||||
#include "llvm/ObjectYAML/yaml2obj.h"
|
||||
#include "llvm/Option/Arg.h"
|
||||
#include "llvm/Option/ArgList.h"
|
||||
#include "llvm/Option/Option.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Errc.h"
|
||||
|
@ -46,100 +49,68 @@ const VersionTuple IfsVersionCurrent(3, 0);
|
|||
enum class FileFormat { IFS, ELF, TBD };
|
||||
} // end anonymous namespace
|
||||
|
||||
cl::OptionCategory IfsCategory("Ifs Options");
|
||||
using namespace llvm::opt;
|
||||
enum ID {
|
||||
OPT_INVALID = 0, // This is not an option ID.
|
||||
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
|
||||
HELPTEXT, METAVAR, VALUES) \
|
||||
OPT_##ID,
|
||||
#include "Opts.inc"
|
||||
#undef OPTION
|
||||
};
|
||||
|
||||
// TODO: Use OptTable for option parsing in the future.
|
||||
// Command line flags:
|
||||
cl::list<std::string> InputFilePaths(cl::Positional, cl::desc("input"),
|
||||
cl::ZeroOrMore, cl::cat(IfsCategory));
|
||||
cl::opt<FileFormat> InputFormat(
|
||||
"input-format", cl::desc("Specify the input file format"),
|
||||
cl::values(clEnumValN(FileFormat::IFS, "IFS", "Text based ELF stub file"),
|
||||
clEnumValN(FileFormat::ELF, "ELF", "ELF object file")),
|
||||
cl::cat(IfsCategory));
|
||||
cl::opt<FileFormat> OutputFormat(
|
||||
"output-format", cl::desc("Specify the output file format **DEPRECATED**"),
|
||||
cl::values(clEnumValN(FileFormat::IFS, "IFS", "Text based ELF stub file"),
|
||||
clEnumValN(FileFormat::ELF, "ELF", "ELF stub file"),
|
||||
clEnumValN(FileFormat::TBD, "TBD", "Apple TBD text stub file")),
|
||||
cl::cat(IfsCategory));
|
||||
cl::opt<std::string> OptArch("arch",
|
||||
cl::desc("Specify the architecture, e.g. x86_64"),
|
||||
cl::cat(IfsCategory));
|
||||
cl::opt<IFSBitWidthType>
|
||||
OptBitWidth("bitwidth", cl::desc("Specify the bit width"),
|
||||
cl::values(clEnumValN(IFSBitWidthType::IFS32, "32", "32 bits"),
|
||||
clEnumValN(IFSBitWidthType::IFS64, "64", "64 bits")),
|
||||
cl::cat(IfsCategory));
|
||||
cl::opt<IFSEndiannessType> OptEndianness(
|
||||
"endianness", cl::desc("Specify the endianness"),
|
||||
cl::values(clEnumValN(IFSEndiannessType::Little, "little", "Little Endian"),
|
||||
clEnumValN(IFSEndiannessType::Big, "big", "Big Endian")),
|
||||
cl::cat(IfsCategory));
|
||||
cl::opt<std::string> OptTargetTriple(
|
||||
"target", cl::desc("Specify the target triple, e.g. x86_64-linux-gnu"),
|
||||
cl::cat(IfsCategory));
|
||||
cl::opt<std::string> OptTargetTripleHint(
|
||||
"hint-ifs-target",
|
||||
cl::desc("When --output-format is 'IFS', this flag will hint the expected "
|
||||
"target triple for IFS output"),
|
||||
cl::cat(IfsCategory));
|
||||
cl::opt<bool> StripIFSArch(
|
||||
"strip-ifs-arch",
|
||||
cl::desc("Strip target architecture information away from IFS output"),
|
||||
cl::cat(IfsCategory));
|
||||
cl::opt<bool> StripIFSBitWidth(
|
||||
"strip-ifs-bitwidth",
|
||||
cl::desc("Strip target bit width information away from IFS output"),
|
||||
cl::cat(IfsCategory));
|
||||
cl::opt<bool> StripIFSEndiannessWidth(
|
||||
"strip-ifs-endianness",
|
||||
cl::desc("Strip target endianness information away from IFS output"),
|
||||
cl::cat(IfsCategory));
|
||||
cl::opt<bool> StripIFSTarget(
|
||||
"strip-ifs-target",
|
||||
cl::desc("Strip all target information away from IFS output"),
|
||||
cl::cat(IfsCategory));
|
||||
cl::opt<bool>
|
||||
StripUndefined("strip-undefined",
|
||||
cl::desc("Strip undefined symbols from IFS output"),
|
||||
cl::cat(IfsCategory));
|
||||
cl::opt<bool> StripNeededLibs("strip-needed",
|
||||
cl::desc("Strip needed libs from output"),
|
||||
cl::cat(IfsCategory));
|
||||
cl::opt<bool> StripSize("strip-size",
|
||||
cl::desc("Remove object size from the output"),
|
||||
cl::cat(IfsCategory));
|
||||
#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
|
||||
#include "Opts.inc"
|
||||
#undef PREFIX
|
||||
|
||||
cl::list<std::string>
|
||||
ExcludeSyms("exclude",
|
||||
cl::desc("Remove symbols which match the pattern. Can be "
|
||||
"specified multiple times"),
|
||||
cl::cat(IfsCategory));
|
||||
const opt::OptTable::Info InfoTable[] = {
|
||||
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
|
||||
HELPTEXT, METAVAR, VALUES) \
|
||||
{ \
|
||||
PREFIX, NAME, HELPTEXT, \
|
||||
METAVAR, OPT_##ID, opt::Option::KIND##Class, \
|
||||
PARAM, FLAGS, OPT_##GROUP, \
|
||||
OPT_##ALIAS, ALIASARGS, VALUES},
|
||||
#include "Opts.inc"
|
||||
#undef OPTION
|
||||
};
|
||||
|
||||
cl::opt<std::string>
|
||||
SoName("soname",
|
||||
cl::desc("Manually set the DT_SONAME entry of any emitted files"),
|
||||
cl::value_desc("name"), cl::cat(IfsCategory));
|
||||
cl::opt<std::string> OutputFilePath("output",
|
||||
cl::desc("Output file **DEPRECATED**"),
|
||||
cl::cat(IfsCategory));
|
||||
cl::alias OutputFilePathA("o", cl::desc("Alias for --output"),
|
||||
cl::aliasopt(OutputFilePath), cl::cat(IfsCategory));
|
||||
cl::opt<std::string> OutputELFFilePath("output-elf",
|
||||
cl::desc("Output path for ELF file"),
|
||||
cl::cat(IfsCategory));
|
||||
cl::opt<std::string> OutputIFSFilePath("output-ifs",
|
||||
cl::desc("Output path for IFS file"),
|
||||
cl::cat(IfsCategory));
|
||||
cl::opt<std::string> OutputTBDFilePath("output-tbd",
|
||||
cl::desc("Output path for TBD file"),
|
||||
cl::cat(IfsCategory));
|
||||
class IFSOptTable : public opt::OptTable {
|
||||
public:
|
||||
IFSOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
|
||||
};
|
||||
|
||||
cl::opt<bool> WriteIfChanged(
|
||||
"write-if-changed",
|
||||
cl::desc("Write the output file only if it is new or has changed."),
|
||||
cl::cat(IfsCategory));
|
||||
struct DriverConfig {
|
||||
std::vector<std::string> InputFilePaths;
|
||||
|
||||
Optional<FileFormat> InputFormat;
|
||||
Optional<FileFormat> OutputFormat;
|
||||
|
||||
Optional<std::string> HintIfsTarget;
|
||||
Optional<std::string> OptTargetTriple;
|
||||
Optional<IFSArch> OverrideArch;
|
||||
Optional<IFSBitWidthType> OverrideBitWidth;
|
||||
Optional<IFSEndiannessType> OverrideEndianness;
|
||||
|
||||
bool StripIfsArch = false;
|
||||
bool StripIfsBitwidth = false;
|
||||
bool StripIfsEndianness = false;
|
||||
bool StripIfsTarget = false;
|
||||
bool StripNeeded = false;
|
||||
bool StripSize = false;
|
||||
bool StripUndefined = false;
|
||||
|
||||
std::vector<std::string> Exclude;
|
||||
|
||||
Optional<std::string> SoName;
|
||||
|
||||
Optional<std::string> Output;
|
||||
Optional<std::string> OutputElf;
|
||||
Optional<std::string> OutputIfs;
|
||||
Optional<std::string> OutputTbd;
|
||||
|
||||
bool WriteIfChanged = false;
|
||||
};
|
||||
|
||||
static std::string getTypeName(IFSSymbolType Type) {
|
||||
switch (Type) {
|
||||
|
@ -157,7 +128,8 @@ static std::string getTypeName(IFSSymbolType Type) {
|
|||
llvm_unreachable("Unexpected ifs symbol type.");
|
||||
}
|
||||
|
||||
static Expected<std::unique_ptr<IFSStub>> readInputFile(StringRef FilePath) {
|
||||
static Expected<std::unique_ptr<IFSStub>>
|
||||
readInputFile(Optional<FileFormat> &InputFormat, StringRef FilePath) {
|
||||
// Read in file.
|
||||
ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrError =
|
||||
MemoryBuffer::getFileOrSTDIN(FilePath, /*IsText=*/true);
|
||||
|
@ -169,10 +141,11 @@ static Expected<std::unique_ptr<IFSStub>> readInputFile(StringRef FilePath) {
|
|||
ErrorCollector EC(/*UseFatalErrors=*/false);
|
||||
|
||||
// First try to read as a binary (fails fast if not binary).
|
||||
if (InputFormat.getNumOccurrences() == 0 || InputFormat == FileFormat::ELF) {
|
||||
if (!InputFormat || *InputFormat == FileFormat::ELF) {
|
||||
Expected<std::unique_ptr<IFSStub>> StubFromELF =
|
||||
readELFFile(FileReadBuffer->getMemBufferRef());
|
||||
if (StubFromELF) {
|
||||
InputFormat = FileFormat::ELF;
|
||||
(*StubFromELF)->IfsVersion = IfsVersionCurrent;
|
||||
return std::move(*StubFromELF);
|
||||
}
|
||||
|
@ -180,10 +153,11 @@ static Expected<std::unique_ptr<IFSStub>> readInputFile(StringRef FilePath) {
|
|||
}
|
||||
|
||||
// Fall back to reading as a ifs.
|
||||
if (InputFormat.getNumOccurrences() == 0 || InputFormat == FileFormat::IFS) {
|
||||
if (!InputFormat || *InputFormat == FileFormat::IFS) {
|
||||
Expected<std::unique_ptr<IFSStub>> StubFromIFS =
|
||||
readIFSFromBuffer(FileReadBuffer->getBuffer());
|
||||
if (StubFromIFS) {
|
||||
InputFormat = FileFormat::IFS;
|
||||
if ((*StubFromIFS)->IfsVersion > IfsVersionCurrent)
|
||||
EC.addError(
|
||||
createStringError(errc::not_supported,
|
||||
|
@ -271,9 +245,14 @@ static void fatalError(Error Err) {
|
|||
exit(1);
|
||||
}
|
||||
|
||||
static void fatalError(Twine T) {
|
||||
WithColor::error() << T.str() << '\n';
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/// writeIFS() writes a Text-Based ELF stub to a file using the latest version
|
||||
/// of the YAML parser.
|
||||
static Error writeIFS(StringRef FilePath, IFSStub &Stub) {
|
||||
static Error writeIFS(StringRef FilePath, IFSStub &Stub, bool WriteIfChanged) {
|
||||
// Write IFS to memory first.
|
||||
std::string IFSStr;
|
||||
raw_string_ostream OutStr(IFSStr);
|
||||
|
@ -285,7 +264,8 @@ static Error writeIFS(StringRef FilePath, IFSStub &Stub) {
|
|||
if (WriteIfChanged) {
|
||||
if (ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrError =
|
||||
MemoryBuffer::getFile(FilePath)) {
|
||||
// Compare IFS output with the existing IFS file. If unchanged, avoid changing the file.
|
||||
// Compare IFS output with the existing IFS file. If unchanged, avoid
|
||||
// changing the file.
|
||||
if ((*BufOrError)->getBuffer() == IFSStr)
|
||||
return Error::success();
|
||||
}
|
||||
|
@ -300,24 +280,119 @@ static Error writeIFS(StringRef FilePath, IFSStub &Stub) {
|
|||
return Error::success();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// Parse arguments.
|
||||
cl::HideUnrelatedOptions({&IfsCategory, &getColorCategory()});
|
||||
cl::ParseCommandLineOptions(argc, argv);
|
||||
static DriverConfig parseArgs(int argc, char *const *argv) {
|
||||
BumpPtrAllocator A;
|
||||
StringSaver Saver(A);
|
||||
IFSOptTable Tbl;
|
||||
StringRef ToolName = argv[0];
|
||||
llvm::opt::InputArgList Args = Tbl.parseArgs(
|
||||
argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) { fatalError(Msg); });
|
||||
if (Args.hasArg(OPT_help)) {
|
||||
Tbl.printHelp(llvm::outs(),
|
||||
(Twine(ToolName) + " <input_file> <output_file> [options]")
|
||||
.str()
|
||||
.c_str(),
|
||||
"shared object stubbing tool");
|
||||
std::exit(0);
|
||||
}
|
||||
if (Args.hasArg(OPT_version)) {
|
||||
llvm::outs() << ToolName << '\n';
|
||||
cl::PrintVersionMessage();
|
||||
std::exit(0);
|
||||
}
|
||||
|
||||
if (InputFilePaths.empty())
|
||||
InputFilePaths.push_back("-");
|
||||
DriverConfig Config;
|
||||
for (const opt::Arg *A : Args.filtered(OPT_INPUT))
|
||||
Config.InputFilePaths.push_back(A->getValue());
|
||||
if (const opt::Arg *A = Args.getLastArg(OPT_input_format_EQ)) {
|
||||
Config.InputFormat = StringSwitch<Optional<FileFormat>>(A->getValue())
|
||||
.Case("IFS", FileFormat::IFS)
|
||||
.Case("ELF", FileFormat::ELF)
|
||||
.Default(None);
|
||||
if (!Config.InputFormat)
|
||||
fatalError(Twine("invalid argument '") + A->getValue());
|
||||
}
|
||||
|
||||
auto OptionNotFound = [ToolName](StringRef FlagName, StringRef OptionName) {
|
||||
fatalError(Twine(ToolName) + ": for the " + FlagName +
|
||||
" option: Cannot find option named '" + OptionName + "'!");
|
||||
};
|
||||
if (const opt::Arg *A = Args.getLastArg(OPT_output_format_EQ)) {
|
||||
Config.OutputFormat = StringSwitch<Optional<FileFormat>>(A->getValue())
|
||||
.Case("IFS", FileFormat::IFS)
|
||||
.Case("ELF", FileFormat::ELF)
|
||||
.Case("TBD", FileFormat::TBD)
|
||||
.Default(None);
|
||||
if (!Config.OutputFormat)
|
||||
OptionNotFound("--output-format", A->getValue());
|
||||
}
|
||||
if (const opt::Arg *A = Args.getLastArg(OPT_arch_EQ))
|
||||
Config.OverrideArch = ELF::convertArchNameToEMachine(A->getValue());
|
||||
|
||||
if (const opt::Arg *A = Args.getLastArg(OPT_bitwidth_EQ)) {
|
||||
size_t Width;
|
||||
llvm::StringRef S(A->getValue());
|
||||
if (!S.getAsInteger<size_t>(10, Width) || Width == 64 || Width == 32)
|
||||
Config.OverrideBitWidth =
|
||||
Width == 64 ? IFSBitWidthType::IFS64 : IFSBitWidthType::IFS32;
|
||||
else
|
||||
OptionNotFound("--bitwidth", A->getValue());
|
||||
}
|
||||
if (const opt::Arg *A = Args.getLastArg(OPT_endianness_EQ)) {
|
||||
Config.OverrideEndianness =
|
||||
StringSwitch<Optional<IFSEndiannessType>>(A->getValue())
|
||||
.Case("little", IFSEndiannessType::Little)
|
||||
.Case("big", IFSEndiannessType::Big)
|
||||
.Default(None);
|
||||
if (!Config.OverrideEndianness)
|
||||
OptionNotFound("--endianness", A->getValue());
|
||||
}
|
||||
if (const opt::Arg *A = Args.getLastArg(OPT_target_EQ))
|
||||
Config.OptTargetTriple = A->getValue();
|
||||
if (const opt::Arg *A = Args.getLastArg(OPT_hint_ifs_target_EQ))
|
||||
Config.HintIfsTarget = A->getValue();
|
||||
|
||||
Config.StripIfsArch = Args.hasArg(OPT_strip_ifs_arch);
|
||||
Config.StripIfsBitwidth = Args.hasArg(OPT_strip_ifs_bitwidth);
|
||||
Config.StripIfsEndianness = Args.hasArg(OPT_strip_ifs_endianness);
|
||||
Config.StripIfsTarget = Args.hasArg(OPT_strip_ifs_target);
|
||||
Config.StripUndefined = Args.hasArg(OPT_strip_undefined);
|
||||
Config.StripNeeded = Args.hasArg(OPT_strip_needed);
|
||||
Config.StripSize = Args.hasArg(OPT_strip_size);
|
||||
|
||||
for (const opt::Arg *A : Args.filtered(OPT_exclude_EQ))
|
||||
Config.Exclude.push_back(A->getValue());
|
||||
if (const opt::Arg *A = Args.getLastArg(OPT_soname_EQ))
|
||||
Config.SoName = A->getValue();
|
||||
if (const opt::Arg *A = Args.getLastArg(OPT_output_EQ))
|
||||
Config.Output = A->getValue();
|
||||
if (const opt::Arg *A = Args.getLastArg(OPT_output_elf_EQ))
|
||||
Config.OutputElf = A->getValue();
|
||||
if (const opt::Arg *A = Args.getLastArg(OPT_output_ifs_EQ))
|
||||
Config.OutputIfs = A->getValue();
|
||||
if (const opt::Arg *A = Args.getLastArg(OPT_output_tbd_EQ))
|
||||
Config.OutputTbd = A->getValue();
|
||||
Config.WriteIfChanged = Args.hasArg(OPT_write_if_changed);
|
||||
return Config;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
DriverConfig Config = parseArgs(argc, argv);
|
||||
|
||||
if (Config.InputFilePaths.empty())
|
||||
Config.InputFilePaths.push_back("-");
|
||||
|
||||
// If input files are more than one, they can only be IFS files.
|
||||
if (InputFilePaths.size() > 1)
|
||||
InputFormat.setValue(FileFormat::IFS);
|
||||
if (Config.InputFilePaths.size() > 1)
|
||||
Config.InputFormat = FileFormat::IFS;
|
||||
|
||||
// Attempt to merge input.
|
||||
IFSStub Stub;
|
||||
std::map<std::string, IFSSymbol> SymbolMap;
|
||||
std::string PreviousInputFilePath;
|
||||
for (const std::string &InputFilePath : InputFilePaths) {
|
||||
Expected<std::unique_ptr<IFSStub>> StubOrErr = readInputFile(InputFilePath);
|
||||
for (const std::string &InputFilePath : Config.InputFilePaths) {
|
||||
Expected<std::unique_ptr<IFSStub>> StubOrErr =
|
||||
readInputFile(Config.InputFormat, InputFilePath);
|
||||
if (!StubOrErr)
|
||||
fatalError(StubOrErr.takeError());
|
||||
|
||||
|
@ -411,57 +486,45 @@ int main(int argc, char *argv[]) {
|
|||
Stub.Symbols.push_back(Entry.second);
|
||||
|
||||
// Change SoName before emitting stubs.
|
||||
if (SoName.getNumOccurrences() == 1)
|
||||
Stub.SoName = SoName;
|
||||
Optional<IFSArch> OverrideArch;
|
||||
Optional<IFSEndiannessType> OverrideEndianness;
|
||||
Optional<IFSBitWidthType> OverrideBitWidth;
|
||||
Optional<std::string> OverrideTriple;
|
||||
if (OptArch.getNumOccurrences() == 1)
|
||||
OverrideArch = ELF::convertArchNameToEMachine(OptArch.getValue());
|
||||
if (OptEndianness.getNumOccurrences() == 1)
|
||||
OverrideEndianness = OptEndianness.getValue();
|
||||
if (OptBitWidth.getNumOccurrences() == 1)
|
||||
OverrideBitWidth = OptBitWidth.getValue();
|
||||
if (OptTargetTriple.getNumOccurrences() == 1)
|
||||
OverrideTriple = OptTargetTriple.getValue();
|
||||
Error OverrideError = overrideIFSTarget(
|
||||
Stub, OverrideArch, OverrideEndianness, OverrideBitWidth, OverrideTriple);
|
||||
if (Config.SoName)
|
||||
Stub.SoName = *Config.SoName;
|
||||
|
||||
Error OverrideError =
|
||||
overrideIFSTarget(Stub, Config.OverrideArch, Config.OverrideEndianness,
|
||||
Config.OverrideBitWidth, Config.OptTargetTriple);
|
||||
if (OverrideError)
|
||||
fatalError(std::move(OverrideError));
|
||||
|
||||
if (StripNeededLibs)
|
||||
if (Config.StripNeeded)
|
||||
Stub.NeededLibs.clear();
|
||||
|
||||
if (Error E = filterIFSSyms(Stub, StripUndefined, ExcludeSyms))
|
||||
if (Error E = filterIFSSyms(Stub, Config.StripUndefined, Config.Exclude))
|
||||
fatalError(std::move(E));
|
||||
|
||||
if (StripSize)
|
||||
if (Config.StripSize)
|
||||
for (IFSSymbol &Sym : Stub.Symbols)
|
||||
Sym.Size.reset();
|
||||
|
||||
if (OutputELFFilePath.getNumOccurrences() == 0 &&
|
||||
OutputIFSFilePath.getNumOccurrences() == 0 &&
|
||||
OutputTBDFilePath.getNumOccurrences() == 0) {
|
||||
if (OutputFormat.getNumOccurrences() == 0) {
|
||||
if (!Config.OutputElf && !Config.OutputIfs && !Config.OutputTbd) {
|
||||
if (!Config.OutputFormat) {
|
||||
WithColor::error() << "at least one output should be specified.";
|
||||
return -1;
|
||||
}
|
||||
} else if (OutputFormat.getNumOccurrences() == 1) {
|
||||
} else if (Config.OutputFormat) {
|
||||
WithColor::error() << "'--output-format' cannot be used with "
|
||||
"'--output-{FILE_FORMAT}' options at the same time";
|
||||
return -1;
|
||||
}
|
||||
if (OutputFormat.getNumOccurrences() == 1) {
|
||||
if (Config.OutputFormat) {
|
||||
// TODO: Remove OutputFormat flag in the next revision.
|
||||
WithColor::warning() << "--output-format option is deprecated, please use "
|
||||
"--output-{FILE_FORMAT} options instead\n";
|
||||
switch (OutputFormat.getValue()) {
|
||||
switch (Config.OutputFormat.getValue()) {
|
||||
case FileFormat::TBD: {
|
||||
std::error_code SysErr;
|
||||
raw_fd_ostream Out(OutputFilePath, SysErr);
|
||||
raw_fd_ostream Out(*Config.Output, SysErr);
|
||||
if (SysErr) {
|
||||
WithColor::error() << "Couldn't open " << OutputFilePath
|
||||
WithColor::error() << "Couldn't open " << *Config.Output
|
||||
<< " for writing.\n";
|
||||
return -1;
|
||||
}
|
||||
|
@ -475,10 +538,10 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
case FileFormat::IFS: {
|
||||
Stub.IfsVersion = IfsVersionCurrent;
|
||||
if (InputFormat.getValue() == FileFormat::ELF &&
|
||||
OptTargetTripleHint.getNumOccurrences() == 1) {
|
||||
if (Config.InputFormat.getValue() == FileFormat::ELF &&
|
||||
Config.HintIfsTarget) {
|
||||
std::error_code HintEC(1, std::generic_category());
|
||||
IFSTarget HintTarget = parseTriple(OptTargetTripleHint);
|
||||
IFSTarget HintTarget = parseTriple(*Config.HintIfsTarget);
|
||||
if (Stub.Target.Arch.getValue() != HintTarget.Arch.getValue())
|
||||
fatalError(make_error<StringError>(
|
||||
"Triple hint does not match the actual architecture", HintEC));
|
||||
|
@ -491,12 +554,13 @@ int main(int argc, char *argv[]) {
|
|||
"Triple hint does not match the actual bit width", HintEC));
|
||||
|
||||
stripIFSTarget(Stub, true, false, false, false);
|
||||
Stub.Target.Triple = OptTargetTripleHint.getValue();
|
||||
Stub.Target.Triple = Config.HintIfsTarget.getValue();
|
||||
} else {
|
||||
stripIFSTarget(Stub, StripIFSTarget, StripIFSArch,
|
||||
StripIFSEndiannessWidth, StripIFSBitWidth);
|
||||
stripIFSTarget(Stub, Config.StripIfsTarget, Config.StripIfsArch,
|
||||
Config.StripIfsEndianness, Config.StripIfsBitwidth);
|
||||
}
|
||||
Error IFSWriteError = writeIFS(OutputFilePath.getValue(), Stub);
|
||||
Error IFSWriteError =
|
||||
writeIFS(Config.Output.getValue(), Stub, Config.WriteIfChanged);
|
||||
if (IFSWriteError)
|
||||
fatalError(std::move(IFSWriteError));
|
||||
break;
|
||||
|
@ -506,7 +570,7 @@ int main(int argc, char *argv[]) {
|
|||
if (TargetError)
|
||||
fatalError(std::move(TargetError));
|
||||
Error BinaryWriteError =
|
||||
writeBinaryStub(OutputFilePath, Stub, WriteIfChanged);
|
||||
writeBinaryStub(*Config.Output, Stub, Config.WriteIfChanged);
|
||||
if (BinaryWriteError)
|
||||
fatalError(std::move(BinaryWriteError));
|
||||
break;
|
||||
|
@ -514,21 +578,21 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
} else {
|
||||
// Check if output path for individual format.
|
||||
if (OutputELFFilePath.getNumOccurrences() == 1) {
|
||||
if (Config.OutputElf) {
|
||||
Error TargetError = validateIFSTarget(Stub, true);
|
||||
if (TargetError)
|
||||
fatalError(std::move(TargetError));
|
||||
Error BinaryWriteError =
|
||||
writeBinaryStub(OutputELFFilePath, Stub, WriteIfChanged);
|
||||
writeBinaryStub(*Config.OutputElf, Stub, Config.WriteIfChanged);
|
||||
if (BinaryWriteError)
|
||||
fatalError(std::move(BinaryWriteError));
|
||||
}
|
||||
if (OutputIFSFilePath.getNumOccurrences() == 1) {
|
||||
if (Config.OutputIfs) {
|
||||
Stub.IfsVersion = IfsVersionCurrent;
|
||||
if (InputFormat.getValue() == FileFormat::ELF &&
|
||||
OptTargetTripleHint.getNumOccurrences() == 1) {
|
||||
if (Config.InputFormat.getValue() == FileFormat::ELF &&
|
||||
Config.HintIfsTarget) {
|
||||
std::error_code HintEC(1, std::generic_category());
|
||||
IFSTarget HintTarget = parseTriple(OptTargetTripleHint);
|
||||
IFSTarget HintTarget = parseTriple(*Config.HintIfsTarget);
|
||||
if (Stub.Target.Arch.getValue() != HintTarget.Arch.getValue())
|
||||
fatalError(make_error<StringError>(
|
||||
"Triple hint does not match the actual architecture", HintEC));
|
||||
|
@ -541,20 +605,21 @@ int main(int argc, char *argv[]) {
|
|||
"Triple hint does not match the actual bit width", HintEC));
|
||||
|
||||
stripIFSTarget(Stub, true, false, false, false);
|
||||
Stub.Target.Triple = OptTargetTripleHint.getValue();
|
||||
Stub.Target.Triple = Config.HintIfsTarget.getValue();
|
||||
} else {
|
||||
stripIFSTarget(Stub, StripIFSTarget, StripIFSArch,
|
||||
StripIFSEndiannessWidth, StripIFSBitWidth);
|
||||
stripIFSTarget(Stub, Config.StripIfsTarget, Config.StripIfsArch,
|
||||
Config.StripIfsEndianness, Config.StripIfsBitwidth);
|
||||
}
|
||||
Error IFSWriteError = writeIFS(OutputIFSFilePath.getValue(), Stub);
|
||||
Error IFSWriteError =
|
||||
writeIFS(Config.OutputIfs.getValue(), Stub, Config.WriteIfChanged);
|
||||
if (IFSWriteError)
|
||||
fatalError(std::move(IFSWriteError));
|
||||
}
|
||||
if (OutputTBDFilePath.getNumOccurrences() == 1) {
|
||||
if (Config.OutputTbd) {
|
||||
std::error_code SysErr;
|
||||
raw_fd_ostream Out(OutputTBDFilePath, SysErr);
|
||||
raw_fd_ostream Out(*Config.OutputTbd, SysErr);
|
||||
if (SysErr) {
|
||||
WithColor::error() << "Couldn't open " << OutputTBDFilePath
|
||||
WithColor::error() << "Couldn't open " << *Config.OutputTbd
|
||||
<< " for writing.\n";
|
||||
return -1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue