28#define DEBUG_TYPE "ReaderHandler"
33 if (
Error Err = createReaders())
35 if (
Error Err = printReaders())
37 if (
Error Err = compareReaders())
47 auto CreateOneReader = [&]() -> std::unique_ptr<LVReader> {
48 if (
auto ObjPtrPtr = std::get_if<ObjectFile *>(&
Input)) {
52 return std::make_unique<LVCodeViewReader>(
Filename, FileFormatName,
55 if (Obj.isELF() || Obj.isMachO() || Obj.isWasm())
56 return std::make_unique<LVDWARFReader>(
Filename, FileFormatName, Obj,
59 if (
auto PdbPtrPtr = std::get_if<PDBFile *>(&
Input)) {
61 return std::make_unique<LVCodeViewReader>(
Filename, FileFormatName,
Pdb,
64 if (
auto Ir = std::get_if<IRObjectFile *>(&Input))
65 return std::make_unique<LVIRReader>(
Filename, FileFormatName, *Ir, W);
66 if (
auto MemBuf = std::get_if<MemoryBufferRef *>(&Input)) {
68 constexpr StringRef IRFileExt =
".ll";
76 std::unique_ptr<LVReader> ReaderObj = CreateOneReader();
79 "unable to create reader for: '%s'",
82 LVReader *Reader = ReaderObj.get();
83 Readers.emplace_back(std::move(ReaderObj));
90 for (
const Archive::Child &Child : Arch.
children(Err)) {
91 Expected<MemoryBufferRef> BuffOrErr = Child.getMemoryBufferRef();
95 Expected<StringRef> NameOrErr = Child.getName();
100 if (
Error Err = handleBuffer(Readers,
Name, BuffOrErr.
get()))
117 std::unique_ptr<IPDBSession> Session;
131 if (ConvertedPath ==
Path)
132 return std::string(ExePath);
147 return std::string(ObjPath);
154 MemoryBufferRef Buffer, StringRef ExePath) {
159 if (!ExePath.
empty())
166 std::vector<StringRef> ExecutableExtensions = {
"exe",
"dll"};
167 for (StringRef Extension : ExecutableExtensions) {
169 if (ExecutableImage.empty())
179 std::vector<StringRef> ObjectExtensions = {
"o",
"obj",
"lib"};
180 for (StringRef Extension : ObjectExtensions) {
182 if (ObjectImage.empty())
184 if (
Error Err = handleFile(Readers, ObjectImage)) {
200 "Binary object format in '%s' does not have debug info.",
204 return handleFile(Readers, PdbPath.
get(),
Filename);
211 return handleObject(Readers,
Filename, Buffer);
213 return handleObject(Readers,
Filename, *BinOrErr.
get());
219 std::string ConvertedPath =
221 ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr =
225 "File '%s' does not exist.",
226 ConvertedPath.c_str());
228 std::unique_ptr<MemoryBuffer> Buffer = std::move(BuffOrErr.
get());
229 return handleBuffer(Readers, ConvertedPath, *Buffer, ExePath);
233 MachOUniversalBinary &Mach) {
234 for (
const MachOUniversalBinary::ObjectForArch &ObjForArch : Mach.
objects()) {
235 std::string ObjName = (Twine(
Filename) + Twine(
"(") +
236 Twine(ObjForArch.getArchFlagName()) + Twine(
")"))
238 if (Expected<std::unique_ptr<MachOObjectFile>> MachOOrErr =
239 ObjForArch.getAsObjectFile()) {
240 MachOObjectFile &
Obj = **MachOOrErr;
243 createReader(
Filename, Readers, Input,
Obj.getFileFormatName()))
248 if (Expected<std::unique_ptr<Archive>> ArchiveOrErr =
249 ObjForArch.getAsArchive()) {
250 if (
Error Err = handleArchive(Readers, ObjName, *ArchiveOrErr.get()))
263 return createReader(
Filename, Readers, Input, ObjFile->getFileFormatName());
267 return handleMach(Readers,
Filename, *Fat);
270 return handleArchive(Readers,
Filename, *Arch);
274 return createReader(
Filename, Readers, Input,
"Bitcode IR");
278 "Binary object format in '%s' is not supported.",
283 StringRef Buffer, StringRef ExePath) {
284 std::unique_ptr<IPDBSession> Session;
289 std::unique_ptr<NativeSession> PdbSession;
290 PdbSession.reset(
static_cast<NativeSession *
>(Session.release()));
292 StringRef FileFormatName;
295 FileFormatName = Buffer.
substr(0, Pos - 1);
296 return createReader(
Filename, Readers, Input, FileFormatName, ExePath);
300 MemoryBufferRef Buffer) {
305Error LVReaderHandler::createReaders() {
307 for (std::string &Object : Objects) {
309 if (
Error Err = createReader(Object, Readers))
311 TheReaders.insert(TheReaders.end(),
312 std::make_move_iterator(Readers.begin()),
313 std::make_move_iterator(Readers.end()));
319Error LVReaderHandler::printReaders() {
321 if (
options().getPrintExecute())
322 for (
const std::unique_ptr<LVReader> &Reader : TheReaders)
329Error LVReaderHandler::compareReaders() {
331 size_t ReadersCount = TheReaders.size();
332 if (
options().getCompareExecute() && ReadersCount >= 2) {
334 size_t ViewPairs = ReadersCount / 2;
336 for (
size_t Pair = 0, Index = 0; Pair < ViewPairs; ++Pair) {
337 if (
Error Err =
Compare.execute(TheReaders[Index].get(),
338 TheReaders[Index + 1].get()))
static constexpr StringRef IRFileFormatName
static std::string searchForObj(const StringRef Path, const StringRef Extension)
static std::string searchForExe(const StringRef Path, const StringRef Extension)
static constexpr StringLiteral Filename
Represents either an error or a value T.
std::error_code getError() const
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
reference get()
Returns a reference to the stored T value.
StringRef getBuffer() const
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Represent a constant reference to a string, i.e.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
constexpr bool empty() const
Check if the string is empty.
size_t find_first_of(char C, size_t From=0) const
Find the first character in the string that is C, or npos if not found.
LLVM_ABI void print(raw_ostream &OS) const
iterator_range< child_iterator > children(Error &Err, bool SkipInternal=true) const
iterator_range< object_iterator > objects() const
static Expected< std::string > searchForPdb(const PdbSearchOptions &Opts)
This class implements an extremely fast bulk output stream that can only output to a stream.
std::vector< std::unique_ptr< LVReader > > LVReaders
std::variant< StringRef *, MemoryBufferRef *, object::ObjectFile *, object::IRObjectFile *, pdb::PDBFile * > InputHandle
LLVM_ABI Expected< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr, bool InitContent=true)
Create a Binary from Source, autodetecting the file type.
LLVM_ABI Error loadDataForEXE(PDB_ReaderType Type, StringRef Path, std::unique_ptr< IPDBSession > &Session)
LLVM_ABI Error loadDataForPDB(PDB_ReaderType Type, StringRef Path, std::unique_ptr< IPDBSession > &Session)
LLVM_ABI bool exists(const basic_file_status &status)
Does file exist?
LLVM_ABI void replace_extension(SmallVectorImpl< char > &path, const Twine &extension, Style style=Style::native)
Replace the file extension of path with extension.
LLVM_ABI std::string convert_to_slash(StringRef path, Style style=Style::native)
Replaces backslashes with slashes if Windows.
LLVM_ABI StringRef extension(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get extension.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI file_magic identify_magic(StringRef magic)
Identify the type of a binary file based on how magical it is.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::error_code errorToErrorCode(Error Err)
Helper for converting an ECError to a std::error_code.
void consumeError(Error Err)
Consume a Error without doing anything.
@ pdb
Windows PDB debug info file.
@ pecoff_executable
PECOFF executable file.