1 //===- Symbolize.h ----------------------------------------------*- C++ -*-===//
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 // Header for LLVM symbolization library.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZE_H
14 #define LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZE_H
15 
16 #include "llvm/DebugInfo/Symbolize/DIFetcher.h"
17 #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
18 #include "llvm/Object/Binary.h"
19 #include "llvm/Object/ELFObjectFile.h"
20 #include "llvm/Object/ObjectFile.h"
21 #include "llvm/Support/Error.h"
22 #include <algorithm>
23 #include <cstdint>
24 #include <map>
25 #include <memory>
26 #include <string>
27 #include <utility>
28 #include <vector>
29 
30 namespace llvm {
31 namespace symbolize {
32 
33 using namespace object;
34 
35 using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind;
36 using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;
37 
38 class LLVMSymbolizer {
39 public:
40   struct Options {
41     FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName;
42     FileLineInfoKind PathStyle = FileLineInfoKind::AbsoluteFilePath;
43     bool UseSymbolTable = true;
44     bool Demangle = true;
45     bool RelativeAddresses = false;
46     bool UntagAddresses = false;
47     bool UseDIA = false;
48     std::string DefaultArch;
49     std::vector<std::string> DsymHints;
50     std::string FallbackDebugPath;
51     std::string DWPName;
52     std::vector<std::string> DebugFileDirectory;
53   };
54 
55   LLVMSymbolizer() = default;
56   LLVMSymbolizer(const Options &Opts) : Opts(Opts) {}
57 
58   ~LLVMSymbolizer() { flush(); }
59 
60   // Overloads accepting ObjectFile does not support COFF currently
61   Expected<DILineInfo> symbolizeCode(const ObjectFile &Obj,
62                                      object::SectionedAddress ModuleOffset);
63   Expected<DILineInfo> symbolizeCode(const std::string &ModuleName,
64                                      object::SectionedAddress ModuleOffset);
65   Expected<DIInliningInfo>
66   symbolizeInlinedCode(const ObjectFile &Obj,
67                        object::SectionedAddress ModuleOffset);
68   Expected<DIInliningInfo>
69   symbolizeInlinedCode(const std::string &ModuleName,
70                        object::SectionedAddress ModuleOffset);
71 
72   Expected<DIGlobal> symbolizeData(const ObjectFile &Obj,
73                                    object::SectionedAddress ModuleOffset);
74   Expected<DIGlobal> symbolizeData(const std::string &ModuleName,
75                                    object::SectionedAddress ModuleOffset);
76   Expected<std::vector<DILocal>>
77   symbolizeFrame(const ObjectFile &Obj, object::SectionedAddress ModuleOffset);
78   Expected<std::vector<DILocal>>
79   symbolizeFrame(const std::string &ModuleName,
80                  object::SectionedAddress ModuleOffset);
81   void flush();
82 
83   static std::string
84   DemangleName(const std::string &Name,
85                const SymbolizableModule *DbiModuleDescriptor);
86 
87   void addDIFetcher(std::unique_ptr<DIFetcher> Fetcher) {
88     DIFetchers.push_back(std::move(Fetcher));
89   }
90 
91 private:
92   // Bundles together object file with code/data and object file with
93   // corresponding debug info. These objects can be the same.
94   using ObjectPair = std::pair<const ObjectFile *, const ObjectFile *>;
95 
96   template <typename T>
97   Expected<DILineInfo>
98   symbolizeCodeCommon(const T &ModuleSpecifier,
99                       object::SectionedAddress ModuleOffset);
100   template <typename T>
101   Expected<DIInliningInfo>
102   symbolizeInlinedCodeCommon(const T &ModuleSpecifier,
103                              object::SectionedAddress ModuleOffset);
104   template <typename T>
105   Expected<DIGlobal> symbolizeDataCommon(const T &ModuleSpecifier,
106                                          object::SectionedAddress ModuleOffset);
107   template <typename T>
108   Expected<std::vector<DILocal>>
109   symbolizeFrameCommon(const T &ModuleSpecifier,
110                        object::SectionedAddress ModuleOffset);
111 
112   /// Returns a SymbolizableModule or an error if loading debug info failed.
113   /// Only one attempt is made to load a module, and errors during loading are
114   /// only reported once. Subsequent calls to get module info for a module that
115   /// failed to load will return nullptr.
116   Expected<SymbolizableModule *>
117   getOrCreateModuleInfo(const std::string &ModuleName);
118   Expected<SymbolizableModule *> getOrCreateModuleInfo(const ObjectFile &Obj);
119 
120   Expected<SymbolizableModule *>
121   createModuleInfo(const ObjectFile *Obj, std::unique_ptr<DIContext> Context,
122                    StringRef ModuleName);
123 
124   ObjectFile *lookUpDsymFile(const std::string &Path,
125                              const MachOObjectFile *ExeObj,
126                              const std::string &ArchName);
127   ObjectFile *lookUpDebuglinkObject(const std::string &Path,
128                                     const ObjectFile *Obj,
129                                     const std::string &ArchName);
130   ObjectFile *lookUpBuildIDObject(const std::string &Path,
131                                   const ELFObjectFileBase *Obj,
132                                   const std::string &ArchName);
133 
134   bool findDebugBinary(const std::string &OrigPath,
135                        const std::string &DebuglinkName, uint32_t CRCHash,
136                        std::string &Result);
137 
138   bool findDebugBinary(const ArrayRef<uint8_t> BuildID, std::string &Result);
139 
140   /// Returns pair of pointers to object and debug object.
141   Expected<ObjectPair> getOrCreateObjectPair(const std::string &Path,
142                                              const std::string &ArchName);
143 
144   /// Return a pointer to object file at specified path, for a specified
145   /// architecture (e.g. if path refers to a Mach-O universal binary, only one
146   /// object file from it will be returned).
147   Expected<ObjectFile *> getOrCreateObject(const std::string &Path,
148                                            const std::string &ArchName);
149 
150   std::map<std::string, std::unique_ptr<SymbolizableModule>, std::less<>>
151       Modules;
152 
153   /// Contains cached results of getOrCreateObjectPair().
154   std::map<std::pair<std::string, std::string>, ObjectPair>
155       ObjectPairForPathArch;
156 
157   /// Contains parsed binary for each path, or parsing error.
158   std::map<std::string, OwningBinary<Binary>> BinaryForPath;
159 
160   /// Parsed object file for path/architecture pair, where "path" refers
161   /// to Mach-O universal binary.
162   std::map<std::pair<std::string, std::string>, std::unique_ptr<ObjectFile>>
163       ObjectForUBPathAndArch;
164 
165   Options Opts;
166 
167   SmallVector<std::unique_ptr<DIFetcher>> DIFetchers;
168 };
169 
170 } // end namespace symbolize
171 } // end namespace llvm
172 
173 #endif // LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZE_H
174