1//===- GsymReaderV2.cpp ---------------------------------------------------===//
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#include "llvm/DebugInfo/GSYM/GsymReaderV2.h"
10
11#include <assert.h>
12#include <inttypes.h>
13
14#include "llvm/ADT/STLExtras.h"
15#include "llvm/DebugInfo/GSYM/GlobalData.h"
16#include "llvm/DebugInfo/GSYM/GsymDataExtractor.h"
17#include "llvm/Support/FormatVariadic.h"
18#include "llvm/Support/MemoryBuffer.h"
19
20using namespace llvm;
21using namespace gsym;
22
23GsymReaderV2::GsymReaderV2(std::unique_ptr<MemoryBuffer> Buffer,
24 llvm::endianness Endian)
25 : GsymReader(std::move(Buffer), Endian) {}
26
27/// For V2 file layout, see HeaderV2.h
28llvm::Error GsymReaderV2::parseHeaderAndGlobalDataEntries() {
29 if (auto Err = parseHeader(OutHdr&: Hdr, OutSwappedHdr&: SwappedHdr))
30 return Err;
31 return parseGlobalDataEntries(Offset: HeaderV2::getEncodedSize());
32}
33
34void GsymReaderV2::dump(raw_ostream &OS) {
35 OS << *Hdr << "\n";
36
37 // Print GlobalData entries.
38 OS << "Global Data Sections:\n";
39 OS << "TYPE FILE OFFSET FILE SIZE\n";
40 OS << "=============== ================== ==================\n";
41 /// Re-parse the GlobalData entries to ensure we show the GlobalData
42 /// in the exact order it appears in the GSYM data.
43 const StringRef Buf = MemBuffer->getBuffer();
44 const uint64_t BufSize = Buf.size();
45 GsymDataExtractor Data(Buf, isLittleEndian());
46 uint64_t Offset = HeaderV2::getEncodedSize();
47 while (Offset + sizeof(GlobalData) <= BufSize) {
48 auto GDOrErr = GlobalData::decode(GsymData&: Data, Offset);
49 assert(GDOrErr && "GlobalData::decode() should not fail");
50 const GlobalData &GD = *GDOrErr;
51
52 OS << formatv(Fmt: "{0,-15} ", Vals: getNameForGlobalInfoType(Type: GD.Type).data())
53 << HEX64(GD.FileOffset) << " " << HEX64(GD.FileSize) << "\n";
54
55 // Stop printing after the end of list entry.
56 if (GD.Type == GlobalInfoType::EndOfList)
57 break;
58 }
59 OS << "\n";
60
61 // Print UUID if present.
62 if (auto UUIDBytes = getOptionalGlobalDataBytes(Type: GlobalInfoType::UUID)) {
63 OS << "UUID:\n";
64 for (uint8_t Byte : *UUIDBytes)
65 OS << format_hex_no_prefix(N: Byte, Width: 2);
66 OS << "\n\n";
67 }
68
69 OS << "Address Table:\n";
70 OS << "INDEX OFFSET ";
71 switch (getAddressOffsetSize()) {
72 case 1:
73 OS << "8 ";
74 break;
75 case 2:
76 OS << "16";
77 break;
78 case 4:
79 OS << "32";
80 break;
81 case 8:
82 OS << "64";
83 break;
84 default:
85 OS << "??";
86 break;
87 }
88 OS << " (ADDRESS 64)\n";
89 OS << "====== ========================================\n";
90 for (uint32_t I = 0; I < getNumAddresses(); ++I) {
91 OS << formatv(Fmt: "[{0,4}] ", Vals&: I);
92 switch (getAddressOffsetSize()) {
93 case 1:
94 OS << HEX8(getAddrOffsets<uint8_t>()[I]);
95 break;
96 case 2:
97 OS << HEX16(getAddrOffsets<uint16_t>()[I]);
98 break;
99 case 4:
100 OS << HEX32(getAddrOffsets<uint32_t>()[I]);
101 break;
102 case 8:
103 OS << HEX32(getAddrOffsets<uint64_t>()[I]);
104 break;
105 default:
106 break;
107 }
108 OS << " (" << HEX64(*getAddress(I)) << ")\n";
109 }
110 OS << "\nAddress Info Offsets:\n";
111 OS << "INDEX OFFSET 64 (FILE OFFSET 64)\n";
112 OS << "====== ========================================\n";
113 for (uint32_t I = 0; I < getNumAddresses(); ++I) {
114 uint64_t RelOffset = I * getAddressInfoOffsetSize();
115 uint64_t RelValue =
116 AddrInfoOffsetsData.getUnsigned(offset_ptr: &RelOffset, byte_size: getAddressInfoOffsetSize());
117 OS << formatv(Fmt: "[{0,4}] ", Vals&: I) << HEX64(RelValue) << " ("
118 << HEX64(*getAddressInfoOffset(I)) << ")\n";
119 }
120 OS << "\nFiles:\n";
121 OS << "INDEX DIRECTORY BASENAME PATH\n";
122 OS << "====== ========== ========== "
123 "========================================\n";
124 // Since we don't store the total number of files in the file table, loop
125 // until we get a null entry which means the index is out of range.
126 for (uint32_t I = 0;; ++I) {
127 auto FE = getFile(Index: I);
128 if (!FE)
129 break;
130 OS << formatv(Fmt: "[{0,4}] ", Vals&: I) << HEX32(FE->Dir) << ' ' << HEX32(FE->Base)
131 << ' ';
132 dump(OS, FE);
133 OS << "\n";
134 }
135 OS << "\n";
136 gsym::dump(OS, S: StrTab, StringOffsetSize: 8);
137 OS << "\n";
138
139 for (uint32_t I = 0; I < getNumAddresses(); ++I) {
140 OS << "FunctionInfo @ " << HEX32(*getAddressInfoOffset(I)) << ": ";
141 if (auto FI = getFunctionInfoAtIndex(AddrIdx: I))
142 dump(OS, FI: *FI);
143 else
144 logAllUnhandledErrors(E: FI.takeError(), OS, ErrorBanner: "FunctionInfo:");
145 }
146}
147