xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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