| //===- GsymReaderV1.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/GsymReaderV1.h" | |
| #include <assert.h> | |
| #include <inttypes.h> | |
| #include "llvm/DebugInfo/GSYM/GsymDataExtractor.h" | |
| #include "llvm/DebugInfo/GSYM/Header.h" | |
| #include "llvm/Support/FormatVariadic.h" | |
| #include "llvm/Support/MemoryBuffer.h" | |
| using namespace llvm; | |
| using namespace gsym; | |
| GsymReaderV1::GsymReaderV1(std::unique_ptr<MemoryBuffer> Buffer, | |
| llvm::endianness Endian) | |
| : GsymReader(std::move(Buffer), Endian) {} | |
| llvm::Error GsymReaderV1::parseHeaderAndGlobalDataEntries() { | |
| if (auto Err = parseHeader(Hdr, SwappedHdr)) | |
| return Err; | |
| // Compute section offsets from the fixed V1 layout and populate the | |
| // GlobalDataSections map. V1 sections are laid out sequentially: | |
| // [Header] [AddrOffsets] [AddrInfoOffsets] [FileTable] ... [StringTable] | |
| const StringRef Buf = MemBuffer->getBuffer(); | |
| const uint64_t NumAddrs = Hdr->NumAddresses; | |
| const uint8_t AddrOffSize = Hdr->AddrOffSize; | |
| // AddrOffsets | |
| uint64_t Offset = alignTo(sizeof(Header), AddrOffSize); | |
| uint64_t AddrOffsetsSize = NumAddrs * AddrOffSize; | |
| GlobalDataSections[GlobalInfoType::AddrOffsets] = { | |
| GlobalInfoType::AddrOffsets, Offset, AddrOffsetsSize}; | |
| Offset += AddrOffsetsSize; | |
| // AddrInfoOffsets | |
| Offset = alignTo(Offset, 4); | |
| uint64_t AddrInfoOffsetsSize = NumAddrs * Header::getAddressInfoOffsetSize(); | |
| GlobalDataSections[GlobalInfoType::AddrInfoOffsets] = { | |
| GlobalInfoType::AddrInfoOffsets, Offset, AddrInfoOffsetsSize}; | |
| Offset += AddrInfoOffsetsSize; | |
| // FileTable: read NumFiles to compute the size. | |
| GsymDataExtractor Data(Buf, isLittleEndian()); | |
| uint64_t FTOffset = Offset; | |
| uint32_t NumFiles = Data.getU32(&FTOffset); | |
| uint64_t FileTableSize = | |
| 4 + static_cast<uint64_t>(NumFiles) * | |
| FileEntry::getEncodedSize(Header::getStringOffsetSize()); | |
| GlobalDataSections[GlobalInfoType::FileTable] = {GlobalInfoType::FileTable, | |
| Offset, FileTableSize}; | |
| // StringTable: offset and size are in the header. | |
| GlobalDataSections[GlobalInfoType::StringTable] = { | |
| GlobalInfoType::StringTable, Hdr->StrtabOffset, Hdr->StrtabSize}; | |
| // FunctionInfo: starts after the string table and extends to end of file. | |
| const uint64_t FIOffset = Hdr->StrtabOffset + Hdr->StrtabSize; | |
| GlobalDataSections[GlobalInfoType::FunctionInfo] = { | |
| GlobalInfoType::FunctionInfo, FIOffset, Buf.size() - FIOffset}; | |
| return Error::success(); | |
| } | |
| void GsymReaderV1::dump(raw_ostream &OS) { | |
| OS << *Hdr << "\n"; | |
| OS << "Address Table:\n"; | |
| OS << "INDEX OFFSET"; | |
| switch (getAddressOffsetSize()) { | |
| case 1: | |
| OS << "8 "; | |
| break; | |
| case 2: | |
| OS << "16"; | |
| break; | |
| case 4: | |
| OS << "32"; | |
| break; | |
| case 8: | |
| OS << "64"; | |
| break; | |
| default: | |
| OS << "??"; | |
| break; | |
| } | |
| OS << " (ADDRESS)\n"; | |
| OS << "====== =============================== \n"; | |
| for (uint32_t I = 0; I < getNumAddresses(); ++I) { | |
| OS << formatv("[{0,4}] ", I); | |
| switch (getAddressOffsetSize()) { | |
| case 1: | |
| OS << HEX8(getAddrOffsets<uint8_t>()[I]); | |
| break; | |
| case 2: | |
| OS << HEX16(getAddrOffsets<uint16_t>()[I]); | |
| break; | |
| case 4: | |
| OS << HEX32(getAddrOffsets<uint32_t>()[I]); | |
| break; | |
| case 8: | |
| OS << HEX32(getAddrOffsets<uint64_t>()[I]); | |
| break; | |
| default: | |
| break; | |
| } | |
| OS << " (" << HEX64(*getAddress(I)) << ")\n"; | |
| } | |
| OS << "\nAddress Info Offsets:\n"; | |
| OS << "INDEX Offset\n"; | |
| OS << "====== ==========\n"; | |
| for (uint32_t I = 0; I < getNumAddresses(); ++I) | |
| OS << formatv("[{0,4}] ", I) << HEX32(*getAddressInfoOffset(I)) << "\n"; | |
| OS << "\nFiles:\n"; | |
| OS << "INDEX DIRECTORY BASENAME PATH\n"; | |
| OS << "====== ========== ========== ==============================\n"; | |
| for (uint32_t I = 0;; ++I) { | |
| auto FE = getFile(I); | |
| if (!FE) | |
| break; | |
| OS << formatv("[{0,4}] ", I) << HEX32(FE->Dir) << ' ' << HEX32(FE->Base) | |
| << ' '; | |
| dump(OS, FE); | |
| OS << "\n"; | |
| } | |
| OS << "\n"; | |
| gsym::dump(OS, StrTab, 4); | |
| OS << "\n"; | |
| for (uint32_t I = 0; I < getNumAddresses(); ++I) { | |
| OS << "FunctionInfo @ " << HEX32(*getAddressInfoOffset(I)) << ": "; | |
| if (auto FI = getFunctionInfoAtIndex(I)) | |
| dump(OS, *FI); | |
| else | |
| logAllUnhandledErrors(FI.takeError(), OS, "FunctionInfo:"); | |
| } | |
| } |