Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit c3cf101

Browse files
committed
Add GsymCreator and GsymReader.
This patch adds the ability to create GSYM files with GsymCreator, and read them with GsymReader. Full testing has been added for both new classes. This patch differs from the original patch https://reviews.llvm.org/D53379 in that is uses a StringTableBuilder class from llvm instead of a custom version. Support for big and little endian files has been added. If the endianness matches the current host, we use efficient extraction for the header, address table and address info offset tables. Differential Revision: https://reviews.llvm.org/D68744 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@374381 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 5d52d6a commit c3cf101

File tree

11 files changed

+1295
-23
lines changed

11 files changed

+1295
-23
lines changed

include/llvm/DebugInfo/GSYM/FileWriter.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ class FileWriter {
109109
/// file position.
110110
uint64_t tell();
111111

112+
llvm::raw_pwrite_stream &get_stream() {
113+
return OS;
114+
}
115+
112116
private:
113117
FileWriter(const FileWriter &rhs) = delete;
114118
void operator=(const FileWriter &rhs) = delete;
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
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 alinged to
86+
/// Header.AddrOffSize alignement 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 algined 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+
llvm::sys::path::Style = llvm::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

0 commit comments

Comments
 (0)