diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:04 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:11 +0000 |
commit | e3b557809604d036af6e00c60f012c2025b59a5e (patch) | |
tree | 8a11ba2269a3b669601e2fd41145b174008f4da8 /llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp | |
parent | 08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff) |
Diffstat (limited to 'llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp')
-rw-r--r-- | llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp | 194 |
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"; } |