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
process()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
destroyReaders()35 void LVReaderHandler::destroyReaders() {
36 LLVM_DEBUG(dbgs() << "destroyReaders\n");
37 for (const LVReader *Reader : TheReaders)
38 delete Reader;
39 }
40
createReader(StringRef Filename,LVReaders & Readers,PdbOrObj & Input,StringRef FileFormatName,StringRef ExePath)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
handleArchive(LVReaders & Readers,StringRef Filename,Archive & Arch)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
handleBuffer(LVReaders & Readers,StringRef Filename,MemoryBufferRef Buffer,StringRef ExePath)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
handleFile(LVReaders & Readers,StringRef Filename,StringRef ExePath)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
handleMach(LVReaders & Readers,StringRef Filename,MachOUniversalBinary & Mach)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
handleObject(LVReaders & Readers,StringRef Filename,Binary & Binary)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
createReaders()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
printReaders()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
compareReaders()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
print(raw_ostream & OS) const194 void LVReaderHandler::print(raw_ostream &OS) const { OS << "ReaderHandler\n"; }
195