1//===- GsymCreatorV1.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#include "llvm/DebugInfo/GSYM/GsymCreatorV1.h"
9#include "llvm/DebugInfo/GSYM/FileWriter.h"
10#include "llvm/DebugInfo/GSYM/Header.h"
11
12#include <cassert>
13
14using namespace llvm;
15using namespace gsym;
16
17uint64_t GsymCreatorV1::calculateHeaderAndTableSize() const {
18 uint64_t Size = sizeof(Header);
19 const size_t NumFuncs = Funcs.size();
20 Size += NumFuncs * getAddressOffsetSize();
21 Size += NumFuncs * sizeof(uint32_t);
22 Size += Files.size() * FileEntry::getEncodedSize(StringOffsetSize: getStringOffsetSize());
23 Size += StrTab.getSize();
24 return Size;
25}
26
27llvm::Error GsymCreatorV1::encode(FileWriter &O) const {
28 std::lock_guard<std::mutex> Guard(Mutex);
29 std::optional<uint64_t> BaseAddress;
30 if (auto Err = validateForEncoding(BaseAddr&: BaseAddress))
31 return Err;
32 Header Hdr;
33 Hdr.Magic = GSYM_MAGIC;
34 Hdr.Version = Header::getVersion();
35 Hdr.AddrOffSize = getAddressOffsetSize();
36 Hdr.UUIDSize = static_cast<uint8_t>(UUID.size());
37 Hdr.BaseAddress = *BaseAddress;
38 Hdr.NumAddresses = static_cast<uint32_t>(Funcs.size());
39 Hdr.StrtabOffset = 0;
40 Hdr.StrtabSize = 0;
41 memset(s: Hdr.UUID, c: 0, n: sizeof(Hdr.UUID));
42 if (UUID.size() > sizeof(Hdr.UUID))
43 return createStringError(EC: std::errc::invalid_argument,
44 Fmt: "invalid UUID size %u", Vals: (uint32_t)UUID.size());
45 if (UUID.size() > 0)
46 memcpy(dest: Hdr.UUID, src: UUID.data(), n: UUID.size());
47 llvm::Error Err = Hdr.encode(O);
48 if (Err)
49 return Err;
50
51 O.setStringOffsetSize(getStringOffsetSize());
52 encodeAddrOffsets(O, AddrOffSize: Hdr.AddrOffSize, BaseAddr: Hdr.BaseAddress);
53
54 O.alignTo(Align: 4);
55 const uint64_t AddrInfoOffsetsOffset = O.tell();
56 for (size_t i = 0, n = Funcs.size(); i < n; ++i)
57 O.writeU32(Value: 0);
58
59 O.alignTo(Align: 4);
60 if (auto Err = encodeFileTable(O))
61 return Err;
62
63 const uint64_t StrtabOffset = O.tell();
64 StrTab.write(OS&: O.get_stream());
65 const uint64_t StrtabSize = O.tell() - StrtabOffset;
66 std::vector<uint32_t> AddrInfoOffsets;
67
68 if (StrtabSize > UINT32_MAX) {
69 return createStringError(EC: std::errc::invalid_argument,
70 Fmt: "string table size exceeded 32-bit max");
71 }
72
73 for (const auto &FuncInfo : Funcs) {
74 if (Expected<uint64_t> OffsetOrErr = FuncInfo.encode(O)) {
75 uint64_t Offset = OffsetOrErr.get();
76 if (Offset > UINT32_MAX) {
77 return createStringError(EC: std::errc::invalid_argument,
78 Fmt: "address info offset exceeded 32-bit max");
79 }
80 AddrInfoOffsets.push_back(x: Offset);
81 } else
82 return OffsetOrErr.takeError();
83 }
84 O.fixup32(Value: (uint32_t)StrtabOffset, offsetof(Header, StrtabOffset));
85 O.fixup32(Value: (uint32_t)StrtabSize, offsetof(Header, StrtabSize));
86
87 uint64_t Offset = 0;
88 for (auto AddrInfoOffset : AddrInfoOffsets) {
89 O.fixup32(Value: AddrInfoOffset, Offset: AddrInfoOffsetsOffset + Offset);
90 Offset += 4;
91 }
92 return ErrorSuccess();
93}
94