1 //===- GsymCreator.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 #ifndef LLVM_DEBUGINFO_GSYM_GSYMCREATOR_H 10 #define LLVM_DEBUGINFO_GSYM_GSYMCREATOR_H 11 12 #include <functional> 13 #include <memory> 14 #include <mutex> 15 #include <string> 16 #include <thread> 17 18 #include "llvm/ADT/ArrayRef.h" 19 #include "llvm/DebugInfo/GSYM/FileEntry.h" 20 #include "llvm/DebugInfo/GSYM/FunctionInfo.h" 21 #include "llvm/DebugInfo/GSYM/Range.h" 22 #include "llvm/MC/StringTableBuilder.h" 23 #include "llvm/Support/Endian.h" 24 #include "llvm/Support/Error.h" 25 #include "llvm/Support/Path.h" 26 27 namespace llvm { 28 29 namespace gsym { 30 class FileWriter; 31 32 /// GsymCreator is used to emit GSYM data to a stand alone file or section 33 /// within a file. 34 /// 35 /// The GsymCreator is designed to be used in 3 stages: 36 /// - Create FunctionInfo objects and add them 37 /// - Finalize the GsymCreator object 38 /// - Save to file or section 39 /// 40 /// The first stage involves creating FunctionInfo objects from another source 41 /// of information like compiler debug info metadata, DWARF or Breakpad files. 42 /// Any strings in the FunctionInfo or contained information, like InlineInfo 43 /// or LineTable objects, should get the string table offsets by calling 44 /// GsymCreator::insertString(...). Any file indexes that are needed should be 45 /// obtained by calling GsymCreator::insertFile(...). All of the function calls 46 /// in GsymCreator are thread safe. This allows multiple threads to create and 47 /// add FunctionInfo objects while parsing debug information. 48 /// 49 /// Once all of the FunctionInfo objects have been added, the 50 /// GsymCreator::finalize(...) must be called prior to saving. This function 51 /// will sort the FunctionInfo objects, finalize the string table, and do any 52 /// other passes on the information needed to prepare the information to be 53 /// saved. 54 /// 55 /// Once the object has been finalized, it can be saved to a file or section. 56 /// 57 /// ENCODING 58 /// 59 /// GSYM files are designed to be memory mapped into a process as shared, read 60 /// only data, and used as is. 61 /// 62 /// The GSYM file format when in a stand alone file consists of: 63 /// - Header 64 /// - Address Table 65 /// - Function Info Offsets 66 /// - File Table 67 /// - String Table 68 /// - Function Info Data 69 /// 70 /// HEADER 71 /// 72 /// The header is fully described in "llvm/DebugInfo/GSYM/Header.h". 73 /// 74 /// ADDRESS TABLE 75 /// 76 /// The address table immediately follows the header in the file and consists 77 /// of Header.NumAddresses address offsets. These offsets are sorted and can be 78 /// binary searched for efficient lookups. Addresses in the address table are 79 /// stored as offsets from a 64 bit base address found in Header.BaseAddress. 80 /// This allows the address table to contain 8, 16, or 32 offsets. This allows 81 /// the address table to not require full 64 bit addresses for each address. 82 /// The resulting GSYM size is smaller and causes fewer pages to be touched 83 /// during address lookups when the address table is smaller. The size of the 84 /// address offsets in the address table is specified in the header in 85 /// Header.AddrOffSize. The first offset in the address table is aligned to 86 /// Header.AddrOffSize alignment to ensure efficient access when loaded into 87 /// memory. 88 /// 89 /// FUNCTION INFO OFFSETS TABLE 90 /// 91 /// The function info offsets table immediately follows the address table and 92 /// consists of Header.NumAddresses 32 bit file offsets: one for each address 93 /// in the address table. This data is aligned to a 4 byte boundary. The 94 /// offsets in this table are the relative offsets from the start offset of the 95 /// GSYM header and point to the function info data for each address in the 96 /// address table. Keeping this data separate from the address table helps to 97 /// reduce the number of pages that are touched when address lookups occur on a 98 /// GSYM file. 99 /// 100 /// FILE TABLE 101 /// 102 /// The file table immediately follows the function info offsets table. The 103 /// encoding of the FileTable is: 104 /// 105 /// struct FileTable { 106 /// uint32_t Count; 107 /// FileEntry Files[]; 108 /// }; 109 /// 110 /// The file table starts with a 32 bit count of the number of files that are 111 /// used in all of the function info, followed by that number of FileEntry 112 /// structures. The file table is aligned to a 4 byte boundary, Each file in 113 /// the file table is represented with a FileEntry structure. 114 /// See "llvm/DebugInfo/GSYM/FileEntry.h" for details. 115 /// 116 /// STRING TABLE 117 /// 118 /// The string table follows the file table in stand alone GSYM files and 119 /// contains all strings for everything contained in the GSYM file. Any string 120 /// data should be added to the string table and any references to strings 121 /// inside GSYM information must be stored as 32 bit string table offsets into 122 /// this string table. The string table always starts with an empty string at 123 /// offset zero and is followed by any strings needed by the GSYM information. 124 /// The start of the string table is not aligned to any boundary. 125 /// 126 /// FUNCTION INFO DATA 127 /// 128 /// The function info data is the payload that contains information about the 129 /// address that is being looked up. It contains all of the encoded 130 /// FunctionInfo objects. Each encoded FunctionInfo's data is pointed to by an 131 /// entry in the Function Info Offsets Table. For details on the exact encoding 132 /// of FunctionInfo objects, see "llvm/DebugInfo/GSYM/FunctionInfo.h". 133 class GsymCreator { 134 // Private member variables require Mutex protections 135 mutable std::recursive_mutex Mutex; 136 std::vector<FunctionInfo> Funcs; 137 StringTableBuilder StrTab; 138 DenseMap<llvm::gsym::FileEntry, uint32_t> FileEntryToIndex; 139 std::vector<llvm::gsym::FileEntry> Files; 140 std::vector<uint8_t> UUID; 141 bool Finalized = false; 142 143 public: 144 145 GsymCreator(); 146 147 /// Save a GSYM file to a stand alone file. 148 /// 149 /// \param Path The file path to save the GSYM file to. 150 /// \param ByteOrder The endianness to use when saving the file. 151 /// \returns An error object that indicates success or failure of the save. 152 llvm::Error save(StringRef Path, llvm::support::endianness ByteOrder) const; 153 154 /// Encode a GSYM into the file writer stream at the current position. 155 /// 156 /// \param O The stream to save the binary data to 157 /// \returns An error object that indicates success or failure of the save. 158 llvm::Error encode(FileWriter &O) const; 159 160 /// Insert a string into the GSYM string table. 161 /// 162 /// All strings used by GSYM files must be uniqued by adding them to this 163 /// string pool and using the returned offset for any string values. 164 /// 165 /// \param S The string to insert into the string table. 166 /// \returns The unique 32 bit offset into the string table. 167 uint32_t insertString(StringRef S); 168 169 /// Insert a file into this GSYM creator. 170 /// 171 /// Inserts a file by adding a FileEntry into the "Files" member variable if 172 /// the file has not already been added. The file path is split into 173 /// directory and filename which are both added to the string table. This 174 /// allows paths to be stored efficiently by reusing the directories that are 175 /// common between multiple files. 176 /// 177 /// \param Path The path to the file to insert. 178 /// \param Style The path style for the "Path" parameter. 179 /// \returns The unique file index for the inserted file. 180 uint32_t insertFile(StringRef Path, 181 sys::path::Style Style = sys::path::Style::native); 182 183 /// Add a function info to this GSYM creator. 184 /// 185 /// All information in the FunctionInfo object must use the 186 /// GsymCreator::insertString(...) function when creating string table 187 /// offsets for names and other strings. 188 /// 189 /// \param FI The function info object to emplace into our functions list. 190 void addFunctionInfo(FunctionInfo &&FI); 191 192 /// Finalize the data in the GSYM creator prior to saving the data out. 193 /// 194 /// Finalize must be called after all FunctionInfo objects have been added 195 /// and before GsymCreator::save() is called. 196 /// 197 /// \param OS Output stream to report duplicate function infos, overlapping 198 /// function infos, and function infos that were merged or removed. 199 /// \returns An error object that indicates success or failure of the 200 /// finalize. 201 llvm::Error finalize(llvm::raw_ostream &OS); 202 203 /// Set the UUID value. 204 /// 205 /// \param UUIDBytes The new UUID bytes. 206 void setUUID(llvm::ArrayRef<uint8_t> UUIDBytes) { 207 UUID.assign(UUIDBytes.begin(), UUIDBytes.end()); 208 } 209 210 /// Thread safe iteration over all function infos. 211 /// 212 /// \param Callback A callback function that will get called with each 213 /// FunctionInfo. If the callback returns false, stop iterating. 214 void forEachFunctionInfo( 215 std::function<bool(FunctionInfo &)> const &Callback); 216 217 /// Thread safe const iteration over all function infos. 218 /// 219 /// \param Callback A callback function that will get called with each 220 /// FunctionInfo. If the callback returns false, stop iterating. 221 void forEachFunctionInfo( 222 std::function<bool(const FunctionInfo &)> const &Callback) const; 223 224 }; 225 226 } // namespace gsym 227 } // namespace llvm 228 229 #endif // #ifndef LLVM_DEBUGINFO_GSYM_GSYMCREATOR_H 230