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