Go to the documentation of this file.
40 std::lock_guard<std::recursive_mutex> Guard(
Mutex);
41 const auto NextIndex = Files.size();
43 auto R = FileEntryToIndex.
insert(std::make_pair(FE, NextIndex));
45 Files.emplace_back(FE);
46 return R.first->second;
60 std::lock_guard<std::recursive_mutex> Guard(
Mutex);
63 "no functions to encode");
66 "GsymCreator wasn't finalized prior to encoding");
68 if (Funcs.size() > UINT32_MAX)
70 "too many FunctionInfos");
72 const uint64_t MinAddr = BaseAddress ? *BaseAddress : Funcs.front().startAddress();
73 const uint64_t MaxAddr = Funcs.back().startAddress();
74 const uint64_t AddrDelta = MaxAddr - MinAddr;
84 memset(Hdr.
UUID, 0,
sizeof(Hdr.
UUID));
89 if (AddrDelta <= UINT8_MAX)
91 else if (AddrDelta <= UINT16_MAX)
93 else if (AddrDelta <= UINT32_MAX)
107 for (
const auto &FuncInfo : Funcs) {
108 uint64_t AddrOffset = FuncInfo.startAddress() - Hdr.
BaseAddress;
110 case 1:
O.writeU8(
static_cast<uint8_t
>(AddrOffset));
break;
111 case 2:
O.writeU16(
static_cast<uint16_t>(AddrOffset));
break;
112 case 4:
O.writeU32(
static_cast<uint32_t>(AddrOffset));
break;
113 case 8:
O.writeU64(AddrOffset);
break;
119 const off_t AddrInfoOffsetsOffset =
O.tell();
120 for (
size_t i = 0,
n = Funcs.size();
i <
n; ++
i)
126 assert(Files[0].Dir == 0);
127 assert(Files[0].Base == 0);
128 size_t NumFiles = Files.size();
129 if (NumFiles > UINT32_MAX)
132 O.writeU32(
static_cast<uint32_t>(NumFiles));
133 for (
auto File: Files) {
134 O.writeU32(
File.Dir);
135 O.writeU32(
File.Base);
139 const off_t StrtabOffset =
O.tell();
140 StrTab.
write(
O.get_stream());
141 const off_t StrtabSize =
O.tell() - StrtabOffset;
142 std::vector<uint32_t> AddrInfoOffsets;
145 for (
const auto &FuncInfo : Funcs) {
147 AddrInfoOffsets.push_back(OffsetOrErr.get());
149 return OffsetOrErr.takeError();
157 for (
auto AddrInfoOffset: AddrInfoOffsets) {
158 O.fixup32(AddrInfoOffset, AddrInfoOffsetsOffset +
Offset);
165 std::lock_guard<std::recursive_mutex> Guard(
Mutex);
168 "already finalized");
197 auto NumBefore = Funcs.size();
198 auto Curr = Funcs.begin();
199 auto Prev = Funcs.end();
200 while (Curr != Funcs.end()) {
203 if (Prev != Funcs.end()) {
204 if (Prev->Range.intersects(Curr->Range)) {
206 if (Prev->Range == Curr->Range) {
211 if (*Prev == *Curr) {
213 OS <<
"warning: duplicate function info entries for range: "
214 << Curr->Range <<
'\n';
215 Curr = Funcs.erase(Prev);
217 if (!Prev->hasRichInfo() && Curr->hasRichInfo()) {
220 Curr = Funcs.erase(Prev);
222 OS <<
"warning: same address range contains different debug "
223 <<
"info. Removing:\n"
224 << *Prev <<
"\nIn favor of this one:\n"
226 Curr = Funcs.erase(Prev);
231 OS <<
"warning: function ranges overlap:\n"
235 }
else if (Prev->Range.size() == 0 &&
236 Curr->Range.contains(Prev->Range.Start)) {
237 OS <<
"warning: removing symbol:\n"
238 << *Prev <<
"\nKeeping:\n"
240 Curr = Funcs.erase(Prev);
243 if (Curr == Funcs.end())
253 if (!Funcs.empty() && Funcs.back().Range.size() == 0 && ValidTextRanges) {
254 if (
auto Range = ValidTextRanges->getRangeThatContains(
255 Funcs.back().Range.Start)) {
256 Funcs.back().Range.End = Range->End;
259 OS <<
"Pruned " << NumBefore - Funcs.size() <<
" functions, ended with "
260 << Funcs.size() <<
" total\n";
267 std::lock_guard<std::recursive_mutex> Guard(
Mutex);
277 S = StringStorage.
insert(
S).first->getKey();
279 return StrTab.
add(
S);
283 std::lock_guard<std::recursive_mutex> Guard(
Mutex);
285 Funcs.emplace_back(FI);
290 std::lock_guard<std::recursive_mutex> Guard(
Mutex);
291 for (
auto &FI : Funcs) {
299 std::lock_guard<std::recursive_mutex> Guard(
Mutex);
300 for (
const auto &FI : Funcs) {
307 std::lock_guard<std::recursive_mutex> Guard(
Mutex);
313 return ValidTextRanges->contains(
Addr);
318 std::lock_guard<std::recursive_mutex> Guard(
Mutex);
This class represents lattice values for constants.
bool contains(StringRef S) const
Check if a string is contained in the string table.
void insert(AddressRange Range)
#define offsetof(TYPE, MEMBER)
static ErrorSuccess success()
Create a success value.
void finalizeInOrder()
Finalize the string table without reording it.
llvm::Error encode(FileWriter &O) const
Encode a GSYM into the file writer stream at the current position.
bool IsValidTextAddress(uint64_t Addr) const
Check if an address is a valid code address.
std::pair< typename Base::iterator, bool > insert(StringRef key)
Tagged union holding either a T or a Error.
constexpr uint32_t GSYM_MAGIC
constexpr uint32_t GSYM_VERSION
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
bool contains(uint64_t Addr) const
bool hasFunctionInfoForAddress(uint64_t Addr) const
Check if an address has already been added as a function info.
This class implements an extremely fast bulk output stream that can only output to a stream.
Function information in GSYM files encodes information for one contiguous address range.
A container which contains a StringRef plus a precomputed hash.
Subclass of Error for the sole purpose of identifying the success path in the type system.
A simplified binary data writer class that doesn't require targets, target definitions,...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StringRef parent_path(StringRef path, Style style=Style::native)
Get parent path.
<%struct.s * > cast struct s *S to sbyte *< sbyte * > sbyte uint cast struct s *agg result to sbyte *< sbyte * > sbyte uint cast struct s *memtmp to sbyte *< sbyte * > sbyte uint ret void llc ends up issuing two memcpy or custom lower memcpy(of small size) to be ldmia/stmia. I think option 2 is better but the current register allocator cannot allocate a chunk of registers at a time. A feasible temporary solution is to use specific physical registers at the lowering time for small(<
print Print MemDeps of function
std::pair< llvm::MachO::Target, std::string > UUID
void forEachFunctionInfo(std::function< bool(FunctionInfo &)> const &Callback)
Thread safe iteration over all function infos.
void write(raw_ostream &OS) const
size_t getNumFunctionInfos() const
Get the current number of FunctionInfo objects contained in this object.
StringRef - Represent a constant reference to a string, i.e.
void addFunctionInfo(FunctionInfo &&FI)
Add a function info to this GSYM creator.
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
uint32_t insertString(StringRef S, bool Copy=true)
Insert a string into the GSYM string table.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
A raw_ostream that writes to a file descriptor.
Files in GSYM are contained in FileEntry structs where we split the directory and basename into two d...
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Lightweight error class with error context and mandatory checking.
size_t add(CachedHashStringRef S)
Add a string to the builder.
void sort(IteratorTy Start, IteratorTy End)
Utility for building string tables with deduplicated suffixes.
uint32_t insertFile(StringRef Path, sys::path::Style Style=sys::path::Style::native)
Insert a file into this GSYM creator.
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
llvm::Error save(StringRef Path, llvm::support::endianness ByteOrder) const
Save a GSYM file to a stand alone file.
The same transformation can work with an even modulo with the addition of a and shrink the compare RHS by the same amount Unless the target supports that transformation probably isn t worthwhile The transformation can also easily be made to work with non zero equality for n
llvm::Error finalize(llvm::raw_ostream &OS)
Finalize the data in the GSYM creator prior to saving the data out.
Instrumentation for Order File