1*bdd1243dSDimitry Andric //===-- LVReaderHandler.cpp -----------------------------------------------===// 2*bdd1243dSDimitry Andric // 3*bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*bdd1243dSDimitry Andric // 7*bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 8*bdd1243dSDimitry Andric // 9*bdd1243dSDimitry Andric // This class implements the Reader Handler. 10*bdd1243dSDimitry Andric // 11*bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 12*bdd1243dSDimitry Andric 13*bdd1243dSDimitry Andric #include "llvm/DebugInfo/LogicalView/LVReaderHandler.h" 14*bdd1243dSDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVCompare.h" 15*bdd1243dSDimitry Andric #include "llvm/DebugInfo/LogicalView/Readers/LVELFReader.h" 16*bdd1243dSDimitry Andric 17*bdd1243dSDimitry Andric using namespace llvm; 18*bdd1243dSDimitry Andric using namespace llvm::object; 19*bdd1243dSDimitry Andric using namespace llvm::pdb; 20*bdd1243dSDimitry Andric using namespace llvm::logicalview; 21*bdd1243dSDimitry Andric 22*bdd1243dSDimitry Andric #define DEBUG_TYPE "ReaderHandler" 23*bdd1243dSDimitry Andric 24*bdd1243dSDimitry Andric Error LVReaderHandler::process() { 25*bdd1243dSDimitry Andric if (Error Err = createReaders()) 26*bdd1243dSDimitry Andric return Err; 27*bdd1243dSDimitry Andric if (Error Err = printReaders()) 28*bdd1243dSDimitry Andric return Err; 29*bdd1243dSDimitry Andric if (Error Err = compareReaders()) 30*bdd1243dSDimitry Andric return Err; 31*bdd1243dSDimitry Andric 32*bdd1243dSDimitry Andric return Error::success(); 33*bdd1243dSDimitry Andric } 34*bdd1243dSDimitry Andric 35*bdd1243dSDimitry Andric void LVReaderHandler::destroyReaders() { 36*bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "destroyReaders\n"); 37*bdd1243dSDimitry Andric for (const LVReader *Reader : TheReaders) 38*bdd1243dSDimitry Andric delete Reader; 39*bdd1243dSDimitry Andric } 40*bdd1243dSDimitry Andric 41*bdd1243dSDimitry Andric Error LVReaderHandler::createReader(StringRef Filename, LVReaders &Readers, 42*bdd1243dSDimitry Andric PdbOrObj &Input, StringRef FileFormatName, 43*bdd1243dSDimitry Andric StringRef ExePath) { 44*bdd1243dSDimitry Andric auto CreateOneReader = [&]() -> LVReader * { 45*bdd1243dSDimitry Andric if (Input.is<ObjectFile *>()) { 46*bdd1243dSDimitry Andric ObjectFile &Obj = *Input.get<ObjectFile *>(); 47*bdd1243dSDimitry Andric if (Obj.isELF() || Obj.isMachO()) 48*bdd1243dSDimitry Andric return new LVELFReader(Filename, FileFormatName, Obj, W); 49*bdd1243dSDimitry Andric } 50*bdd1243dSDimitry Andric return nullptr; 51*bdd1243dSDimitry Andric }; 52*bdd1243dSDimitry Andric 53*bdd1243dSDimitry Andric LVReader *Reader = CreateOneReader(); 54*bdd1243dSDimitry Andric if (!Reader) 55*bdd1243dSDimitry Andric return createStringError(errc::invalid_argument, 56*bdd1243dSDimitry Andric "unable to create reader for: '%s'", 57*bdd1243dSDimitry Andric Filename.str().c_str()); 58*bdd1243dSDimitry Andric 59*bdd1243dSDimitry Andric Readers.push_back(Reader); 60*bdd1243dSDimitry Andric return Reader->doLoad(); 61*bdd1243dSDimitry Andric } 62*bdd1243dSDimitry Andric 63*bdd1243dSDimitry Andric Error LVReaderHandler::handleArchive(LVReaders &Readers, StringRef Filename, 64*bdd1243dSDimitry Andric Archive &Arch) { 65*bdd1243dSDimitry Andric Error Err = Error::success(); 66*bdd1243dSDimitry Andric for (const Archive::Child &Child : Arch.children(Err)) { 67*bdd1243dSDimitry Andric Expected<MemoryBufferRef> BuffOrErr = Child.getMemoryBufferRef(); 68*bdd1243dSDimitry Andric if (Error Err = BuffOrErr.takeError()) 69*bdd1243dSDimitry Andric return createStringError(errorToErrorCode(std::move(Err)), "%s", 70*bdd1243dSDimitry Andric Filename.str().c_str()); 71*bdd1243dSDimitry Andric Expected<StringRef> NameOrErr = Child.getName(); 72*bdd1243dSDimitry Andric if (Error Err = NameOrErr.takeError()) 73*bdd1243dSDimitry Andric return createStringError(errorToErrorCode(std::move(Err)), "%s", 74*bdd1243dSDimitry Andric Filename.str().c_str()); 75*bdd1243dSDimitry Andric std::string Name = (Filename + "(" + NameOrErr.get() + ")").str(); 76*bdd1243dSDimitry Andric if (Error Err = handleBuffer(Readers, Name, BuffOrErr.get())) 77*bdd1243dSDimitry Andric return createStringError(errorToErrorCode(std::move(Err)), "%s", 78*bdd1243dSDimitry Andric Filename.str().c_str()); 79*bdd1243dSDimitry Andric } 80*bdd1243dSDimitry Andric 81*bdd1243dSDimitry Andric return Error::success(); 82*bdd1243dSDimitry Andric } 83*bdd1243dSDimitry Andric 84*bdd1243dSDimitry Andric Error LVReaderHandler::handleBuffer(LVReaders &Readers, StringRef Filename, 85*bdd1243dSDimitry Andric MemoryBufferRef Buffer, StringRef ExePath) { 86*bdd1243dSDimitry Andric Expected<std::unique_ptr<Binary>> BinOrErr = createBinary(Buffer); 87*bdd1243dSDimitry Andric if (errorToErrorCode(BinOrErr.takeError())) { 88*bdd1243dSDimitry Andric return createStringError(errc::not_supported, 89*bdd1243dSDimitry Andric "Binary object format in '%s' is not supported.", 90*bdd1243dSDimitry Andric Filename.str().c_str()); 91*bdd1243dSDimitry Andric } 92*bdd1243dSDimitry Andric return handleObject(Readers, Filename, *BinOrErr.get()); 93*bdd1243dSDimitry Andric } 94*bdd1243dSDimitry Andric 95*bdd1243dSDimitry Andric Error LVReaderHandler::handleFile(LVReaders &Readers, StringRef Filename, 96*bdd1243dSDimitry Andric StringRef ExePath) { 97*bdd1243dSDimitry Andric // Convert any Windows backslashes into forward slashes to get the path. 98*bdd1243dSDimitry Andric std::string ConvertedPath = 99*bdd1243dSDimitry Andric sys::path::convert_to_slash(Filename, sys::path::Style::windows); 100*bdd1243dSDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr = 101*bdd1243dSDimitry Andric MemoryBuffer::getFileOrSTDIN(ConvertedPath); 102*bdd1243dSDimitry Andric if (BuffOrErr.getError()) { 103*bdd1243dSDimitry Andric return createStringError(errc::bad_file_descriptor, 104*bdd1243dSDimitry Andric "File '%s' does not exist.", 105*bdd1243dSDimitry Andric ConvertedPath.c_str()); 106*bdd1243dSDimitry Andric } 107*bdd1243dSDimitry Andric std::unique_ptr<MemoryBuffer> Buffer = std::move(BuffOrErr.get()); 108*bdd1243dSDimitry Andric return handleBuffer(Readers, ConvertedPath, *Buffer, ExePath); 109*bdd1243dSDimitry Andric } 110*bdd1243dSDimitry Andric 111*bdd1243dSDimitry Andric Error LVReaderHandler::handleMach(LVReaders &Readers, StringRef Filename, 112*bdd1243dSDimitry Andric MachOUniversalBinary &Mach) { 113*bdd1243dSDimitry Andric for (const MachOUniversalBinary::ObjectForArch &ObjForArch : Mach.objects()) { 114*bdd1243dSDimitry Andric std::string ObjName = (Twine(Filename) + Twine("(") + 115*bdd1243dSDimitry Andric Twine(ObjForArch.getArchFlagName()) + Twine(")")) 116*bdd1243dSDimitry Andric .str(); 117*bdd1243dSDimitry Andric if (Expected<std::unique_ptr<MachOObjectFile>> MachOOrErr = 118*bdd1243dSDimitry Andric ObjForArch.getAsObjectFile()) { 119*bdd1243dSDimitry Andric MachOObjectFile &Obj = **MachOOrErr; 120*bdd1243dSDimitry Andric PdbOrObj Input = &Obj; 121*bdd1243dSDimitry Andric if (Error Err = 122*bdd1243dSDimitry Andric createReader(Filename, Readers, Input, Obj.getFileFormatName())) 123*bdd1243dSDimitry Andric return Err; 124*bdd1243dSDimitry Andric continue; 125*bdd1243dSDimitry Andric } else 126*bdd1243dSDimitry Andric consumeError(MachOOrErr.takeError()); 127*bdd1243dSDimitry Andric if (Expected<std::unique_ptr<Archive>> ArchiveOrErr = 128*bdd1243dSDimitry Andric ObjForArch.getAsArchive()) { 129*bdd1243dSDimitry Andric if (Error Err = handleArchive(Readers, ObjName, *ArchiveOrErr.get())) 130*bdd1243dSDimitry Andric return Err; 131*bdd1243dSDimitry Andric continue; 132*bdd1243dSDimitry Andric } else 133*bdd1243dSDimitry Andric consumeError(ArchiveOrErr.takeError()); 134*bdd1243dSDimitry Andric } 135*bdd1243dSDimitry Andric return Error::success(); 136*bdd1243dSDimitry Andric } 137*bdd1243dSDimitry Andric 138*bdd1243dSDimitry Andric Error LVReaderHandler::handleObject(LVReaders &Readers, StringRef Filename, 139*bdd1243dSDimitry Andric Binary &Binary) { 140*bdd1243dSDimitry Andric if (PdbOrObj Input = dyn_cast<ObjectFile>(&Binary)) 141*bdd1243dSDimitry Andric return createReader(Filename, Readers, Input, 142*bdd1243dSDimitry Andric Input.get<ObjectFile *>()->getFileFormatName()); 143*bdd1243dSDimitry Andric 144*bdd1243dSDimitry Andric if (MachOUniversalBinary *Fat = dyn_cast<MachOUniversalBinary>(&Binary)) 145*bdd1243dSDimitry Andric return handleMach(Readers, Filename, *Fat); 146*bdd1243dSDimitry Andric 147*bdd1243dSDimitry Andric if (Archive *Arch = dyn_cast<Archive>(&Binary)) 148*bdd1243dSDimitry Andric return handleArchive(Readers, Filename, *Arch); 149*bdd1243dSDimitry Andric 150*bdd1243dSDimitry Andric return createStringError(errc::not_supported, 151*bdd1243dSDimitry Andric "Binary object format in '%s' is not supported.", 152*bdd1243dSDimitry Andric Filename.str().c_str()); 153*bdd1243dSDimitry Andric } 154*bdd1243dSDimitry Andric 155*bdd1243dSDimitry Andric Error LVReaderHandler::createReaders() { 156*bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "createReaders\n"); 157*bdd1243dSDimitry Andric for (std::string &Object : Objects) { 158*bdd1243dSDimitry Andric LVReaders Readers; 159*bdd1243dSDimitry Andric if (Error Err = createReader(Object, Readers)) 160*bdd1243dSDimitry Andric return Err; 161*bdd1243dSDimitry Andric TheReaders.insert(TheReaders.end(), Readers.begin(), Readers.end()); 162*bdd1243dSDimitry Andric } 163*bdd1243dSDimitry Andric 164*bdd1243dSDimitry Andric return Error::success(); 165*bdd1243dSDimitry Andric } 166*bdd1243dSDimitry Andric 167*bdd1243dSDimitry Andric Error LVReaderHandler::printReaders() { 168*bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "printReaders\n"); 169*bdd1243dSDimitry Andric if (options().getPrintExecute()) 170*bdd1243dSDimitry Andric for (LVReader *Reader : TheReaders) 171*bdd1243dSDimitry Andric if (Error Err = Reader->doPrint()) 172*bdd1243dSDimitry Andric return Err; 173*bdd1243dSDimitry Andric 174*bdd1243dSDimitry Andric return Error::success(); 175*bdd1243dSDimitry Andric } 176*bdd1243dSDimitry Andric 177*bdd1243dSDimitry Andric Error LVReaderHandler::compareReaders() { 178*bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "compareReaders\n"); 179*bdd1243dSDimitry Andric size_t ReadersCount = TheReaders.size(); 180*bdd1243dSDimitry Andric if (options().getCompareExecute() && ReadersCount >= 2) { 181*bdd1243dSDimitry Andric // If we have more than 2 readers, compare them by pairs. 182*bdd1243dSDimitry Andric size_t ViewPairs = ReadersCount / 2; 183*bdd1243dSDimitry Andric LVCompare Compare(OS); 184*bdd1243dSDimitry Andric for (size_t Pair = 0, Index = 0; Pair < ViewPairs; ++Pair) { 185*bdd1243dSDimitry Andric if (Error Err = Compare.execute(TheReaders[Index], TheReaders[Index + 1])) 186*bdd1243dSDimitry Andric return Err; 187*bdd1243dSDimitry Andric Index += 2; 188*bdd1243dSDimitry Andric } 189*bdd1243dSDimitry Andric } 190*bdd1243dSDimitry Andric 191*bdd1243dSDimitry Andric return Error::success(); 192*bdd1243dSDimitry Andric } 193*bdd1243dSDimitry Andric 194*bdd1243dSDimitry Andric void LVReaderHandler::print(raw_ostream &OS) const { OS << "ReaderHandler\n"; } 195