blob: 5876c7b4af1ba02d2b048c960df0ee8f4c9f1dba [file]
//===- GsymCreatorV1.cpp --------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/GSYM/GsymCreatorV1.h"
#include "llvm/DebugInfo/GSYM/FileWriter.h"
#include "llvm/DebugInfo/GSYM/Header.h"
#include <cassert>
using namespace llvm;
using namespace gsym;
uint64_t GsymCreatorV1::calculateHeaderAndTableSize() const {
uint64_t Size = sizeof(Header);
const size_t NumFuncs = Funcs.size();
Size += NumFuncs * getAddressOffsetSize();
Size += NumFuncs * sizeof(uint32_t);
Size += Files.size() * FileEntry::getEncodedSize(getStringOffsetSize());
Size += StrTab.getSize();
return Size;
}
llvm::Error GsymCreatorV1::encode(FileWriter &O) const {
std::lock_guard<std::mutex> Guard(Mutex);
std::optional<uint64_t> BaseAddress;
if (auto Err = validateForEncoding(BaseAddress))
return Err;
Header Hdr;
Hdr.Magic = GSYM_MAGIC;
Hdr.Version = Header::getVersion();
Hdr.AddrOffSize = getAddressOffsetSize();
Hdr.UUIDSize = static_cast<uint8_t>(UUID.size());
Hdr.BaseAddress = *BaseAddress;
Hdr.NumAddresses = static_cast<uint32_t>(Funcs.size());
Hdr.StrtabOffset = 0;
Hdr.StrtabSize = 0;
memset(Hdr.UUID, 0, sizeof(Hdr.UUID));
if (UUID.size() > sizeof(Hdr.UUID))
return createStringError(std::errc::invalid_argument,
"invalid UUID size %u", (uint32_t)UUID.size());
if (UUID.size() > 0)
memcpy(Hdr.UUID, UUID.data(), UUID.size());
llvm::Error Err = Hdr.encode(O);
if (Err)
return Err;
O.setStringOffsetSize(getStringOffsetSize());
encodeAddrOffsets(O, Hdr.AddrOffSize, Hdr.BaseAddress);
O.alignTo(4);
const uint64_t AddrInfoOffsetsOffset = O.tell();
for (size_t i = 0, n = Funcs.size(); i < n; ++i)
O.writeU32(0);
O.alignTo(4);
if (auto Err = encodeFileTable(O))
return Err;
const uint64_t StrtabOffset = O.tell();
StrTab.write(O.get_stream());
const uint64_t StrtabSize = O.tell() - StrtabOffset;
std::vector<uint32_t> AddrInfoOffsets;
if (StrtabSize > UINT32_MAX) {
return createStringError(std::errc::invalid_argument,
"string table size exceeded 32-bit max");
}
for (const auto &FuncInfo : Funcs) {
if (Expected<uint64_t> OffsetOrErr = FuncInfo.encode(O)) {
uint64_t Offset = OffsetOrErr.get();
if (Offset > UINT32_MAX) {
return createStringError(std::errc::invalid_argument,
"address info offset exceeded 32-bit max");
}
AddrInfoOffsets.push_back(Offset);
} else
return OffsetOrErr.takeError();
}
O.fixup32((uint32_t)StrtabOffset, offsetof(Header, StrtabOffset));
O.fixup32((uint32_t)StrtabSize, offsetof(Header, StrtabSize));
uint64_t Offset = 0;
for (auto AddrInfoOffset : AddrInfoOffsets) {
O.fixup32(AddrInfoOffset, AddrInfoOffsetsOffset + Offset);
Offset += 4;
}
return ErrorSuccess();
}