aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-09-02 21:17:18 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-12-08 17:34:50 +0000
commit06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e (patch)
tree62f873df87c7c675557a179e0c4c83fe9f3087bc /contrib/llvm-project/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp
parentcf037972ea8863e2bab7461d77345367d2c1e054 (diff)
parent7fa27ce4a07f19b07799a767fc29416f3b625afb (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp158
1 files changed, 141 insertions, 17 deletions
diff --git a/contrib/llvm-project/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp b/contrib/llvm-project/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp
index 35dc30fd601f..5f82f816dc19 100644
--- a/contrib/llvm-project/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp
+++ b/contrib/llvm-project/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp
@@ -11,8 +11,13 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/LogicalView/LVReaderHandler.h"
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/LogicalView/Core/LVCompare.h"
+#include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h"
#include "llvm/DebugInfo/LogicalView/Readers/LVELFReader.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/PDB.h"
+#include "llvm/Object/COFF.h"
using namespace llvm;
using namespace llvm::object;
@@ -32,31 +37,36 @@ Error LVReaderHandler::process() {
return Error::success();
}
-void LVReaderHandler::destroyReaders() {
- LLVM_DEBUG(dbgs() << "destroyReaders\n");
- for (const LVReader *Reader : TheReaders)
- delete Reader;
-}
-
Error LVReaderHandler::createReader(StringRef Filename, LVReaders &Readers,
PdbOrObj &Input, StringRef FileFormatName,
StringRef ExePath) {
- auto CreateOneReader = [&]() -> LVReader * {
- if (Input.is<ObjectFile *>()) {
- ObjectFile &Obj = *Input.get<ObjectFile *>();
+ auto CreateOneReader = [&]() -> std::unique_ptr<LVReader> {
+ if (isa<ObjectFile *>(Input)) {
+ ObjectFile &Obj = *cast<ObjectFile *>(Input);
+ if (Obj.isCOFF()) {
+ COFFObjectFile *COFF = cast<COFFObjectFile>(&Obj);
+ return std::make_unique<LVCodeViewReader>(Filename, FileFormatName,
+ *COFF, W, ExePath);
+ }
if (Obj.isELF() || Obj.isMachO())
- return new LVELFReader(Filename, FileFormatName, Obj, W);
+ return std::make_unique<LVELFReader>(Filename, FileFormatName, Obj, W);
+ }
+ if (isa<PDBFile *>(Input)) {
+ PDBFile &Pdb = *cast<PDBFile *>(Input);
+ return std::make_unique<LVCodeViewReader>(Filename, FileFormatName, Pdb,
+ W, ExePath);
}
return nullptr;
};
- LVReader *Reader = CreateOneReader();
- if (!Reader)
+ std::unique_ptr<LVReader> ReaderObj = CreateOneReader();
+ if (!ReaderObj)
return createStringError(errc::invalid_argument,
"unable to create reader for: '%s'",
Filename.str().c_str());
- Readers.push_back(Reader);
+ LVReader *Reader = ReaderObj.get();
+ Readers.emplace_back(std::move(ReaderObj));
return Reader->doLoad();
}
@@ -81,8 +91,102 @@ Error LVReaderHandler::handleArchive(LVReaders &Readers, StringRef Filename,
return Error::success();
}
+// Search for a matching executable image for the given PDB path.
+static std::string searchForExe(const StringRef Path,
+ const StringRef Extension) {
+ SmallString<128> ExePath(Path);
+ llvm::sys::path::replace_extension(ExePath, Extension);
+
+ std::unique_ptr<IPDBSession> Session;
+ if (Error Err = loadDataForEXE(PDB_ReaderType::Native, ExePath, Session)) {
+ consumeError(std::move(Err));
+ return {};
+ }
+ // We have a candidate for the executable image.
+ Expected<std::string> PdbPathOrErr = NativeSession::searchForPdb({ExePath});
+ if (!PdbPathOrErr) {
+ consumeError(PdbPathOrErr.takeError());
+ return {};
+ }
+ // Convert any Windows backslashes into forward slashes to get the path.
+ std::string ConvertedPath = sys::path::convert_to_slash(
+ PdbPathOrErr.get(), sys::path::Style::windows);
+ if (ConvertedPath == Path)
+ return std::string(ExePath);
+
+ return {};
+}
+
+// Search for a matching object image for the given PDB path.
+static std::string searchForObj(const StringRef Path,
+ const StringRef Extension) {
+ SmallString<128> ObjPath(Path);
+ llvm::sys::path::replace_extension(ObjPath, Extension);
+ if (llvm::sys::fs::exists(ObjPath)) {
+ ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr =
+ MemoryBuffer::getFileOrSTDIN(ObjPath);
+ if (!BuffOrErr)
+ return {};
+ return std::string(ObjPath);
+ }
+
+ return {};
+}
+
Error LVReaderHandler::handleBuffer(LVReaders &Readers, StringRef Filename,
MemoryBufferRef Buffer, StringRef ExePath) {
+ // As PDB does not support the Binary interface, at this point we can check
+ // if the buffer corresponds to a PDB or PE file.
+ file_magic FileMagic = identify_magic(Buffer.getBuffer());
+ if (FileMagic == file_magic::pdb) {
+ if (!ExePath.empty())
+ return handleObject(Readers, Filename, Buffer.getBuffer(), ExePath);
+
+ // Search in the directory derived from the given 'Filename' for a
+ // matching object file (.o, .obj, .lib) or a matching executable file
+ // (.exe/.dll) and try to create the reader based on the matched file.
+ // If no matching file is found then we load the original PDB file.
+ std::vector<StringRef> ExecutableExtensions = {"exe", "dll"};
+ for (StringRef Extension : ExecutableExtensions) {
+ std::string ExecutableImage = searchForExe(Filename, Extension);
+ if (ExecutableImage.empty())
+ continue;
+ if (Error Err = handleObject(Readers, Filename, Buffer.getBuffer(),
+ ExecutableImage)) {
+ consumeError(std::move(Err));
+ continue;
+ }
+ return Error::success();
+ }
+
+ std::vector<StringRef> ObjectExtensions = {"o", "obj", "lib"};
+ for (StringRef Extension : ObjectExtensions) {
+ std::string ObjectImage = searchForObj(Filename, Extension);
+ if (ObjectImage.empty())
+ continue;
+ if (Error Err = handleFile(Readers, ObjectImage)) {
+ consumeError(std::move(Err));
+ continue;
+ }
+ return Error::success();
+ }
+
+ // No matching executable/object image was found. Load the given PDB.
+ return handleObject(Readers, Filename, Buffer.getBuffer(), ExePath);
+ }
+ if (FileMagic == file_magic::pecoff_executable) {
+ // If we have a valid executable, try to find a matching PDB file.
+ Expected<std::string> PdbPath = NativeSession::searchForPdb({Filename});
+ if (errorToErrorCode(PdbPath.takeError())) {
+ return createStringError(
+ errc::not_supported,
+ "Binary object format in '%s' does not have debug info.",
+ Filename.str().c_str());
+ }
+ // Process the matching PDB file and pass the executable filename.
+ return handleFile(Readers, PdbPath.get(), Filename);
+ }
+
Expected<std::unique_ptr<Binary>> BinOrErr = createBinary(Buffer);
if (errorToErrorCode(BinOrErr.takeError())) {
return createStringError(errc::not_supported,
@@ -139,7 +243,7 @@ Error LVReaderHandler::handleObject(LVReaders &Readers, StringRef Filename,
Binary &Binary) {
if (PdbOrObj Input = dyn_cast<ObjectFile>(&Binary))
return createReader(Filename, Readers, Input,
- Input.get<ObjectFile *>()->getFileFormatName());
+ cast<ObjectFile *>(Input)->getFileFormatName());
if (MachOUniversalBinary *Fat = dyn_cast<MachOUniversalBinary>(&Binary))
return handleMach(Readers, Filename, *Fat);
@@ -152,13 +256,32 @@ Error LVReaderHandler::handleObject(LVReaders &Readers, StringRef Filename,
Filename.str().c_str());
}
+Error LVReaderHandler::handleObject(LVReaders &Readers, StringRef Filename,
+ StringRef Buffer, StringRef ExePath) {
+ std::unique_ptr<IPDBSession> Session;
+ if (Error Err = loadDataForPDB(PDB_ReaderType::Native, Filename, Session))
+ return createStringError(errorToErrorCode(std::move(Err)), "%s",
+ Filename.str().c_str());
+
+ std::unique_ptr<NativeSession> PdbSession;
+ PdbSession.reset(static_cast<NativeSession *>(Session.release()));
+ PdbOrObj Input = &PdbSession->getPDBFile();
+ StringRef FileFormatName;
+ size_t Pos = Buffer.find_first_of("\r\n");
+ if (Pos)
+ FileFormatName = Buffer.substr(0, Pos - 1);
+ return createReader(Filename, Readers, Input, FileFormatName, ExePath);
+}
+
Error LVReaderHandler::createReaders() {
LLVM_DEBUG(dbgs() << "createReaders\n");
for (std::string &Object : Objects) {
LVReaders Readers;
if (Error Err = createReader(Object, Readers))
return Err;
- TheReaders.insert(TheReaders.end(), Readers.begin(), Readers.end());
+ TheReaders.insert(TheReaders.end(),
+ std::make_move_iterator(Readers.begin()),
+ std::make_move_iterator(Readers.end()));
}
return Error::success();
@@ -167,7 +290,7 @@ Error LVReaderHandler::createReaders() {
Error LVReaderHandler::printReaders() {
LLVM_DEBUG(dbgs() << "printReaders\n");
if (options().getPrintExecute())
- for (LVReader *Reader : TheReaders)
+ for (const std::unique_ptr<LVReader> &Reader : TheReaders)
if (Error Err = Reader->doPrint())
return Err;
@@ -182,7 +305,8 @@ Error LVReaderHandler::compareReaders() {
size_t ViewPairs = ReadersCount / 2;
LVCompare Compare(OS);
for (size_t Pair = 0, Index = 0; Pair < ViewPairs; ++Pair) {
- if (Error Err = Compare.execute(TheReaders[Index], TheReaders[Index + 1]))
+ if (Error Err = Compare.execute(TheReaders[Index].get(),
+ TheReaders[Index + 1].get()))
return Err;
Index += 2;
}