14f06d46fSCarlos Alberto Enciso //===-- LVReaderHandler.cpp -----------------------------------------------===// 24f06d46fSCarlos Alberto Enciso // 34f06d46fSCarlos Alberto Enciso // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 44f06d46fSCarlos Alberto Enciso // See https://llvm.org/LICENSE.txt for license information. 54f06d46fSCarlos Alberto Enciso // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 64f06d46fSCarlos Alberto Enciso // 74f06d46fSCarlos Alberto Enciso //===----------------------------------------------------------------------===// 84f06d46fSCarlos Alberto Enciso // 94f06d46fSCarlos Alberto Enciso // This class implements the Reader Handler. 104f06d46fSCarlos Alberto Enciso // 114f06d46fSCarlos Alberto Enciso //===----------------------------------------------------------------------===// 124f06d46fSCarlos Alberto Enciso 134f06d46fSCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/LVReaderHandler.h" 144f06d46fSCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVCompare.h" 15e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h" 16c1ccf078SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h" 17e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/NativeSession.h" 18e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/PDB.h" 19e7950fceSCarlos Alberto Enciso #include "llvm/Object/COFF.h" 204f06d46fSCarlos Alberto Enciso 214f06d46fSCarlos Alberto Enciso using namespace llvm; 224f06d46fSCarlos Alberto Enciso using namespace llvm::object; 234f06d46fSCarlos Alberto Enciso using namespace llvm::pdb; 244f06d46fSCarlos Alberto Enciso using namespace llvm::logicalview; 254f06d46fSCarlos Alberto Enciso 264f06d46fSCarlos Alberto Enciso #define DEBUG_TYPE "ReaderHandler" 274f06d46fSCarlos Alberto Enciso 284f06d46fSCarlos Alberto Enciso Error LVReaderHandler::process() { 294f06d46fSCarlos Alberto Enciso if (Error Err = createReaders()) 304f06d46fSCarlos Alberto Enciso return Err; 314f06d46fSCarlos Alberto Enciso if (Error Err = printReaders()) 324f06d46fSCarlos Alberto Enciso return Err; 334f06d46fSCarlos Alberto Enciso if (Error Err = compareReaders()) 344f06d46fSCarlos Alberto Enciso return Err; 354f06d46fSCarlos Alberto Enciso 364f06d46fSCarlos Alberto Enciso return Error::success(); 374f06d46fSCarlos Alberto Enciso } 384f06d46fSCarlos Alberto Enciso 394f06d46fSCarlos Alberto Enciso Error LVReaderHandler::createReader(StringRef Filename, LVReaders &Readers, 404f06d46fSCarlos Alberto Enciso PdbOrObj &Input, StringRef FileFormatName, 414f06d46fSCarlos Alberto Enciso StringRef ExePath) { 427fbcc244SCarlos Alberto Enciso auto CreateOneReader = [&]() -> std::unique_ptr<LVReader> { 437021182dSShraiysh Vaishay if (isa<ObjectFile *>(Input)) { 447021182dSShraiysh Vaishay ObjectFile &Obj = *cast<ObjectFile *>(Input); 45e7950fceSCarlos Alberto Enciso if (Obj.isCOFF()) { 46e7950fceSCarlos Alberto Enciso COFFObjectFile *COFF = cast<COFFObjectFile>(&Obj); 47e7950fceSCarlos Alberto Enciso return std::make_unique<LVCodeViewReader>(Filename, FileFormatName, 48e7950fceSCarlos Alberto Enciso *COFF, W, ExePath); 49e7950fceSCarlos Alberto Enciso } 50b19cfb91SCarlos Alberto Enciso if (Obj.isELF() || Obj.isMachO() || Obj.isWasm()) 51c1ccf078SCarlos Alberto Enciso return std::make_unique<LVDWARFReader>(Filename, FileFormatName, Obj, 52c1ccf078SCarlos Alberto Enciso W); 534f06d46fSCarlos Alberto Enciso } 547021182dSShraiysh Vaishay if (isa<PDBFile *>(Input)) { 557021182dSShraiysh Vaishay PDBFile &Pdb = *cast<PDBFile *>(Input); 56e7950fceSCarlos Alberto Enciso return std::make_unique<LVCodeViewReader>(Filename, FileFormatName, Pdb, 57e7950fceSCarlos Alberto Enciso W, ExePath); 58e7950fceSCarlos Alberto Enciso } 594f06d46fSCarlos Alberto Enciso return nullptr; 604f06d46fSCarlos Alberto Enciso }; 614f06d46fSCarlos Alberto Enciso 627fbcc244SCarlos Alberto Enciso std::unique_ptr<LVReader> ReaderObj = CreateOneReader(); 637fbcc244SCarlos Alberto Enciso if (!ReaderObj) 644f06d46fSCarlos Alberto Enciso return createStringError(errc::invalid_argument, 654f06d46fSCarlos Alberto Enciso "unable to create reader for: '%s'", 664f06d46fSCarlos Alberto Enciso Filename.str().c_str()); 674f06d46fSCarlos Alberto Enciso 687fbcc244SCarlos Alberto Enciso LVReader *Reader = ReaderObj.get(); 697fbcc244SCarlos Alberto Enciso Readers.emplace_back(std::move(ReaderObj)); 704f06d46fSCarlos Alberto Enciso return Reader->doLoad(); 714f06d46fSCarlos Alberto Enciso } 724f06d46fSCarlos Alberto Enciso 734f06d46fSCarlos Alberto Enciso Error LVReaderHandler::handleArchive(LVReaders &Readers, StringRef Filename, 744f06d46fSCarlos Alberto Enciso Archive &Arch) { 754f06d46fSCarlos Alberto Enciso Error Err = Error::success(); 764f06d46fSCarlos Alberto Enciso for (const Archive::Child &Child : Arch.children(Err)) { 774f06d46fSCarlos Alberto Enciso Expected<MemoryBufferRef> BuffOrErr = Child.getMemoryBufferRef(); 784f06d46fSCarlos Alberto Enciso if (Error Err = BuffOrErr.takeError()) 794f06d46fSCarlos Alberto Enciso return createStringError(errorToErrorCode(std::move(Err)), "%s", 804f06d46fSCarlos Alberto Enciso Filename.str().c_str()); 814f06d46fSCarlos Alberto Enciso Expected<StringRef> NameOrErr = Child.getName(); 824f06d46fSCarlos Alberto Enciso if (Error Err = NameOrErr.takeError()) 834f06d46fSCarlos Alberto Enciso return createStringError(errorToErrorCode(std::move(Err)), "%s", 844f06d46fSCarlos Alberto Enciso Filename.str().c_str()); 854f06d46fSCarlos Alberto Enciso std::string Name = (Filename + "(" + NameOrErr.get() + ")").str(); 864f06d46fSCarlos Alberto Enciso if (Error Err = handleBuffer(Readers, Name, BuffOrErr.get())) 874f06d46fSCarlos Alberto Enciso return createStringError(errorToErrorCode(std::move(Err)), "%s", 884f06d46fSCarlos Alberto Enciso Filename.str().c_str()); 894f06d46fSCarlos Alberto Enciso } 904f06d46fSCarlos Alberto Enciso 91*37e48e4aSaurelien35 if (Err) 92*37e48e4aSaurelien35 return createStringError(errorToErrorCode(std::move(Err)), "%s", 93*37e48e4aSaurelien35 Filename.str().c_str()); 944f06d46fSCarlos Alberto Enciso return Error::success(); 954f06d46fSCarlos Alberto Enciso } 964f06d46fSCarlos Alberto Enciso 97e7950fceSCarlos Alberto Enciso // Search for a matching executable image for the given PDB path. 98e7950fceSCarlos Alberto Enciso static std::string searchForExe(const StringRef Path, 99e7950fceSCarlos Alberto Enciso const StringRef Extension) { 100e7950fceSCarlos Alberto Enciso SmallString<128> ExePath(Path); 101e7950fceSCarlos Alberto Enciso llvm::sys::path::replace_extension(ExePath, Extension); 102e7950fceSCarlos Alberto Enciso 103e7950fceSCarlos Alberto Enciso std::unique_ptr<IPDBSession> Session; 104e7950fceSCarlos Alberto Enciso if (Error Err = loadDataForEXE(PDB_ReaderType::Native, ExePath, Session)) { 105e7950fceSCarlos Alberto Enciso consumeError(std::move(Err)); 106e7950fceSCarlos Alberto Enciso return {}; 107e7950fceSCarlos Alberto Enciso } 108e7950fceSCarlos Alberto Enciso // We have a candidate for the executable image. 109e7950fceSCarlos Alberto Enciso Expected<std::string> PdbPathOrErr = NativeSession::searchForPdb({ExePath}); 110e7950fceSCarlos Alberto Enciso if (!PdbPathOrErr) { 111e7950fceSCarlos Alberto Enciso consumeError(PdbPathOrErr.takeError()); 112e7950fceSCarlos Alberto Enciso return {}; 113e7950fceSCarlos Alberto Enciso } 114e7950fceSCarlos Alberto Enciso // Convert any Windows backslashes into forward slashes to get the path. 115e7950fceSCarlos Alberto Enciso std::string ConvertedPath = sys::path::convert_to_slash( 116e7950fceSCarlos Alberto Enciso PdbPathOrErr.get(), sys::path::Style::windows); 117e7950fceSCarlos Alberto Enciso if (ConvertedPath == Path) 118e7950fceSCarlos Alberto Enciso return std::string(ExePath); 119e7950fceSCarlos Alberto Enciso 120e7950fceSCarlos Alberto Enciso return {}; 121e7950fceSCarlos Alberto Enciso } 122e7950fceSCarlos Alberto Enciso 123e7950fceSCarlos Alberto Enciso // Search for a matching object image for the given PDB path. 124e7950fceSCarlos Alberto Enciso static std::string searchForObj(const StringRef Path, 125e7950fceSCarlos Alberto Enciso const StringRef Extension) { 126e7950fceSCarlos Alberto Enciso SmallString<128> ObjPath(Path); 127e7950fceSCarlos Alberto Enciso llvm::sys::path::replace_extension(ObjPath, Extension); 128e7950fceSCarlos Alberto Enciso if (llvm::sys::fs::exists(ObjPath)) { 129e7950fceSCarlos Alberto Enciso ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr = 130e7950fceSCarlos Alberto Enciso MemoryBuffer::getFileOrSTDIN(ObjPath); 131e7950fceSCarlos Alberto Enciso if (!BuffOrErr) 132e7950fceSCarlos Alberto Enciso return {}; 133e7950fceSCarlos Alberto Enciso return std::string(ObjPath); 134e7950fceSCarlos Alberto Enciso } 135e7950fceSCarlos Alberto Enciso 136e7950fceSCarlos Alberto Enciso return {}; 137e7950fceSCarlos Alberto Enciso } 138e7950fceSCarlos Alberto Enciso 1394f06d46fSCarlos Alberto Enciso Error LVReaderHandler::handleBuffer(LVReaders &Readers, StringRef Filename, 1404f06d46fSCarlos Alberto Enciso MemoryBufferRef Buffer, StringRef ExePath) { 141e7950fceSCarlos Alberto Enciso // As PDB does not support the Binary interface, at this point we can check 142e7950fceSCarlos Alberto Enciso // if the buffer corresponds to a PDB or PE file. 143e7950fceSCarlos Alberto Enciso file_magic FileMagic = identify_magic(Buffer.getBuffer()); 144e7950fceSCarlos Alberto Enciso if (FileMagic == file_magic::pdb) { 145e7950fceSCarlos Alberto Enciso if (!ExePath.empty()) 146e7950fceSCarlos Alberto Enciso return handleObject(Readers, Filename, Buffer.getBuffer(), ExePath); 147e7950fceSCarlos Alberto Enciso 148e7950fceSCarlos Alberto Enciso // Search in the directory derived from the given 'Filename' for a 149e7950fceSCarlos Alberto Enciso // matching object file (.o, .obj, .lib) or a matching executable file 150e7950fceSCarlos Alberto Enciso // (.exe/.dll) and try to create the reader based on the matched file. 151e7950fceSCarlos Alberto Enciso // If no matching file is found then we load the original PDB file. 152e7950fceSCarlos Alberto Enciso std::vector<StringRef> ExecutableExtensions = {"exe", "dll"}; 153e7950fceSCarlos Alberto Enciso for (StringRef Extension : ExecutableExtensions) { 154e7950fceSCarlos Alberto Enciso std::string ExecutableImage = searchForExe(Filename, Extension); 155e7950fceSCarlos Alberto Enciso if (ExecutableImage.empty()) 156e7950fceSCarlos Alberto Enciso continue; 157e7950fceSCarlos Alberto Enciso if (Error Err = handleObject(Readers, Filename, Buffer.getBuffer(), 158e7950fceSCarlos Alberto Enciso ExecutableImage)) { 159e7950fceSCarlos Alberto Enciso consumeError(std::move(Err)); 160e7950fceSCarlos Alberto Enciso continue; 161e7950fceSCarlos Alberto Enciso } 162e7950fceSCarlos Alberto Enciso return Error::success(); 163e7950fceSCarlos Alberto Enciso } 164e7950fceSCarlos Alberto Enciso 165e7950fceSCarlos Alberto Enciso std::vector<StringRef> ObjectExtensions = {"o", "obj", "lib"}; 166e7950fceSCarlos Alberto Enciso for (StringRef Extension : ObjectExtensions) { 167e7950fceSCarlos Alberto Enciso std::string ObjectImage = searchForObj(Filename, Extension); 168e7950fceSCarlos Alberto Enciso if (ObjectImage.empty()) 169e7950fceSCarlos Alberto Enciso continue; 170e7950fceSCarlos Alberto Enciso if (Error Err = handleFile(Readers, ObjectImage)) { 171e7950fceSCarlos Alberto Enciso consumeError(std::move(Err)); 172e7950fceSCarlos Alberto Enciso continue; 173e7950fceSCarlos Alberto Enciso } 174e7950fceSCarlos Alberto Enciso return Error::success(); 175e7950fceSCarlos Alberto Enciso } 176e7950fceSCarlos Alberto Enciso 177e7950fceSCarlos Alberto Enciso // No matching executable/object image was found. Load the given PDB. 178e7950fceSCarlos Alberto Enciso return handleObject(Readers, Filename, Buffer.getBuffer(), ExePath); 179e7950fceSCarlos Alberto Enciso } 180e7950fceSCarlos Alberto Enciso if (FileMagic == file_magic::pecoff_executable) { 181e7950fceSCarlos Alberto Enciso // If we have a valid executable, try to find a matching PDB file. 182e7950fceSCarlos Alberto Enciso Expected<std::string> PdbPath = NativeSession::searchForPdb({Filename}); 183e7950fceSCarlos Alberto Enciso if (errorToErrorCode(PdbPath.takeError())) { 184e7950fceSCarlos Alberto Enciso return createStringError( 185e7950fceSCarlos Alberto Enciso errc::not_supported, 186e7950fceSCarlos Alberto Enciso "Binary object format in '%s' does not have debug info.", 187e7950fceSCarlos Alberto Enciso Filename.str().c_str()); 188e7950fceSCarlos Alberto Enciso } 189e7950fceSCarlos Alberto Enciso // Process the matching PDB file and pass the executable filename. 190e7950fceSCarlos Alberto Enciso return handleFile(Readers, PdbPath.get(), Filename); 191e7950fceSCarlos Alberto Enciso } 192e7950fceSCarlos Alberto Enciso 1934f06d46fSCarlos Alberto Enciso Expected<std::unique_ptr<Binary>> BinOrErr = createBinary(Buffer); 1944f06d46fSCarlos Alberto Enciso if (errorToErrorCode(BinOrErr.takeError())) { 1954f06d46fSCarlos Alberto Enciso return createStringError(errc::not_supported, 1964f06d46fSCarlos Alberto Enciso "Binary object format in '%s' is not supported.", 1974f06d46fSCarlos Alberto Enciso Filename.str().c_str()); 1984f06d46fSCarlos Alberto Enciso } 1994f06d46fSCarlos Alberto Enciso return handleObject(Readers, Filename, *BinOrErr.get()); 2004f06d46fSCarlos Alberto Enciso } 2014f06d46fSCarlos Alberto Enciso 2024f06d46fSCarlos Alberto Enciso Error LVReaderHandler::handleFile(LVReaders &Readers, StringRef Filename, 2034f06d46fSCarlos Alberto Enciso StringRef ExePath) { 2044f06d46fSCarlos Alberto Enciso // Convert any Windows backslashes into forward slashes to get the path. 2054f06d46fSCarlos Alberto Enciso std::string ConvertedPath = 2064f06d46fSCarlos Alberto Enciso sys::path::convert_to_slash(Filename, sys::path::Style::windows); 2074f06d46fSCarlos Alberto Enciso ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr = 2084f06d46fSCarlos Alberto Enciso MemoryBuffer::getFileOrSTDIN(ConvertedPath); 2094f06d46fSCarlos Alberto Enciso if (BuffOrErr.getError()) { 2104f06d46fSCarlos Alberto Enciso return createStringError(errc::bad_file_descriptor, 2114f06d46fSCarlos Alberto Enciso "File '%s' does not exist.", 2124f06d46fSCarlos Alberto Enciso ConvertedPath.c_str()); 2134f06d46fSCarlos Alberto Enciso } 2144f06d46fSCarlos Alberto Enciso std::unique_ptr<MemoryBuffer> Buffer = std::move(BuffOrErr.get()); 2154f06d46fSCarlos Alberto Enciso return handleBuffer(Readers, ConvertedPath, *Buffer, ExePath); 2164f06d46fSCarlos Alberto Enciso } 2174f06d46fSCarlos Alberto Enciso 2184f06d46fSCarlos Alberto Enciso Error LVReaderHandler::handleMach(LVReaders &Readers, StringRef Filename, 2194f06d46fSCarlos Alberto Enciso MachOUniversalBinary &Mach) { 2204f06d46fSCarlos Alberto Enciso for (const MachOUniversalBinary::ObjectForArch &ObjForArch : Mach.objects()) { 2214f06d46fSCarlos Alberto Enciso std::string ObjName = (Twine(Filename) + Twine("(") + 2224f06d46fSCarlos Alberto Enciso Twine(ObjForArch.getArchFlagName()) + Twine(")")) 2234f06d46fSCarlos Alberto Enciso .str(); 2244f06d46fSCarlos Alberto Enciso if (Expected<std::unique_ptr<MachOObjectFile>> MachOOrErr = 2254f06d46fSCarlos Alberto Enciso ObjForArch.getAsObjectFile()) { 2264f06d46fSCarlos Alberto Enciso MachOObjectFile &Obj = **MachOOrErr; 2274f06d46fSCarlos Alberto Enciso PdbOrObj Input = &Obj; 2284f06d46fSCarlos Alberto Enciso if (Error Err = 2294f06d46fSCarlos Alberto Enciso createReader(Filename, Readers, Input, Obj.getFileFormatName())) 2304f06d46fSCarlos Alberto Enciso return Err; 2314f06d46fSCarlos Alberto Enciso continue; 2324f06d46fSCarlos Alberto Enciso } else 2334f06d46fSCarlos Alberto Enciso consumeError(MachOOrErr.takeError()); 2344f06d46fSCarlos Alberto Enciso if (Expected<std::unique_ptr<Archive>> ArchiveOrErr = 2354f06d46fSCarlos Alberto Enciso ObjForArch.getAsArchive()) { 2364f06d46fSCarlos Alberto Enciso if (Error Err = handleArchive(Readers, ObjName, *ArchiveOrErr.get())) 2374f06d46fSCarlos Alberto Enciso return Err; 2384f06d46fSCarlos Alberto Enciso continue; 2394f06d46fSCarlos Alberto Enciso } else 2404f06d46fSCarlos Alberto Enciso consumeError(ArchiveOrErr.takeError()); 2414f06d46fSCarlos Alberto Enciso } 2424f06d46fSCarlos Alberto Enciso return Error::success(); 2434f06d46fSCarlos Alberto Enciso } 2444f06d46fSCarlos Alberto Enciso 2454f06d46fSCarlos Alberto Enciso Error LVReaderHandler::handleObject(LVReaders &Readers, StringRef Filename, 2464f06d46fSCarlos Alberto Enciso Binary &Binary) { 2474f06d46fSCarlos Alberto Enciso if (PdbOrObj Input = dyn_cast<ObjectFile>(&Binary)) 2484f06d46fSCarlos Alberto Enciso return createReader(Filename, Readers, Input, 2497021182dSShraiysh Vaishay cast<ObjectFile *>(Input)->getFileFormatName()); 2504f06d46fSCarlos Alberto Enciso 2514f06d46fSCarlos Alberto Enciso if (MachOUniversalBinary *Fat = dyn_cast<MachOUniversalBinary>(&Binary)) 2524f06d46fSCarlos Alberto Enciso return handleMach(Readers, Filename, *Fat); 2534f06d46fSCarlos Alberto Enciso 2544f06d46fSCarlos Alberto Enciso if (Archive *Arch = dyn_cast<Archive>(&Binary)) 2554f06d46fSCarlos Alberto Enciso return handleArchive(Readers, Filename, *Arch); 2564f06d46fSCarlos Alberto Enciso 2574f06d46fSCarlos Alberto Enciso return createStringError(errc::not_supported, 2584f06d46fSCarlos Alberto Enciso "Binary object format in '%s' is not supported.", 2594f06d46fSCarlos Alberto Enciso Filename.str().c_str()); 2604f06d46fSCarlos Alberto Enciso } 2614f06d46fSCarlos Alberto Enciso 262e7950fceSCarlos Alberto Enciso Error LVReaderHandler::handleObject(LVReaders &Readers, StringRef Filename, 263e7950fceSCarlos Alberto Enciso StringRef Buffer, StringRef ExePath) { 264e7950fceSCarlos Alberto Enciso std::unique_ptr<IPDBSession> Session; 265e7950fceSCarlos Alberto Enciso if (Error Err = loadDataForPDB(PDB_ReaderType::Native, Filename, Session)) 266e7950fceSCarlos Alberto Enciso return createStringError(errorToErrorCode(std::move(Err)), "%s", 267e7950fceSCarlos Alberto Enciso Filename.str().c_str()); 268e7950fceSCarlos Alberto Enciso 269e7950fceSCarlos Alberto Enciso std::unique_ptr<NativeSession> PdbSession; 270e7950fceSCarlos Alberto Enciso PdbSession.reset(static_cast<NativeSession *>(Session.release())); 271e7950fceSCarlos Alberto Enciso PdbOrObj Input = &PdbSession->getPDBFile(); 272e7950fceSCarlos Alberto Enciso StringRef FileFormatName; 273e7950fceSCarlos Alberto Enciso size_t Pos = Buffer.find_first_of("\r\n"); 274e7950fceSCarlos Alberto Enciso if (Pos) 275e7950fceSCarlos Alberto Enciso FileFormatName = Buffer.substr(0, Pos - 1); 276e7950fceSCarlos Alberto Enciso return createReader(Filename, Readers, Input, FileFormatName, ExePath); 277e7950fceSCarlos Alberto Enciso } 278e7950fceSCarlos Alberto Enciso 2794f06d46fSCarlos Alberto Enciso Error LVReaderHandler::createReaders() { 2804f06d46fSCarlos Alberto Enciso LLVM_DEBUG(dbgs() << "createReaders\n"); 2814f06d46fSCarlos Alberto Enciso for (std::string &Object : Objects) { 2824f06d46fSCarlos Alberto Enciso LVReaders Readers; 2834f06d46fSCarlos Alberto Enciso if (Error Err = createReader(Object, Readers)) 2844f06d46fSCarlos Alberto Enciso return Err; 2857fbcc244SCarlos Alberto Enciso TheReaders.insert(TheReaders.end(), 2867fbcc244SCarlos Alberto Enciso std::make_move_iterator(Readers.begin()), 2877fbcc244SCarlos Alberto Enciso std::make_move_iterator(Readers.end())); 2884f06d46fSCarlos Alberto Enciso } 2894f06d46fSCarlos Alberto Enciso 2904f06d46fSCarlos Alberto Enciso return Error::success(); 2914f06d46fSCarlos Alberto Enciso } 2924f06d46fSCarlos Alberto Enciso 2934f06d46fSCarlos Alberto Enciso Error LVReaderHandler::printReaders() { 2944f06d46fSCarlos Alberto Enciso LLVM_DEBUG(dbgs() << "printReaders\n"); 2954f06d46fSCarlos Alberto Enciso if (options().getPrintExecute()) 2967fbcc244SCarlos Alberto Enciso for (const std::unique_ptr<LVReader> &Reader : TheReaders) 2974f06d46fSCarlos Alberto Enciso if (Error Err = Reader->doPrint()) 2984f06d46fSCarlos Alberto Enciso return Err; 2994f06d46fSCarlos Alberto Enciso 3004f06d46fSCarlos Alberto Enciso return Error::success(); 3014f06d46fSCarlos Alberto Enciso } 3024f06d46fSCarlos Alberto Enciso 3034f06d46fSCarlos Alberto Enciso Error LVReaderHandler::compareReaders() { 3044f06d46fSCarlos Alberto Enciso LLVM_DEBUG(dbgs() << "compareReaders\n"); 3054f06d46fSCarlos Alberto Enciso size_t ReadersCount = TheReaders.size(); 3064f06d46fSCarlos Alberto Enciso if (options().getCompareExecute() && ReadersCount >= 2) { 3074f06d46fSCarlos Alberto Enciso // If we have more than 2 readers, compare them by pairs. 3084f06d46fSCarlos Alberto Enciso size_t ViewPairs = ReadersCount / 2; 3094f06d46fSCarlos Alberto Enciso LVCompare Compare(OS); 3104f06d46fSCarlos Alberto Enciso for (size_t Pair = 0, Index = 0; Pair < ViewPairs; ++Pair) { 3117fbcc244SCarlos Alberto Enciso if (Error Err = Compare.execute(TheReaders[Index].get(), 3127fbcc244SCarlos Alberto Enciso TheReaders[Index + 1].get())) 3134f06d46fSCarlos Alberto Enciso return Err; 3144f06d46fSCarlos Alberto Enciso Index += 2; 3154f06d46fSCarlos Alberto Enciso } 3164f06d46fSCarlos Alberto Enciso } 3174f06d46fSCarlos Alberto Enciso 3184f06d46fSCarlos Alberto Enciso return Error::success(); 3194f06d46fSCarlos Alberto Enciso } 3204f06d46fSCarlos Alberto Enciso 3214f06d46fSCarlos Alberto Enciso void LVReaderHandler::print(raw_ostream &OS) const { OS << "ReaderHandler\n"; } 322