aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:11 +0000
commite3b557809604d036af6e00c60f012c2025b59a5e (patch)
tree8a11ba2269a3b669601e2fd41145b174008f4da8 /llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp
parent08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff)
Diffstat (limited to 'llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp')
-rw-r--r--llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp194
1 files changed, 194 insertions, 0 deletions
diff --git a/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp b/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp
new file mode 100644
index 000000000000..35dc30fd601f
--- /dev/null
+++ b/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp
@@ -0,0 +1,194 @@
+//===-- LVReaderHandler.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
+//
+//===----------------------------------------------------------------------===//
+//
+// This class implements the Reader Handler.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/LogicalView/LVReaderHandler.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVCompare.h"
+#include "llvm/DebugInfo/LogicalView/Readers/LVELFReader.h"
+
+using namespace llvm;
+using namespace llvm::object;
+using namespace llvm::pdb;
+using namespace llvm::logicalview;
+
+#define DEBUG_TYPE "ReaderHandler"
+
+Error LVReaderHandler::process() {
+ if (Error Err = createReaders())
+ return Err;
+ if (Error Err = printReaders())
+ return Err;
+ if (Error Err = compareReaders())
+ return Err;
+
+ 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 *>();
+ if (Obj.isELF() || Obj.isMachO())
+ return new LVELFReader(Filename, FileFormatName, Obj, W);
+ }
+ return nullptr;
+ };
+
+ LVReader *Reader = CreateOneReader();
+ if (!Reader)
+ return createStringError(errc::invalid_argument,
+ "unable to create reader for: '%s'",
+ Filename.str().c_str());
+
+ Readers.push_back(Reader);
+ return Reader->doLoad();
+}
+
+Error LVReaderHandler::handleArchive(LVReaders &Readers, StringRef Filename,
+ Archive &Arch) {
+ Error Err = Error::success();
+ for (const Archive::Child &Child : Arch.children(Err)) {
+ Expected<MemoryBufferRef> BuffOrErr = Child.getMemoryBufferRef();
+ if (Error Err = BuffOrErr.takeError())
+ return createStringError(errorToErrorCode(std::move(Err)), "%s",
+ Filename.str().c_str());
+ Expected<StringRef> NameOrErr = Child.getName();
+ if (Error Err = NameOrErr.takeError())
+ return createStringError(errorToErrorCode(std::move(Err)), "%s",
+ Filename.str().c_str());
+ std::string Name = (Filename + "(" + NameOrErr.get() + ")").str();
+ if (Error Err = handleBuffer(Readers, Name, BuffOrErr.get()))
+ return createStringError(errorToErrorCode(std::move(Err)), "%s",
+ Filename.str().c_str());
+ }
+
+ return Error::success();
+}
+
+Error LVReaderHandler::handleBuffer(LVReaders &Readers, StringRef Filename,
+ MemoryBufferRef Buffer, StringRef ExePath) {
+ Expected<std::unique_ptr<Binary>> BinOrErr = createBinary(Buffer);
+ if (errorToErrorCode(BinOrErr.takeError())) {
+ return createStringError(errc::not_supported,
+ "Binary object format in '%s' is not supported.",
+ Filename.str().c_str());
+ }
+ return handleObject(Readers, Filename, *BinOrErr.get());
+}
+
+Error LVReaderHandler::handleFile(LVReaders &Readers, StringRef Filename,
+ StringRef ExePath) {
+ // Convert any Windows backslashes into forward slashes to get the path.
+ std::string ConvertedPath =
+ sys::path::convert_to_slash(Filename, sys::path::Style::windows);
+ ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr =
+ MemoryBuffer::getFileOrSTDIN(ConvertedPath);
+ if (BuffOrErr.getError()) {
+ return createStringError(errc::bad_file_descriptor,
+ "File '%s' does not exist.",
+ ConvertedPath.c_str());
+ }
+ std::unique_ptr<MemoryBuffer> Buffer = std::move(BuffOrErr.get());
+ return handleBuffer(Readers, ConvertedPath, *Buffer, ExePath);
+}
+
+Error LVReaderHandler::handleMach(LVReaders &Readers, StringRef Filename,
+ MachOUniversalBinary &Mach) {
+ for (const MachOUniversalBinary::ObjectForArch &ObjForArch : Mach.objects()) {
+ std::string ObjName = (Twine(Filename) + Twine("(") +
+ Twine(ObjForArch.getArchFlagName()) + Twine(")"))
+ .str();
+ if (Expected<std::unique_ptr<MachOObjectFile>> MachOOrErr =
+ ObjForArch.getAsObjectFile()) {
+ MachOObjectFile &Obj = **MachOOrErr;
+ PdbOrObj Input = &Obj;
+ if (Error Err =
+ createReader(Filename, Readers, Input, Obj.getFileFormatName()))
+ return Err;
+ continue;
+ } else
+ consumeError(MachOOrErr.takeError());
+ if (Expected<std::unique_ptr<Archive>> ArchiveOrErr =
+ ObjForArch.getAsArchive()) {
+ if (Error Err = handleArchive(Readers, ObjName, *ArchiveOrErr.get()))
+ return Err;
+ continue;
+ } else
+ consumeError(ArchiveOrErr.takeError());
+ }
+ return Error::success();
+}
+
+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());
+
+ if (MachOUniversalBinary *Fat = dyn_cast<MachOUniversalBinary>(&Binary))
+ return handleMach(Readers, Filename, *Fat);
+
+ if (Archive *Arch = dyn_cast<Archive>(&Binary))
+ return handleArchive(Readers, Filename, *Arch);
+
+ return createStringError(errc::not_supported,
+ "Binary object format in '%s' is not supported.",
+ Filename.str().c_str());
+}
+
+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());
+ }
+
+ return Error::success();
+}
+
+Error LVReaderHandler::printReaders() {
+ LLVM_DEBUG(dbgs() << "printReaders\n");
+ if (options().getPrintExecute())
+ for (LVReader *Reader : TheReaders)
+ if (Error Err = Reader->doPrint())
+ return Err;
+
+ return Error::success();
+}
+
+Error LVReaderHandler::compareReaders() {
+ LLVM_DEBUG(dbgs() << "compareReaders\n");
+ size_t ReadersCount = TheReaders.size();
+ if (options().getCompareExecute() && ReadersCount >= 2) {
+ // If we have more than 2 readers, compare them by pairs.
+ 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]))
+ return Err;
+ Index += 2;
+ }
+ }
+
+ return Error::success();
+}
+
+void LVReaderHandler::print(raw_ostream &OS) const { OS << "ReaderHandler\n"; }