1 //===- Header.cpp -----------------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/DebugInfo/GSYM/Header.h"
10 #include "llvm/DebugInfo/GSYM/FileWriter.h"
11 #include "llvm/Support/DataExtractor.h"
12 #include "llvm/Support/Format.h"
13 #include "llvm/Support/raw_ostream.h"
15 #define HEX8(v) llvm::format_hex(v, 4)
16 #define HEX16(v) llvm::format_hex(v, 6)
17 #define HEX32(v) llvm::format_hex(v, 10)
18 #define HEX64(v) llvm::format_hex(v, 18)
23 raw_ostream
&llvm::gsym::operator<<(raw_ostream
&OS
, const Header
&H
) {
25 OS
<< " Magic = " << HEX32(H
.Magic
) << "\n";
26 OS
<< " Version = " << HEX16(H
.Version
) << '\n';
27 OS
<< " AddrOffSize = " << HEX8(H
.AddrOffSize
) << '\n';
28 OS
<< " UUIDSize = " << HEX8(H
.UUIDSize
) << '\n';
29 OS
<< " BaseAddress = " << HEX64(H
.BaseAddress
) << '\n';
30 OS
<< " NumAddresses = " << HEX32(H
.NumAddresses
) << '\n';
31 OS
<< " StrtabOffset = " << HEX32(H
.StrtabOffset
) << '\n';
32 OS
<< " StrtabSize = " << HEX32(H
.StrtabSize
) << '\n';
34 for (uint8_t I
= 0; I
< H
.UUIDSize
; ++I
)
35 OS
<< format_hex_no_prefix(H
.UUID
[I
], 2);
40 /// Check the header and detect any errors.
41 llvm::Error
Header::checkForError() const {
42 if (Magic
!= GSYM_MAGIC
)
43 return createStringError(std::errc::invalid_argument
,
44 "invalid GSYM magic 0x%8.8x", Magic
);
45 if (Version
!= GSYM_VERSION
)
46 return createStringError(std::errc::invalid_argument
,
47 "unsupported GSYM version %u", Version
);
48 switch (AddrOffSize
) {
54 return createStringError(std::errc::invalid_argument
,
55 "invalid address offset size %u",
58 if (UUIDSize
> GSYM_MAX_UUID_SIZE
)
59 return createStringError(std::errc::invalid_argument
,
60 "invalid UUID size %u", UUIDSize
);
61 return Error::success();
64 llvm::Expected
<Header
> Header::decode(DataExtractor
&Data
) {
66 // The header is stored as a single blob of data that has a fixed byte size.
67 if (!Data
.isValidOffsetForDataOfSize(Offset
, sizeof(Header
)))
68 return createStringError(std::errc::invalid_argument
,
69 "not enough data for a gsym::Header");
71 H
.Magic
= Data
.getU32(&Offset
);
72 H
.Version
= Data
.getU16(&Offset
);
73 H
.AddrOffSize
= Data
.getU8(&Offset
);
74 H
.UUIDSize
= Data
.getU8(&Offset
);
75 H
.BaseAddress
= Data
.getU64(&Offset
);
76 H
.NumAddresses
= Data
.getU32(&Offset
);
77 H
.StrtabOffset
= Data
.getU32(&Offset
);
78 H
.StrtabSize
= Data
.getU32(&Offset
);
79 Data
.getU8(&Offset
, H
.UUID
, GSYM_MAX_UUID_SIZE
);
80 if (llvm::Error Err
= H
.checkForError())
81 return std::move(Err
);
85 llvm::Error
Header::encode(FileWriter
&O
) const {
86 // Users must verify the Header is valid prior to calling this funtion.
87 if (llvm::Error Err
= checkForError())
91 O
.writeU8(AddrOffSize
);
93 O
.writeU64(BaseAddress
);
94 O
.writeU32(NumAddresses
);
95 O
.writeU32(StrtabOffset
);
96 O
.writeU32(StrtabSize
);
97 O
.writeData(llvm::ArrayRef
<uint8_t>(UUID
));
98 return Error::success();
101 bool llvm::gsym::operator==(const Header
&LHS
, const Header
&RHS
) {
102 return LHS
.Magic
== RHS
.Magic
&& LHS
.Version
== RHS
.Version
&&
103 LHS
.AddrOffSize
== RHS
.AddrOffSize
&& LHS
.UUIDSize
== RHS
.UUIDSize
&&
104 LHS
.BaseAddress
== RHS
.BaseAddress
&&
105 LHS
.NumAddresses
== RHS
.NumAddresses
&&
106 LHS
.StrtabOffset
== RHS
.StrtabOffset
&&
107 LHS
.StrtabSize
== RHS
.StrtabSize
&&
108 memcmp(LHS
.UUID
, RHS
.UUID
, LHS
.UUIDSize
) == 0;