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