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 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. 41*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 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 85*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 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