2013-08-09 10:31:14 +00:00
|
|
|
//===- llvm-readobj.cpp - Dump contents of an Object File -----------------===//
|
2012-03-01 01:36:50 +00:00
|
|
|
//
|
2019-01-19 08:50:56 +00:00
|
|
|
// 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
|
2012-03-01 01:36:50 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2013-02-05 20:27:22 +00:00
|
|
|
// This is a tool similar to readelf, except it works on multiple object file
|
|
|
|
// formats. The main purpose of this tool is to provide detailed output suitable
|
|
|
|
// for FileCheck.
|
2012-03-02 23:43:51 +00:00
|
|
|
//
|
2013-02-05 20:27:22 +00:00
|
|
|
// Flags should be similar to readelf where supported, but the output format
|
|
|
|
// does not need to be identical. The point is to not make users learn yet
|
|
|
|
// another set of flags.
|
2012-03-02 23:43:51 +00:00
|
|
|
//
|
2013-02-05 20:27:22 +00:00
|
|
|
// Output should be specialized for each format where appropriate.
|
2012-03-02 23:43:51 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2012-03-01 01:36:50 +00:00
|
|
|
|
2013-02-20 02:37:12 +00:00
|
|
|
#include "llvm-readobj.h"
|
2013-04-03 18:31:38 +00:00
|
|
|
#include "ObjDumper.h"
|
2017-09-20 18:33:35 +00:00
|
|
|
#include "WindowsResourceDumper.h"
|
2019-02-07 15:24:18 +00:00
|
|
|
#include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
|
2017-11-30 18:39:50 +00:00
|
|
|
#include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
|
2021-10-08 10:48:15 -07:00
|
|
|
#include "llvm/MC/TargetRegistry.h"
|
2013-04-03 18:31:38 +00:00
|
|
|
#include "llvm/Object/Archive.h"
|
2015-08-28 07:40:30 +00:00
|
|
|
#include "llvm/Object/COFFImportFile.h"
|
2020-08-27 18:20:13 +03:00
|
|
|
#include "llvm/Object/ELFObjectFile.h"
|
2015-03-24 20:26:55 +00:00
|
|
|
#include "llvm/Object/MachOUniversal.h"
|
2012-12-04 10:44:52 +00:00
|
|
|
#include "llvm/Object/ObjectFile.h"
|
2020-08-27 18:20:13 +03:00
|
|
|
#include "llvm/Object/Wasm.h"
|
2017-09-20 18:33:35 +00:00
|
|
|
#include "llvm/Object/WindowsResource.h"
|
2020-08-27 18:20:13 +03:00
|
|
|
#include "llvm/Object/XCOFFObjectFile.h"
|
2021-07-12 10:14:42 -07:00
|
|
|
#include "llvm/Option/Arg.h"
|
|
|
|
#include "llvm/Option/ArgList.h"
|
|
|
|
#include "llvm/Option/Option.h"
|
2013-04-03 18:31:38 +00:00
|
|
|
#include "llvm/Support/Casting.h"
|
2012-03-01 01:36:50 +00:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2013-04-03 18:31:38 +00:00
|
|
|
#include "llvm/Support/DataTypes.h"
|
2012-03-01 01:36:50 +00:00
|
|
|
#include "llvm/Support/Debug.h"
|
2020-08-27 18:20:13 +03:00
|
|
|
#include "llvm/Support/Errc.h"
|
2013-04-03 18:31:38 +00:00
|
|
|
#include "llvm/Support/FileSystem.h"
|
2018-01-10 00:14:19 +00:00
|
|
|
#include "llvm/Support/FormatVariadic.h"
|
2018-04-13 18:26:06 +00:00
|
|
|
#include "llvm/Support/InitLLVM.h"
|
2017-07-19 02:09:37 +00:00
|
|
|
#include "llvm/Support/Path.h"
|
2016-05-03 00:28:04 +00:00
|
|
|
#include "llvm/Support/ScopedPrinter.h"
|
2019-04-15 11:17:48 +00:00
|
|
|
#include "llvm/Support/WithColor.h"
|
2013-04-03 18:31:38 +00:00
|
|
|
|
2012-03-01 01:36:50 +00:00
|
|
|
using namespace llvm;
|
|
|
|
using namespace llvm::object;
|
|
|
|
|
2021-07-12 10:14:42 -07:00
|
|
|
namespace {
|
|
|
|
using namespace llvm::opt; // for HelpHidden in Opts.inc
|
|
|
|
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
|
|
|
|
};
|
|
|
|
|
|
|
|
#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
|
|
|
|
#include "Opts.inc"
|
|
|
|
#undef PREFIX
|
|
|
|
|
2021-10-18 22:21:54 -07:00
|
|
|
const opt::OptTable::Info InfoTable[] = {
|
2021-07-12 10:14:42 -07:00
|
|
|
#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
|
|
|
|
};
|
|
|
|
|
|
|
|
class ReadobjOptTable : public opt::OptTable {
|
|
|
|
public:
|
|
|
|
ReadobjOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
|
|
|
|
};
|
|
|
|
|
|
|
|
enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols };
|
|
|
|
} // namespace
|
|
|
|
|
2013-04-03 18:31:38 +00:00
|
|
|
namespace opts {
|
2021-07-12 10:14:42 -07:00
|
|
|
static bool Addrsig;
|
|
|
|
static bool All;
|
|
|
|
static bool ArchSpecificInfo;
|
|
|
|
static bool BBAddrMap;
|
|
|
|
bool ExpandRelocs;
|
|
|
|
static bool CGProfile;
|
|
|
|
bool Demangle;
|
|
|
|
static bool DependentLibraries;
|
|
|
|
static bool DynRelocs;
|
|
|
|
static bool DynamicSymbols;
|
|
|
|
static bool FileHeaders;
|
|
|
|
static bool Headers;
|
|
|
|
static std::vector<std::string> HexDump;
|
2021-12-10 23:27:06 +00:00
|
|
|
static bool PrettyPrint;
|
2021-07-12 10:14:42 -07:00
|
|
|
static bool PrintStackMap;
|
|
|
|
static bool PrintStackSizes;
|
|
|
|
static bool Relocations;
|
|
|
|
bool SectionData;
|
|
|
|
static bool SectionDetails;
|
|
|
|
static bool SectionHeaders;
|
|
|
|
bool SectionRelocations;
|
|
|
|
bool SectionSymbols;
|
|
|
|
static std::vector<std::string> StringDump;
|
|
|
|
static bool StringTable;
|
|
|
|
static bool Symbols;
|
|
|
|
static bool UnwindInfo;
|
|
|
|
static cl::boolOrDefault SectionMapping;
|
|
|
|
|
|
|
|
// ELF specific options.
|
|
|
|
static bool DynamicTable;
|
|
|
|
static bool ELFLinkerOptions;
|
|
|
|
static bool GnuHashTable;
|
|
|
|
static bool HashSymbols;
|
|
|
|
static bool HashTable;
|
|
|
|
static bool HashHistogram;
|
|
|
|
static bool NeededLibraries;
|
|
|
|
static bool Notes;
|
|
|
|
static bool ProgramHeaders;
|
|
|
|
bool RawRelr;
|
|
|
|
static bool SectionGroups;
|
|
|
|
static bool VersionInfo;
|
|
|
|
|
|
|
|
// Mach-O specific options.
|
|
|
|
static bool MachODataInCode;
|
|
|
|
static bool MachODysymtab;
|
|
|
|
static bool MachOIndirectSymbols;
|
|
|
|
static bool MachOLinkerOptions;
|
|
|
|
static bool MachOSegment;
|
|
|
|
static bool MachOVersionMin;
|
|
|
|
|
|
|
|
// PE/COFF specific options.
|
|
|
|
static bool CodeView;
|
|
|
|
static bool CodeViewEnableGHash;
|
|
|
|
static bool CodeViewMergedTypes;
|
|
|
|
bool CodeViewSubsectionBytes;
|
|
|
|
static bool COFFBaseRelocs;
|
|
|
|
static bool COFFDebugDirectory;
|
|
|
|
static bool COFFDirectives;
|
|
|
|
static bool COFFExports;
|
|
|
|
static bool COFFImports;
|
|
|
|
static bool COFFLoadConfig;
|
|
|
|
static bool COFFResources;
|
|
|
|
static bool COFFTLSDirectory;
|
|
|
|
|
2021-10-26 10:40:25 -04:00
|
|
|
// XCOFF specific options.
|
|
|
|
static bool XCOFFAuxiliaryHeader;
|
|
|
|
|
2021-07-12 10:14:42 -07:00
|
|
|
OutputStyleTy Output = OutputStyleTy::LLVM;
|
|
|
|
static std::vector<std::string> InputFilenames;
|
2013-04-03 18:31:38 +00:00
|
|
|
} // namespace opts
|
|
|
|
|
2019-08-20 12:49:15 +00:00
|
|
|
static StringRef ToolName;
|
|
|
|
|
2015-07-20 03:38:17 +00:00
|
|
|
namespace llvm {
|
|
|
|
|
2021-07-28 09:31:14 -07:00
|
|
|
[[noreturn]] static void error(Twine Msg) {
|
Recommit r369190 "[llvm-readobj/llvm-readelf] - Improve/cleanup the error reporting API."
Fix: Add a `consumeError` call removed by mistake to 'printStackSize',
this should fix the "Expected<T> must be checked before access or destruction." reported by following bot:
http://lab.llvm.org:8011/builders/clang-x64-windows-msvc/builds/9743/steps/stage%201%20check/logs/stdio
Original commit message:
Currently we have the following functions for error reporting:
LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg);
void reportError(Error Err, StringRef Input);
void reportWarning(Twine Msg);
void reportWarning(StringRef Input, Error Err);
void warn(llvm::Error Err);
void error(std::error_code EC);
Problems are: naming is inconsistent, arguments order is inconsistent,
some of the functions looks excessive.
After applying this patch we have:
void reportError(Error Err, StringRef Input);
void reportError(std::error_code EC, StringRef Input);
void reportWarning(Error Err, StringRef Input);
I'd be happy to remove reportError(std::error_code EC, StringRef Input) too, but it
is used by COFF heavily.
Test cases were updated, they show an improvement introduced.
Differential revision: https://reviews.llvm.org/D66286
llvm-svn: 369194
2019-08-17 16:07:18 +00:00
|
|
|
// Flush the standard output to print the error at a
|
|
|
|
// proper place.
|
2019-07-16 11:07:30 +00:00
|
|
|
fouts().flush();
|
2019-08-20 12:49:15 +00:00
|
|
|
WithColor::error(errs(), ToolName) << Msg << "\n";
|
2015-07-20 03:23:55 +00:00
|
|
|
exit(1);
|
2015-07-20 03:01:49 +00:00
|
|
|
}
|
|
|
|
|
2021-07-28 09:31:14 -07:00
|
|
|
[[noreturn]] void reportError(Error Err, StringRef Input) {
|
2019-08-13 12:07:41 +00:00
|
|
|
assert(Err);
|
2019-07-16 11:07:30 +00:00
|
|
|
if (Input == "-")
|
|
|
|
Input = "<stdin>";
|
2019-08-13 12:07:41 +00:00
|
|
|
handleAllErrors(createFileError(Input, std::move(Err)),
|
Recommit r369190 "[llvm-readobj/llvm-readelf] - Improve/cleanup the error reporting API."
Fix: Add a `consumeError` call removed by mistake to 'printStackSize',
this should fix the "Expected<T> must be checked before access or destruction." reported by following bot:
http://lab.llvm.org:8011/builders/clang-x64-windows-msvc/builds/9743/steps/stage%201%20check/logs/stdio
Original commit message:
Currently we have the following functions for error reporting:
LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg);
void reportError(Error Err, StringRef Input);
void reportWarning(Twine Msg);
void reportWarning(StringRef Input, Error Err);
void warn(llvm::Error Err);
void error(std::error_code EC);
Problems are: naming is inconsistent, arguments order is inconsistent,
some of the functions looks excessive.
After applying this patch we have:
void reportError(Error Err, StringRef Input);
void reportError(std::error_code EC, StringRef Input);
void reportWarning(Error Err, StringRef Input);
I'd be happy to remove reportError(std::error_code EC, StringRef Input) too, but it
is used by COFF heavily.
Test cases were updated, they show an improvement introduced.
Differential revision: https://reviews.llvm.org/D66286
llvm-svn: 369194
2019-08-17 16:07:18 +00:00
|
|
|
[&](const ErrorInfoBase &EI) { error(EI.message()); });
|
|
|
|
llvm_unreachable("error() call should never return");
|
2019-07-16 11:07:30 +00:00
|
|
|
}
|
|
|
|
|
Recommit r369190 "[llvm-readobj/llvm-readelf] - Improve/cleanup the error reporting API."
Fix: Add a `consumeError` call removed by mistake to 'printStackSize',
this should fix the "Expected<T> must be checked before access or destruction." reported by following bot:
http://lab.llvm.org:8011/builders/clang-x64-windows-msvc/builds/9743/steps/stage%201%20check/logs/stdio
Original commit message:
Currently we have the following functions for error reporting:
LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg);
void reportError(Error Err, StringRef Input);
void reportWarning(Twine Msg);
void reportWarning(StringRef Input, Error Err);
void warn(llvm::Error Err);
void error(std::error_code EC);
Problems are: naming is inconsistent, arguments order is inconsistent,
some of the functions looks excessive.
After applying this patch we have:
void reportError(Error Err, StringRef Input);
void reportError(std::error_code EC, StringRef Input);
void reportWarning(Error Err, StringRef Input);
I'd be happy to remove reportError(std::error_code EC, StringRef Input) too, but it
is used by COFF heavily.
Test cases were updated, they show an improvement introduced.
Differential revision: https://reviews.llvm.org/D66286
llvm-svn: 369194
2019-08-17 16:07:18 +00:00
|
|
|
void reportWarning(Error Err, StringRef Input) {
|
|
|
|
assert(Err);
|
2019-08-08 07:17:35 +00:00
|
|
|
if (Input == "-")
|
|
|
|
Input = "<stdin>";
|
2012-12-31 16:05:21 +00:00
|
|
|
|
Recommit r369190 "[llvm-readobj/llvm-readelf] - Improve/cleanup the error reporting API."
Fix: Add a `consumeError` call removed by mistake to 'printStackSize',
this should fix the "Expected<T> must be checked before access or destruction." reported by following bot:
http://lab.llvm.org:8011/builders/clang-x64-windows-msvc/builds/9743/steps/stage%201%20check/logs/stdio
Original commit message:
Currently we have the following functions for error reporting:
LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg);
void reportError(Error Err, StringRef Input);
void reportWarning(Twine Msg);
void reportWarning(StringRef Input, Error Err);
void warn(llvm::Error Err);
void error(std::error_code EC);
Problems are: naming is inconsistent, arguments order is inconsistent,
some of the functions looks excessive.
After applying this patch we have:
void reportError(Error Err, StringRef Input);
void reportError(std::error_code EC, StringRef Input);
void reportWarning(Error Err, StringRef Input);
I'd be happy to remove reportError(std::error_code EC, StringRef Input) too, but it
is used by COFF heavily.
Test cases were updated, they show an improvement introduced.
Differential revision: https://reviews.llvm.org/D66286
llvm-svn: 369194
2019-08-17 16:07:18 +00:00
|
|
|
// Flush the standard output to print the warning at a
|
|
|
|
// proper place.
|
|
|
|
fouts().flush();
|
2019-08-20 12:49:15 +00:00
|
|
|
handleAllErrors(
|
|
|
|
createFileError(Input, std::move(Err)), [&](const ErrorInfoBase &EI) {
|
|
|
|
WithColor::warning(errs(), ToolName) << EI.message() << "\n";
|
|
|
|
});
|
2016-07-14 02:24:01 +00:00
|
|
|
}
|
|
|
|
|
Recommit r369190 "[llvm-readobj/llvm-readelf] - Improve/cleanup the error reporting API."
Fix: Add a `consumeError` call removed by mistake to 'printStackSize',
this should fix the "Expected<T> must be checked before access or destruction." reported by following bot:
http://lab.llvm.org:8011/builders/clang-x64-windows-msvc/builds/9743/steps/stage%201%20check/logs/stdio
Original commit message:
Currently we have the following functions for error reporting:
LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg);
void reportError(Error Err, StringRef Input);
void reportWarning(Twine Msg);
void reportWarning(StringRef Input, Error Err);
void warn(llvm::Error Err);
void error(std::error_code EC);
Problems are: naming is inconsistent, arguments order is inconsistent,
some of the functions looks excessive.
After applying this patch we have:
void reportError(Error Err, StringRef Input);
void reportError(std::error_code EC, StringRef Input);
void reportWarning(Error Err, StringRef Input);
I'd be happy to remove reportError(std::error_code EC, StringRef Input) too, but it
is used by COFF heavily.
Test cases were updated, they show an improvement introduced.
Differential revision: https://reviews.llvm.org/D66286
llvm-svn: 369194
2019-08-17 16:07:18 +00:00
|
|
|
} // namespace llvm
|
|
|
|
|
2021-07-12 10:14:42 -07:00
|
|
|
static void parseOptions(const opt::InputArgList &Args) {
|
|
|
|
opts::Addrsig = Args.hasArg(OPT_addrsig);
|
|
|
|
opts::All = Args.hasArg(OPT_all);
|
|
|
|
opts::ArchSpecificInfo = Args.hasArg(OPT_arch_specific);
|
|
|
|
opts::BBAddrMap = Args.hasArg(OPT_bb_addr_map);
|
|
|
|
opts::CGProfile = Args.hasArg(OPT_cg_profile);
|
|
|
|
opts::Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, false);
|
|
|
|
opts::DependentLibraries = Args.hasArg(OPT_dependent_libraries);
|
|
|
|
opts::DynRelocs = Args.hasArg(OPT_dyn_relocations);
|
|
|
|
opts::DynamicSymbols = Args.hasArg(OPT_dyn_syms);
|
|
|
|
opts::ExpandRelocs = Args.hasArg(OPT_expand_relocs);
|
|
|
|
opts::FileHeaders = Args.hasArg(OPT_file_header);
|
|
|
|
opts::Headers = Args.hasArg(OPT_headers);
|
|
|
|
opts::HexDump = Args.getAllArgValues(OPT_hex_dump_EQ);
|
|
|
|
opts::Relocations = Args.hasArg(OPT_relocs);
|
|
|
|
opts::SectionData = Args.hasArg(OPT_section_data);
|
|
|
|
opts::SectionDetails = Args.hasArg(OPT_section_details);
|
|
|
|
opts::SectionHeaders = Args.hasArg(OPT_section_headers);
|
|
|
|
opts::SectionRelocations = Args.hasArg(OPT_section_relocations);
|
|
|
|
opts::SectionSymbols = Args.hasArg(OPT_section_symbols);
|
|
|
|
if (Args.hasArg(OPT_section_mapping))
|
|
|
|
opts::SectionMapping = cl::BOU_TRUE;
|
|
|
|
else if (Args.hasArg(OPT_section_mapping_EQ_false))
|
|
|
|
opts::SectionMapping = cl::BOU_FALSE;
|
|
|
|
else
|
|
|
|
opts::SectionMapping = cl::BOU_UNSET;
|
|
|
|
opts::PrintStackSizes = Args.hasArg(OPT_stack_sizes);
|
|
|
|
opts::PrintStackMap = Args.hasArg(OPT_stackmap);
|
|
|
|
opts::StringDump = Args.getAllArgValues(OPT_string_dump_EQ);
|
|
|
|
opts::StringTable = Args.hasArg(OPT_string_table);
|
|
|
|
opts::Symbols = Args.hasArg(OPT_symbols);
|
|
|
|
opts::UnwindInfo = Args.hasArg(OPT_unwind);
|
|
|
|
|
|
|
|
// ELF specific options.
|
|
|
|
opts::DynamicTable = Args.hasArg(OPT_dynamic_table);
|
|
|
|
opts::ELFLinkerOptions = Args.hasArg(OPT_elf_linker_options);
|
|
|
|
if (Arg *A = Args.getLastArg(OPT_elf_output_style_EQ)) {
|
2021-12-10 23:27:06 +00:00
|
|
|
std::string OutputStyleChoice = A->getValue();
|
|
|
|
opts::Output = StringSwitch<opts::OutputStyleTy>(OutputStyleChoice)
|
|
|
|
.Case("LLVM", opts::OutputStyleTy::LLVM)
|
|
|
|
.Case("GNU", opts::OutputStyleTy::GNU)
|
|
|
|
.Case("JSON", opts::OutputStyleTy::JSON)
|
|
|
|
.Default(opts::OutputStyleTy::UNKNOWN);
|
|
|
|
if (opts::Output == opts::OutputStyleTy::UNKNOWN) {
|
|
|
|
error("--elf-output-style value should be either 'LLVM', 'GNU', or "
|
|
|
|
"'JSON', but was '" +
|
|
|
|
OutputStyleChoice + "'");
|
|
|
|
}
|
2021-07-12 10:14:42 -07:00
|
|
|
}
|
|
|
|
opts::GnuHashTable = Args.hasArg(OPT_gnu_hash_table);
|
|
|
|
opts::HashSymbols = Args.hasArg(OPT_hash_symbols);
|
|
|
|
opts::HashTable = Args.hasArg(OPT_hash_table);
|
|
|
|
opts::HashHistogram = Args.hasArg(OPT_histogram);
|
|
|
|
opts::NeededLibraries = Args.hasArg(OPT_needed_libs);
|
|
|
|
opts::Notes = Args.hasArg(OPT_notes);
|
2021-12-10 23:27:06 +00:00
|
|
|
opts::PrettyPrint = Args.hasArg(OPT_pretty_print);
|
2021-07-12 10:14:42 -07:00
|
|
|
opts::ProgramHeaders = Args.hasArg(OPT_program_headers);
|
|
|
|
opts::RawRelr = Args.hasArg(OPT_raw_relr);
|
|
|
|
opts::SectionGroups = Args.hasArg(OPT_section_groups);
|
|
|
|
opts::VersionInfo = Args.hasArg(OPT_version_info);
|
|
|
|
|
|
|
|
// Mach-O specific options.
|
|
|
|
opts::MachODataInCode = Args.hasArg(OPT_macho_data_in_code);
|
|
|
|
opts::MachODysymtab = Args.hasArg(OPT_macho_dysymtab);
|
|
|
|
opts::MachOIndirectSymbols = Args.hasArg(OPT_macho_indirect_symbols);
|
|
|
|
opts::MachOLinkerOptions = Args.hasArg(OPT_macho_linker_options);
|
|
|
|
opts::MachOSegment = Args.hasArg(OPT_macho_segment);
|
|
|
|
opts::MachOVersionMin = Args.hasArg(OPT_macho_version_min);
|
|
|
|
|
|
|
|
// PE/COFF specific options.
|
|
|
|
opts::CodeView = Args.hasArg(OPT_codeview);
|
|
|
|
opts::CodeViewEnableGHash = Args.hasArg(OPT_codeview_ghash);
|
|
|
|
opts::CodeViewMergedTypes = Args.hasArg(OPT_codeview_merged_types);
|
|
|
|
opts::CodeViewSubsectionBytes = Args.hasArg(OPT_codeview_subsection_bytes);
|
|
|
|
opts::COFFBaseRelocs = Args.hasArg(OPT_coff_basereloc);
|
|
|
|
opts::COFFDebugDirectory = Args.hasArg(OPT_coff_debug_directory);
|
|
|
|
opts::COFFDirectives = Args.hasArg(OPT_coff_directives);
|
|
|
|
opts::COFFExports = Args.hasArg(OPT_coff_exports);
|
|
|
|
opts::COFFImports = Args.hasArg(OPT_coff_imports);
|
|
|
|
opts::COFFLoadConfig = Args.hasArg(OPT_coff_load_config);
|
|
|
|
opts::COFFResources = Args.hasArg(OPT_coff_resources);
|
|
|
|
opts::COFFTLSDirectory = Args.hasArg(OPT_coff_tls_directory);
|
|
|
|
|
2021-10-26 10:40:25 -04:00
|
|
|
// XCOFF specific options.
|
|
|
|
opts::XCOFFAuxiliaryHeader = Args.hasArg(OPT_auxiliary_header);
|
|
|
|
|
2021-07-12 10:14:42 -07:00
|
|
|
opts::InputFilenames = Args.getAllArgValues(OPT_INPUT);
|
|
|
|
}
|
|
|
|
|
2016-09-09 17:46:17 +00:00
|
|
|
namespace {
|
2016-11-08 22:24:53 +00:00
|
|
|
struct ReadObjTypeTableBuilder {
|
2017-03-24 17:26:38 +00:00
|
|
|
ReadObjTypeTableBuilder()
|
2022-01-08 11:56:44 -08:00
|
|
|
: IDTable(Allocator), TypeTable(Allocator), GlobalIDTable(Allocator),
|
|
|
|
GlobalTypeTable(Allocator) {}
|
2014-06-18 08:47:09 +00:00
|
|
|
|
2016-09-09 17:46:17 +00:00
|
|
|
llvm::BumpPtrAllocator Allocator;
|
2017-11-30 18:39:50 +00:00
|
|
|
llvm::codeview::MergingTypeTableBuilder IDTable;
|
|
|
|
llvm::codeview::MergingTypeTableBuilder TypeTable;
|
2019-02-07 15:24:18 +00:00
|
|
|
llvm::codeview::GlobalTypeTableBuilder GlobalIDTable;
|
|
|
|
llvm::codeview::GlobalTypeTableBuilder GlobalTypeTable;
|
|
|
|
std::vector<OwningBinary<Binary>> Binaries;
|
2016-09-09 17:46:17 +00:00
|
|
|
};
|
2019-02-07 15:24:18 +00:00
|
|
|
} // namespace
|
2016-11-08 22:24:53 +00:00
|
|
|
static ReadObjTypeTableBuilder CVTypes;
|
2016-05-14 00:02:53 +00:00
|
|
|
|
2018-05-01 16:10:38 +00:00
|
|
|
/// Creates an format-specific object file dumper.
|
2020-08-27 18:20:13 +03:00
|
|
|
static Expected<std::unique_ptr<ObjDumper>>
|
|
|
|
createDumper(const ObjectFile &Obj, ScopedPrinter &Writer) {
|
|
|
|
if (const COFFObjectFile *COFFObj = dyn_cast<COFFObjectFile>(&Obj))
|
|
|
|
return createCOFFDumper(*COFFObj, Writer);
|
|
|
|
|
|
|
|
if (const ELFObjectFileBase *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj))
|
|
|
|
return createELFDumper(*ELFObj, Writer);
|
|
|
|
|
|
|
|
if (const MachOObjectFile *MachOObj = dyn_cast<MachOObjectFile>(&Obj))
|
|
|
|
return createMachODumper(*MachOObj, Writer);
|
|
|
|
|
|
|
|
if (const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(&Obj))
|
|
|
|
return createWasmDumper(*WasmObj, Writer);
|
|
|
|
|
|
|
|
if (const XCOFFObjectFile *XObj = dyn_cast<XCOFFObjectFile>(&Obj))
|
|
|
|
return createXCOFFDumper(*XObj, Writer);
|
|
|
|
|
|
|
|
return createStringError(errc::invalid_argument,
|
|
|
|
"unsupported object file format");
|
2012-03-01 01:36:50 +00:00
|
|
|
}
|
|
|
|
|
2018-05-01 16:10:38 +00:00
|
|
|
/// Dumps the specified object file.
|
2020-11-09 12:18:18 +03:00
|
|
|
static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
|
2019-07-15 22:52:01 +00:00
|
|
|
const Archive *A = nullptr) {
|
|
|
|
std::string FileStr =
|
2020-08-27 18:20:13 +03:00
|
|
|
A ? Twine(A->getFileName() + "(" + Obj.getFileName() + ")").str()
|
|
|
|
: Obj.getFileName().str();
|
2019-07-15 22:52:01 +00:00
|
|
|
|
2020-11-09 12:18:18 +03:00
|
|
|
std::string ContentErrString;
|
|
|
|
if (Error ContentErr = Obj.initContent())
|
|
|
|
ContentErrString = "unable to continue dumping, the file is corrupt: " +
|
|
|
|
toString(std::move(ContentErr));
|
|
|
|
|
2020-08-27 18:20:13 +03:00
|
|
|
ObjDumper *Dumper;
|
|
|
|
Expected<std::unique_ptr<ObjDumper>> DumperOrErr = createDumper(Obj, Writer);
|
|
|
|
if (!DumperOrErr)
|
|
|
|
reportError(DumperOrErr.takeError(), FileStr);
|
|
|
|
Dumper = (*DumperOrErr).get();
|
2012-12-31 16:29:44 +00:00
|
|
|
|
2021-12-10 23:27:06 +00:00
|
|
|
Dumper->printFileSummary(FileStr, Obj, opts::InputFilenames, A);
|
2013-04-03 18:31:38 +00:00
|
|
|
|
|
|
|
if (opts::FileHeaders)
|
|
|
|
Dumper->printFileHeaders();
|
2020-10-13 10:46:04 +03:00
|
|
|
|
2021-10-26 10:40:25 -04:00
|
|
|
if (Obj.isXCOFF() && opts::XCOFFAuxiliaryHeader)
|
|
|
|
Dumper->printAuxiliaryHeader();
|
|
|
|
|
2020-11-09 12:18:18 +03:00
|
|
|
// This is only used for ELF currently. In some cases, when an object is
|
|
|
|
// corrupt (e.g. truncated), we can't dump anything except the file header.
|
|
|
|
if (!ContentErrString.empty())
|
|
|
|
reportError(createError(ContentErrString), FileStr);
|
|
|
|
|
2020-10-13 10:46:04 +03:00
|
|
|
if (opts::SectionDetails || opts::SectionHeaders) {
|
|
|
|
if (opts::Output == opts::GNU && opts::SectionDetails)
|
|
|
|
Dumper->printSectionDetails();
|
|
|
|
else
|
|
|
|
Dumper->printSectionHeaders();
|
|
|
|
}
|
|
|
|
|
[llvm-readelf]Revert --dyn-symbols behaviour to make it GNU compatible, and add new --hash-symbols switch for old behaviour
In r287786, the behaviour of --dyn-symbols in llvm-readelf (but not
llvm-readobj) was changed to print the dynamic symbols as derived from
the hash table, rather than to print the dynamic symbol table contents
directly. The original change was initially submitted without review,
and some comments were made on the commit mailing list implying that the
new behavious is GNU compatible. I argue that it is not:
1) It does not include a null symbol.
2) It prints the symbols based on an order derived from the hash
table.
3) It prints an extra column indicating which bucket it came from.
This could break parsers that expect a fixed number of columns,
with the first column being the symbol index.
4) If the input happens to have both .hash and .gnu.hash section, it
prints interpretations of them both, resulting in most symbols
being printed twice.
5) There is no way of just printing the raw dynamic symbol table,
because --symbols also prints the static symbol table.
This patch reverts the --dyn-symbols behaviour back to its old behaviour
of just printing the contents of the dynamic symbol table, similar to
what is printed by --symbols. As the hashed interpretation is still
desirable to validate the hash table, it puts it under a new switch
"--hash-symbols". This is a no-op on all output forms except for GNU
output style for ELF. If there is no hash table, it does nothing,
unlike the previous behaviour which printed the raw dynamic symbol
table, since the raw dynsym is available under --dyn-symbols.
The yaml input for the test is based on that in
test/tools/llvm-readobj/demangle.test, but stripped down to the bare
minimum to provide a valid dynamic symbol.
Note: some LLD tests needed updating. I will commit a separate patch for
those.
Reviewed by: grimar, rupprecht
Differential Revision: https://reviews.llvm.org/D56910
llvm-svn: 351789
2019-01-22 09:35:35 +00:00
|
|
|
if (opts::HashSymbols)
|
|
|
|
Dumper->printHashSymbols();
|
2020-03-03 19:49:14 -08:00
|
|
|
if (opts::ProgramHeaders || opts::SectionMapping == cl::BOU_TRUE)
|
|
|
|
Dumper->printProgramHeaders(opts::ProgramHeaders, opts::SectionMapping);
|
2013-04-03 18:31:38 +00:00
|
|
|
if (opts::DynamicTable)
|
|
|
|
Dumper->printDynamicTable();
|
|
|
|
if (opts::NeededLibraries)
|
|
|
|
Dumper->printNeededLibraries();
|
2020-03-03 19:49:14 -08:00
|
|
|
if (opts::Relocations)
|
|
|
|
Dumper->printRelocations();
|
|
|
|
if (opts::DynRelocs)
|
|
|
|
Dumper->printDynamicRelocations();
|
|
|
|
if (opts::UnwindInfo)
|
|
|
|
Dumper->printUnwindInfo();
|
|
|
|
if (opts::Symbols || opts::DynamicSymbols)
|
2022-03-31 09:33:04 -04:00
|
|
|
Dumper->printSymbols(opts::Symbols, opts::DynamicSymbols);
|
2018-06-15 14:15:02 +00:00
|
|
|
if (!opts::StringDump.empty())
|
2020-09-19 19:53:51 +03:00
|
|
|
Dumper->printSectionsAsString(Obj, opts::StringDump);
|
2018-07-11 10:00:29 +00:00
|
|
|
if (!opts::HexDump.empty())
|
2020-09-19 19:53:51 +03:00
|
|
|
Dumper->printSectionsAsHex(Obj, opts::HexDump);
|
2015-07-09 22:32:24 +00:00
|
|
|
if (opts::HashTable)
|
|
|
|
Dumper->printHashTable();
|
2015-10-14 12:11:50 +00:00
|
|
|
if (opts::GnuHashTable)
|
2020-09-19 19:53:51 +03:00
|
|
|
Dumper->printGnuHashTable();
|
2015-10-16 23:19:01 +00:00
|
|
|
if (opts::VersionInfo)
|
|
|
|
Dumper->printVersionInfo();
|
2021-07-05 04:16:58 +00:00
|
|
|
if (opts::StringTable)
|
|
|
|
Dumper->printStringTable();
|
2020-08-27 18:20:13 +03:00
|
|
|
if (Obj.isELF()) {
|
2019-11-25 16:04:58 +03:00
|
|
|
if (opts::DependentLibraries)
|
|
|
|
Dumper->printDependentLibs();
|
2018-01-30 16:29:29 +00:00
|
|
|
if (opts::ELFLinkerOptions)
|
|
|
|
Dumper->printELFLinkerOptions();
|
2019-10-04 11:59:06 +00:00
|
|
|
if (opts::ArchSpecificInfo)
|
|
|
|
Dumper->printArchSpecificInfo();
|
2016-01-26 19:46:39 +00:00
|
|
|
if (opts::SectionGroups)
|
|
|
|
Dumper->printGroupSections();
|
2016-04-11 17:15:30 +00:00
|
|
|
if (opts::HashHistogram)
|
2020-05-26 13:58:20 +03:00
|
|
|
Dumper->printHashHistograms();
|
[MC] Add assembler support for .cg_profile.
Object FIle Representation
At codegen time this is emitted into the ELF file a pair of symbol indices and a weight. In assembly it looks like:
.cg_profile a, b, 32
.cg_profile freq, a, 11
.cg_profile freq, b, 20
When writing an ELF file these are put into a SHT_LLVM_CALL_GRAPH_PROFILE (0x6fff4c02) section as (uint32_t, uint32_t, uint64_t) tuples as (from symbol index, to symbol index, weight).
Differential Revision: https://reviews.llvm.org/D44965
llvm-svn: 333823
2018-06-02 16:33:01 +00:00
|
|
|
if (opts::CGProfile)
|
|
|
|
Dumper->printCGProfile();
|
2021-03-08 16:02:00 -08:00
|
|
|
if (opts::BBAddrMap)
|
|
|
|
Dumper->printBBAddrMaps();
|
2018-07-17 22:17:18 +00:00
|
|
|
if (opts::Addrsig)
|
|
|
|
Dumper->printAddrsig();
|
2016-08-30 18:52:02 +00:00
|
|
|
if (opts::Notes)
|
|
|
|
Dumper->printNotes();
|
2015-05-07 15:40:35 +00:00
|
|
|
}
|
2020-08-27 18:20:13 +03:00
|
|
|
if (Obj.isCOFF()) {
|
2015-07-24 02:14:20 +00:00
|
|
|
if (opts::COFFImports)
|
|
|
|
Dumper->printCOFFImports();
|
|
|
|
if (opts::COFFExports)
|
|
|
|
Dumper->printCOFFExports();
|
|
|
|
if (opts::COFFDirectives)
|
|
|
|
Dumper->printCOFFDirectives();
|
|
|
|
if (opts::COFFBaseRelocs)
|
|
|
|
Dumper->printCOFFBaseReloc();
|
2016-06-02 17:10:43 +00:00
|
|
|
if (opts::COFFDebugDirectory)
|
|
|
|
Dumper->printCOFFDebugDirectory();
|
2020-10-08 01:43:50 -07:00
|
|
|
if (opts::COFFTLSDirectory)
|
|
|
|
Dumper->printCOFFTLSDirectory();
|
2017-04-27 19:38:38 +00:00
|
|
|
if (opts::COFFResources)
|
|
|
|
Dumper->printCOFFResources();
|
2017-06-22 01:10:29 +00:00
|
|
|
if (opts::COFFLoadConfig)
|
|
|
|
Dumper->printCOFFLoadConfig();
|
2020-06-15 16:29:36 -07:00
|
|
|
if (opts::CGProfile)
|
|
|
|
Dumper->printCGProfile();
|
2018-08-22 23:58:16 +00:00
|
|
|
if (opts::Addrsig)
|
|
|
|
Dumper->printAddrsig();
|
2015-12-16 18:28:12 +00:00
|
|
|
if (opts::CodeView)
|
|
|
|
Dumper->printCodeViewDebugInfo();
|
2016-05-14 00:02:53 +00:00
|
|
|
if (opts::CodeViewMergedTypes)
|
2019-02-07 15:24:18 +00:00
|
|
|
Dumper->mergeCodeViewTypes(CVTypes.IDTable, CVTypes.TypeTable,
|
|
|
|
CVTypes.GlobalIDTable, CVTypes.GlobalTypeTable,
|
|
|
|
opts::CodeViewEnableGHash);
|
2015-07-24 02:14:20 +00:00
|
|
|
}
|
2020-08-27 18:20:13 +03:00
|
|
|
if (Obj.isMachO()) {
|
2015-08-21 20:28:30 +00:00
|
|
|
if (opts::MachODataInCode)
|
|
|
|
Dumper->printMachODataInCode();
|
2015-09-03 18:10:28 +00:00
|
|
|
if (opts::MachOIndirectSymbols)
|
|
|
|
Dumper->printMachOIndirectSymbols();
|
2015-09-09 00:21:18 +00:00
|
|
|
if (opts::MachOLinkerOptions)
|
|
|
|
Dumper->printMachOLinkerOptions();
|
2015-09-02 16:24:24 +00:00
|
|
|
if (opts::MachOSegment)
|
|
|
|
Dumper->printMachOSegment();
|
2015-08-27 15:11:32 +00:00
|
|
|
if (opts::MachOVersionMin)
|
|
|
|
Dumper->printMachOVersionMin();
|
2015-08-31 19:32:31 +00:00
|
|
|
if (opts::MachODysymtab)
|
|
|
|
Dumper->printMachODysymtab();
|
2022-01-12 09:12:53 -05:00
|
|
|
if (opts::CGProfile)
|
|
|
|
Dumper->printCGProfile();
|
2015-08-31 17:12:23 +00:00
|
|
|
}
|
2015-06-26 23:56:53 +00:00
|
|
|
if (opts::PrintStackMap)
|
|
|
|
Dumper->printStackMap();
|
2019-08-05 22:47:07 +00:00
|
|
|
if (opts::PrintStackSizes)
|
|
|
|
Dumper->printStackSizes();
|
2012-03-01 22:19:54 +00:00
|
|
|
}
|
|
|
|
|
2018-05-01 16:10:38 +00:00
|
|
|
/// Dumps each object file in \a Arc;
|
2018-01-10 00:14:19 +00:00
|
|
|
static void dumpArchive(const Archive *Arc, ScopedPrinter &Writer) {
|
2016-11-11 04:28:40 +00:00
|
|
|
Error Err = Error::success();
|
2016-07-14 02:24:01 +00:00
|
|
|
for (auto &Child : Arc->children(Err)) {
|
2016-05-17 17:10:12 +00:00
|
|
|
Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary();
|
|
|
|
if (!ChildOrErr) {
|
2019-08-13 12:07:41 +00:00
|
|
|
if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
|
|
|
|
reportError(std::move(E), Arc->getFileName());
|
2013-04-03 18:31:38 +00:00
|
|
|
continue;
|
|
|
|
}
|
2020-08-28 12:18:19 +03:00
|
|
|
|
|
|
|
Binary *Bin = ChildOrErr->get();
|
|
|
|
if (ObjectFile *Obj = dyn_cast<ObjectFile>(Bin))
|
2020-08-27 18:20:13 +03:00
|
|
|
dumpObject(*Obj, Writer, Arc);
|
2020-08-28 12:18:19 +03:00
|
|
|
else if (COFFImportFile *Imp = dyn_cast<COFFImportFile>(Bin))
|
2018-01-10 00:14:19 +00:00
|
|
|
dumpCOFFImportFile(Imp, Writer);
|
2013-04-03 18:31:38 +00:00
|
|
|
else
|
2020-08-28 12:18:19 +03:00
|
|
|
reportWarning(createStringError(errc::invalid_argument,
|
|
|
|
Bin->getFileName() +
|
|
|
|
" has an unsupported file type"),
|
2020-08-28 13:33:20 +03:00
|
|
|
Arc->getFileName());
|
2012-03-01 01:36:50 +00:00
|
|
|
}
|
2016-07-14 02:24:01 +00:00
|
|
|
if (Err)
|
2019-08-13 12:07:41 +00:00
|
|
|
reportError(std::move(Err), Arc->getFileName());
|
2013-04-03 18:31:38 +00:00
|
|
|
}
|
|
|
|
|
2018-05-01 16:10:38 +00:00
|
|
|
/// Dumps each object file in \a MachO Universal Binary;
|
2018-01-10 00:14:19 +00:00
|
|
|
static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary,
|
|
|
|
ScopedPrinter &Writer) {
|
2015-03-24 20:26:55 +00:00
|
|
|
for (const MachOUniversalBinary::ObjectForArch &Obj : UBinary->objects()) {
|
2016-05-31 20:35:34 +00:00
|
|
|
Expected<std::unique_ptr<MachOObjectFile>> ObjOrErr = Obj.getAsObjectFile();
|
2015-04-13 16:05:49 +00:00
|
|
|
if (ObjOrErr)
|
2020-08-27 18:20:13 +03:00
|
|
|
dumpObject(*ObjOrErr.get(), Writer);
|
2019-08-13 12:07:41 +00:00
|
|
|
else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError()))
|
|
|
|
reportError(ObjOrErr.takeError(), UBinary->getFileName());
|
2016-06-28 23:16:13 +00:00
|
|
|
else if (Expected<std::unique_ptr<Archive>> AOrErr = Obj.getAsArchive())
|
2018-01-10 00:14:19 +00:00
|
|
|
dumpArchive(&*AOrErr.get(), Writer);
|
2015-03-24 20:26:55 +00:00
|
|
|
}
|
|
|
|
}
|
2012-03-01 01:36:50 +00:00
|
|
|
|
2018-05-01 16:10:38 +00:00
|
|
|
/// Dumps \a WinRes, Windows Resource (.res) file;
|
2019-06-12 20:16:22 +00:00
|
|
|
static void dumpWindowsResourceFile(WindowsResource *WinRes,
|
|
|
|
ScopedPrinter &Printer) {
|
2017-09-20 18:33:35 +00:00
|
|
|
WindowsRes::Dumper Dumper(WinRes, Printer);
|
|
|
|
if (auto Err = Dumper.printData())
|
2019-08-13 12:07:41 +00:00
|
|
|
reportError(std::move(Err), WinRes->getFileName());
|
2017-09-20 18:33:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-05-01 16:10:38 +00:00
|
|
|
/// Opens \a File and dumps it.
|
2019-06-12 20:16:22 +00:00
|
|
|
static void dumpInput(StringRef File, ScopedPrinter &Writer) {
|
2021-01-28 13:28:55 +03:00
|
|
|
ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
|
[NFC] Reordering parameters in getFile and getFileOrSTDIN
In future patches I will be setting the IsText parameter frequently so I will refactor the args to be in the following order. I have removed the FileSize parameter because it is never used.
```
static ErrorOr<std::unique_ptr<MemoryBuffer>>
getFile(const Twine &Filename, bool IsText = false,
bool RequiresNullTerminator = true, bool IsVolatile = false);
static ErrorOr<std::unique_ptr<MemoryBuffer>>
getFileOrSTDIN(const Twine &Filename, bool IsText = false,
bool RequiresNullTerminator = true);
static ErrorOr<std::unique_ptr<MB>>
getFileAux(const Twine &Filename, uint64_t MapSize, uint64_t Offset,
bool IsText, bool RequiresNullTerminator, bool IsVolatile);
static ErrorOr<std::unique_ptr<WritableMemoryBuffer>>
getFile(const Twine &Filename, bool IsVolatile = false);
```
Reviewed By: jhenderson
Differential Revision: https://reviews.llvm.org/D99182
2021-03-25 09:47:25 -04:00
|
|
|
MemoryBuffer::getFileOrSTDIN(File, /*IsText=*/false,
|
2021-01-28 13:28:55 +03:00
|
|
|
/*RequiresNullTerminator=*/false);
|
|
|
|
if (std::error_code EC = FileOrErr.getError())
|
|
|
|
return reportError(errorCodeToError(EC), File);
|
|
|
|
|
|
|
|
std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
|
|
|
|
file_magic Type = identify_magic(Buffer->getBuffer());
|
|
|
|
if (Type == file_magic::bitcode) {
|
|
|
|
reportWarning(createStringError(errc::invalid_argument,
|
|
|
|
"bitcode files are not supported"),
|
|
|
|
File);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Expected<std::unique_ptr<Binary>> BinaryOrErr = createBinary(
|
|
|
|
Buffer->getMemBufferRef(), /*Context=*/nullptr, /*InitContent=*/false);
|
2016-04-06 22:14:09 +00:00
|
|
|
if (!BinaryOrErr)
|
2019-08-13 12:07:41 +00:00
|
|
|
reportError(BinaryOrErr.takeError(), File);
|
2012-03-01 01:36:50 +00:00
|
|
|
|
2021-01-28 13:28:55 +03:00
|
|
|
std::unique_ptr<Binary> Bin = std::move(*BinaryOrErr);
|
|
|
|
if (Archive *Arc = dyn_cast<Archive>(Bin.get()))
|
2018-01-10 00:14:19 +00:00
|
|
|
dumpArchive(Arc, Writer);
|
2015-03-24 20:26:55 +00:00
|
|
|
else if (MachOUniversalBinary *UBinary =
|
2021-01-28 13:28:55 +03:00
|
|
|
dyn_cast<MachOUniversalBinary>(Bin.get()))
|
2018-01-10 00:14:19 +00:00
|
|
|
dumpMachOUniversalBinary(UBinary, Writer);
|
2021-01-28 13:28:55 +03:00
|
|
|
else if (ObjectFile *Obj = dyn_cast<ObjectFile>(Bin.get()))
|
2020-08-27 18:20:13 +03:00
|
|
|
dumpObject(*Obj, Writer);
|
2021-01-28 13:28:55 +03:00
|
|
|
else if (COFFImportFile *Import = dyn_cast<COFFImportFile>(Bin.get()))
|
2018-01-10 00:14:19 +00:00
|
|
|
dumpCOFFImportFile(Import, Writer);
|
2021-01-28 13:28:55 +03:00
|
|
|
else if (WindowsResource *WinRes = dyn_cast<WindowsResource>(Bin.get()))
|
2019-06-12 20:16:22 +00:00
|
|
|
dumpWindowsResourceFile(WinRes, Writer);
|
2013-04-03 18:31:38 +00:00
|
|
|
else
|
2020-08-28 12:18:19 +03:00
|
|
|
llvm_unreachable("unrecognized file type");
|
2019-02-07 15:24:18 +00:00
|
|
|
|
2021-01-28 13:28:55 +03:00
|
|
|
CVTypes.Binaries.push_back(
|
|
|
|
OwningBinary<Binary>(std::move(Bin), std::move(Buffer)));
|
2013-04-03 18:31:38 +00:00
|
|
|
}
|
2012-12-31 16:53:01 +00:00
|
|
|
|
2021-12-10 23:27:06 +00:00
|
|
|
std::unique_ptr<ScopedPrinter> createWriter() {
|
|
|
|
if (opts::Output == opts::JSON)
|
|
|
|
return std::make_unique<JSONScopedPrinter>(
|
|
|
|
fouts(), opts::PrettyPrint ? 2 : 0, std::make_unique<ListScope>());
|
|
|
|
return std::make_unique<ScopedPrinter>(fouts());
|
|
|
|
}
|
|
|
|
|
2021-07-12 10:14:42 -07:00
|
|
|
int main(int argc, char *argv[]) {
|
2018-04-13 18:26:06 +00:00
|
|
|
InitLLVM X(argc, argv);
|
2021-07-12 10:14:42 -07:00
|
|
|
BumpPtrAllocator A;
|
|
|
|
StringSaver Saver(A);
|
|
|
|
ReadobjOptTable Tbl;
|
2019-08-20 12:49:15 +00:00
|
|
|
ToolName = argv[0];
|
2021-07-12 10:14:42 -07:00
|
|
|
opt::InputArgList Args =
|
|
|
|
Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
|
|
|
|
error(Msg);
|
|
|
|
exit(1);
|
|
|
|
});
|
|
|
|
if (Args.hasArg(OPT_help)) {
|
|
|
|
Tbl.printHelp(
|
|
|
|
outs(),
|
|
|
|
(Twine(ToolName) + " [options] <input object files>").str().c_str(),
|
|
|
|
"LLVM Object Reader");
|
|
|
|
// TODO Replace this with OptTable API once it adds extrahelp support.
|
|
|
|
outs() << "\nPass @FILE as argument to read options from FILE.\n";
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (Args.hasArg(OPT_version)) {
|
|
|
|
cl::PrintVersionMessage();
|
|
|
|
return 0;
|
[llvm-readelf] Make llvm-readelf more compatible with GNU readelf.
Summary:
This change adds a bunch of options that GNU readelf supports. There is one breaking change when invoked as `llvm-readobj`, and three breaking changes when invoked as `llvm-readelf`:
- Add --all (implies --file-header, --program-headers, etc.)
- [Breaking] -a is --all instead of --arm-attributes
- Add --file-header as an alias for --file-headers
- Replace --sections with --sections-headers, keeping --sections as an alias for it
- Add --relocs as an alias for --relocations
- Add --dynamic as an alias for --dynamic-table
- Add --segments as an alias for --program-headers
- Add --section-groups as an alias for --elf-section-groups
- Add --dyn-syms as an alias for --dyn-symbols
- Add --syms as an alias for --symbols
- Add --histogram as an alias for --elf-hash-histogram
- [Breaking] When invoked as `llvm-readelf`, -s is --symbols instead of --sections
- [Breaking] When invoked as `llvm-readelf`, -t is no longer an alias for --symbols
Reviewers: MaskRay, phosek, mcgrathr, jhenderson
Reviewed By: MaskRay, jhenderson
Subscribers: sbc100, aheejin, edd, jhenderson, silvas, echristo, compnerd, kristina, javed.absar, kristof.beyls, llvm-commits, Bigcheese
Differential Revision: https://reviews.llvm.org/D54124
llvm-svn: 346685
2018-11-12 18:02:38 +00:00
|
|
|
}
|
2017-07-19 02:09:37 +00:00
|
|
|
|
2021-07-12 10:14:42 -07:00
|
|
|
if (sys::path::stem(argv[0]).contains("readelf"))
|
|
|
|
opts::Output = opts::GNU;
|
|
|
|
parseOptions(Args);
|
2013-02-20 02:37:12 +00:00
|
|
|
|
2020-07-20 08:47:11 +01:00
|
|
|
// Default to print error if no filename is specified.
|
|
|
|
if (opts::InputFilenames.empty()) {
|
|
|
|
error("no input files specified");
|
|
|
|
}
|
|
|
|
|
[llvm-readelf] Make llvm-readelf more compatible with GNU readelf.
Summary:
This change adds a bunch of options that GNU readelf supports. There is one breaking change when invoked as `llvm-readobj`, and three breaking changes when invoked as `llvm-readelf`:
- Add --all (implies --file-header, --program-headers, etc.)
- [Breaking] -a is --all instead of --arm-attributes
- Add --file-header as an alias for --file-headers
- Replace --sections with --sections-headers, keeping --sections as an alias for it
- Add --relocs as an alias for --relocations
- Add --dynamic as an alias for --dynamic-table
- Add --segments as an alias for --program-headers
- Add --section-groups as an alias for --elf-section-groups
- Add --dyn-syms as an alias for --dyn-symbols
- Add --syms as an alias for --symbols
- Add --histogram as an alias for --elf-hash-histogram
- [Breaking] When invoked as `llvm-readelf`, -s is --symbols instead of --sections
- [Breaking] When invoked as `llvm-readelf`, -t is no longer an alias for --symbols
Reviewers: MaskRay, phosek, mcgrathr, jhenderson
Reviewed By: MaskRay, jhenderson
Subscribers: sbc100, aheejin, edd, jhenderson, silvas, echristo, compnerd, kristina, javed.absar, kristof.beyls, llvm-commits, Bigcheese
Differential Revision: https://reviews.llvm.org/D54124
llvm-svn: 346685
2018-11-12 18:02:38 +00:00
|
|
|
if (opts::All) {
|
|
|
|
opts::FileHeaders = true;
|
2021-10-26 10:40:25 -04:00
|
|
|
opts::XCOFFAuxiliaryHeader = true;
|
[llvm-readelf] Make llvm-readelf more compatible with GNU readelf.
Summary:
This change adds a bunch of options that GNU readelf supports. There is one breaking change when invoked as `llvm-readobj`, and three breaking changes when invoked as `llvm-readelf`:
- Add --all (implies --file-header, --program-headers, etc.)
- [Breaking] -a is --all instead of --arm-attributes
- Add --file-header as an alias for --file-headers
- Replace --sections with --sections-headers, keeping --sections as an alias for it
- Add --relocs as an alias for --relocations
- Add --dynamic as an alias for --dynamic-table
- Add --segments as an alias for --program-headers
- Add --section-groups as an alias for --elf-section-groups
- Add --dyn-syms as an alias for --dyn-symbols
- Add --syms as an alias for --symbols
- Add --histogram as an alias for --elf-hash-histogram
- [Breaking] When invoked as `llvm-readelf`, -s is --symbols instead of --sections
- [Breaking] When invoked as `llvm-readelf`, -t is no longer an alias for --symbols
Reviewers: MaskRay, phosek, mcgrathr, jhenderson
Reviewed By: MaskRay, jhenderson
Subscribers: sbc100, aheejin, edd, jhenderson, silvas, echristo, compnerd, kristina, javed.absar, kristof.beyls, llvm-commits, Bigcheese
Differential Revision: https://reviews.llvm.org/D54124
llvm-svn: 346685
2018-11-12 18:02:38 +00:00
|
|
|
opts::ProgramHeaders = true;
|
|
|
|
opts::SectionHeaders = true;
|
|
|
|
opts::Symbols = true;
|
|
|
|
opts::Relocations = true;
|
|
|
|
opts::DynamicTable = true;
|
|
|
|
opts::Notes = true;
|
|
|
|
opts::VersionInfo = true;
|
|
|
|
opts::UnwindInfo = true;
|
|
|
|
opts::SectionGroups = true;
|
|
|
|
opts::HashHistogram = true;
|
2019-10-07 10:29:38 +00:00
|
|
|
if (opts::Output == opts::LLVM) {
|
|
|
|
opts::Addrsig = true;
|
2019-09-23 10:33:19 +00:00
|
|
|
opts::PrintStackSizes = true;
|
2019-10-07 10:29:38 +00:00
|
|
|
}
|
[llvm-readelf] Make llvm-readelf more compatible with GNU readelf.
Summary:
This change adds a bunch of options that GNU readelf supports. There is one breaking change when invoked as `llvm-readobj`, and three breaking changes when invoked as `llvm-readelf`:
- Add --all (implies --file-header, --program-headers, etc.)
- [Breaking] -a is --all instead of --arm-attributes
- Add --file-header as an alias for --file-headers
- Replace --sections with --sections-headers, keeping --sections as an alias for it
- Add --relocs as an alias for --relocations
- Add --dynamic as an alias for --dynamic-table
- Add --segments as an alias for --program-headers
- Add --section-groups as an alias for --elf-section-groups
- Add --dyn-syms as an alias for --dyn-symbols
- Add --syms as an alias for --symbols
- Add --histogram as an alias for --elf-hash-histogram
- [Breaking] When invoked as `llvm-readelf`, -s is --symbols instead of --sections
- [Breaking] When invoked as `llvm-readelf`, -t is no longer an alias for --symbols
Reviewers: MaskRay, phosek, mcgrathr, jhenderson
Reviewed By: MaskRay, jhenderson
Subscribers: sbc100, aheejin, edd, jhenderson, silvas, echristo, compnerd, kristina, javed.absar, kristof.beyls, llvm-commits, Bigcheese
Differential Revision: https://reviews.llvm.org/D54124
llvm-svn: 346685
2018-11-12 18:02:38 +00:00
|
|
|
}
|
|
|
|
|
2018-12-11 16:15:03 +00:00
|
|
|
if (opts::Headers) {
|
|
|
|
opts::FileHeaders = true;
|
2021-10-26 10:40:25 -04:00
|
|
|
opts::XCOFFAuxiliaryHeader = true;
|
2018-12-11 16:15:03 +00:00
|
|
|
opts::ProgramHeaders = true;
|
|
|
|
opts::SectionHeaders = true;
|
|
|
|
}
|
|
|
|
|
2021-12-10 23:27:06 +00:00
|
|
|
std::unique_ptr<ScopedPrinter> Writer = createWriter();
|
|
|
|
|
2019-06-12 20:16:22 +00:00
|
|
|
for (const std::string &I : opts::InputFilenames)
|
2021-12-10 23:27:06 +00:00
|
|
|
dumpInput(I, *Writer.get());
|
2017-11-30 18:33:34 +00:00
|
|
|
|
|
|
|
if (opts::CodeViewMergedTypes) {
|
2019-02-07 15:24:18 +00:00
|
|
|
if (opts::CodeViewEnableGHash)
|
2021-12-10 23:27:06 +00:00
|
|
|
dumpCodeViewMergedTypes(*Writer.get(), CVTypes.GlobalIDTable.records(),
|
2019-02-07 15:24:18 +00:00
|
|
|
CVTypes.GlobalTypeTable.records());
|
|
|
|
else
|
2021-12-10 23:27:06 +00:00
|
|
|
dumpCodeViewMergedTypes(*Writer.get(), CVTypes.IDTable.records(),
|
2019-02-07 15:24:18 +00:00
|
|
|
CVTypes.TypeTable.records());
|
2016-05-14 00:02:53 +00:00
|
|
|
}
|
|
|
|
|
2015-07-20 03:23:55 +00:00
|
|
|
return 0;
|
2012-03-01 01:36:50 +00:00
|
|
|
}
|