xref: /freebsd-src/contrib/llvm-project/llvm/lib/DebugInfo/GSYM/Header.cpp (revision 5b27928474e6a4103d65b347544705c40c9618fd)
1*8bcb0991SDimitry Andric //===- Header.cpp -----------------------------------------------*- C++ -*-===//
2*8bcb0991SDimitry Andric //
3*8bcb0991SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*8bcb0991SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*8bcb0991SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*8bcb0991SDimitry Andric //
7*8bcb0991SDimitry Andric //===----------------------------------------------------------------------===//
8*8bcb0991SDimitry Andric 
9*8bcb0991SDimitry Andric #include "llvm/DebugInfo/GSYM/Header.h"
10*8bcb0991SDimitry Andric #include "llvm/DebugInfo/GSYM/FileWriter.h"
11*8bcb0991SDimitry Andric #include "llvm/Support/DataExtractor.h"
12*8bcb0991SDimitry Andric #include "llvm/Support/Format.h"
13*8bcb0991SDimitry Andric #include "llvm/Support/raw_ostream.h"
14*8bcb0991SDimitry Andric 
15*8bcb0991SDimitry Andric #define HEX8(v) llvm::format_hex(v, 4)
16*8bcb0991SDimitry Andric #define HEX16(v) llvm::format_hex(v, 6)
17*8bcb0991SDimitry Andric #define HEX32(v) llvm::format_hex(v, 10)
18*8bcb0991SDimitry Andric #define HEX64(v) llvm::format_hex(v, 18)
19*8bcb0991SDimitry Andric 
20*8bcb0991SDimitry Andric using namespace llvm;
21*8bcb0991SDimitry Andric using namespace gsym;
22*8bcb0991SDimitry Andric 
operator <<(raw_ostream & OS,const Header & H)23*8bcb0991SDimitry Andric raw_ostream &llvm::gsym::operator<<(raw_ostream &OS, const Header &H) {
24*8bcb0991SDimitry Andric   OS << "Header:\n";
25*8bcb0991SDimitry Andric   OS << "  Magic        = " << HEX32(H.Magic) << "\n";
26*8bcb0991SDimitry Andric   OS << "  Version      = " << HEX16(H.Version) << '\n';
27*8bcb0991SDimitry Andric   OS << "  AddrOffSize  = " << HEX8(H.AddrOffSize) << '\n';
28*8bcb0991SDimitry Andric   OS << "  UUIDSize     = " << HEX8(H.UUIDSize) << '\n';
29*8bcb0991SDimitry Andric   OS << "  BaseAddress  = " << HEX64(H.BaseAddress) << '\n';
30*8bcb0991SDimitry Andric   OS << "  NumAddresses = " << HEX32(H.NumAddresses) << '\n';
31*8bcb0991SDimitry Andric   OS << "  StrtabOffset = " << HEX32(H.StrtabOffset) << '\n';
32*8bcb0991SDimitry Andric   OS << "  StrtabSize   = " << HEX32(H.StrtabSize) << '\n';
33*8bcb0991SDimitry Andric   OS << "  UUID         = ";
34*8bcb0991SDimitry Andric   for (uint8_t I = 0; I < H.UUIDSize; ++I)
35*8bcb0991SDimitry Andric     OS << format_hex_no_prefix(H.UUID[I], 2);
36*8bcb0991SDimitry Andric   OS << '\n';
37*8bcb0991SDimitry Andric   return OS;
38*8bcb0991SDimitry Andric }
39*8bcb0991SDimitry Andric 
40*8bcb0991SDimitry Andric /// Check the header and detect any errors.
checkForError() const41*8bcb0991SDimitry Andric llvm::Error Header::checkForError() const {
42*8bcb0991SDimitry Andric   if (Magic != GSYM_MAGIC)
43*8bcb0991SDimitry Andric     return createStringError(std::errc::invalid_argument,
44*8bcb0991SDimitry Andric                              "invalid GSYM magic 0x%8.8x", Magic);
45*8bcb0991SDimitry Andric   if (Version != GSYM_VERSION)
46*8bcb0991SDimitry Andric     return createStringError(std::errc::invalid_argument,
47*8bcb0991SDimitry Andric                              "unsupported GSYM version %u", Version);
48*8bcb0991SDimitry Andric   switch (AddrOffSize) {
49*8bcb0991SDimitry Andric     case 1: break;
50*8bcb0991SDimitry Andric     case 2: break;
51*8bcb0991SDimitry Andric     case 4: break;
52*8bcb0991SDimitry Andric     case 8: break;
53*8bcb0991SDimitry Andric     default:
54*8bcb0991SDimitry Andric         return createStringError(std::errc::invalid_argument,
55*8bcb0991SDimitry Andric                                  "invalid address offset size %u",
56*8bcb0991SDimitry Andric                                  AddrOffSize);
57*8bcb0991SDimitry Andric   }
58*8bcb0991SDimitry Andric   if (UUIDSize > GSYM_MAX_UUID_SIZE)
59*8bcb0991SDimitry Andric     return createStringError(std::errc::invalid_argument,
60*8bcb0991SDimitry Andric                              "invalid UUID size %u", UUIDSize);
61*8bcb0991SDimitry Andric   return Error::success();
62*8bcb0991SDimitry Andric }
63*8bcb0991SDimitry Andric 
decode(DataExtractor & Data)64*8bcb0991SDimitry Andric llvm::Expected<Header> Header::decode(DataExtractor &Data) {
65*8bcb0991SDimitry Andric   uint64_t Offset = 0;
66*8bcb0991SDimitry Andric   // The header is stored as a single blob of data that has a fixed byte size.
67*8bcb0991SDimitry Andric   if (!Data.isValidOffsetForDataOfSize(Offset, sizeof(Header)))
68*8bcb0991SDimitry Andric     return createStringError(std::errc::invalid_argument,
69*8bcb0991SDimitry Andric                              "not enough data for a gsym::Header");
70*8bcb0991SDimitry Andric   Header H;
71*8bcb0991SDimitry Andric   H.Magic = Data.getU32(&Offset);
72*8bcb0991SDimitry Andric   H.Version = Data.getU16(&Offset);
73*8bcb0991SDimitry Andric   H.AddrOffSize = Data.getU8(&Offset);
74*8bcb0991SDimitry Andric   H.UUIDSize = Data.getU8(&Offset);
75*8bcb0991SDimitry Andric   H.BaseAddress = Data.getU64(&Offset);
76*8bcb0991SDimitry Andric   H.NumAddresses = Data.getU32(&Offset);
77*8bcb0991SDimitry Andric   H.StrtabOffset = Data.getU32(&Offset);
78*8bcb0991SDimitry Andric   H.StrtabSize = Data.getU32(&Offset);
79*8bcb0991SDimitry Andric   Data.getU8(&Offset, H.UUID, GSYM_MAX_UUID_SIZE);
80*8bcb0991SDimitry Andric   if (llvm::Error Err = H.checkForError())
81*8bcb0991SDimitry Andric     return std::move(Err);
82*8bcb0991SDimitry Andric   return H;
83*8bcb0991SDimitry Andric }
84*8bcb0991SDimitry Andric 
encode(FileWriter & O) const85*8bcb0991SDimitry Andric llvm::Error Header::encode(FileWriter &O) const {
86*8bcb0991SDimitry Andric   // Users must verify the Header is valid prior to calling this funtion.
87*8bcb0991SDimitry Andric   if (llvm::Error Err = checkForError())
88*8bcb0991SDimitry Andric     return Err;
89*8bcb0991SDimitry Andric   O.writeU32(Magic);
90*8bcb0991SDimitry Andric   O.writeU16(Version);
91*8bcb0991SDimitry Andric   O.writeU8(AddrOffSize);
92*8bcb0991SDimitry Andric   O.writeU8(UUIDSize);
93*8bcb0991SDimitry Andric   O.writeU64(BaseAddress);
94*8bcb0991SDimitry Andric   O.writeU32(NumAddresses);
95*8bcb0991SDimitry Andric   O.writeU32(StrtabOffset);
96*8bcb0991SDimitry Andric   O.writeU32(StrtabSize);
97*8bcb0991SDimitry Andric   O.writeData(llvm::ArrayRef<uint8_t>(UUID));
98*8bcb0991SDimitry Andric   return Error::success();
99*8bcb0991SDimitry Andric }
100*8bcb0991SDimitry Andric 
operator ==(const Header & LHS,const Header & RHS)101*8bcb0991SDimitry Andric bool llvm::gsym::operator==(const Header &LHS, const Header &RHS) {
102*8bcb0991SDimitry Andric   return LHS.Magic == RHS.Magic && LHS.Version == RHS.Version &&
103*8bcb0991SDimitry Andric       LHS.AddrOffSize == RHS.AddrOffSize && LHS.UUIDSize == RHS.UUIDSize &&
104*8bcb0991SDimitry Andric       LHS.BaseAddress == RHS.BaseAddress &&
105*8bcb0991SDimitry Andric       LHS.NumAddresses == RHS.NumAddresses &&
106*8bcb0991SDimitry Andric       LHS.StrtabOffset == RHS.StrtabOffset &&
107*8bcb0991SDimitry Andric       LHS.StrtabSize == RHS.StrtabSize &&
108*8bcb0991SDimitry Andric       memcmp(LHS.UUID, RHS.UUID, LHS.UUIDSize) == 0;
109*8bcb0991SDimitry Andric }
110