Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp
35266 views
//===- DWARFDebugAddr.cpp -------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h"9#include "llvm/BinaryFormat/Dwarf.h"10#include "llvm/DebugInfo/DWARF/DWARFContext.h"11#include "llvm/Support/Errc.h"1213using namespace llvm;1415Error DWARFDebugAddrTable::extractAddresses(const DWARFDataExtractor &Data,16uint64_t *OffsetPtr,17uint64_t EndOffset) {18assert(EndOffset >= *OffsetPtr);19uint64_t DataSize = EndOffset - *OffsetPtr;20assert(Data.isValidOffsetForDataOfSize(*OffsetPtr, DataSize));21if (Error SizeErr = DWARFContext::checkAddressSizeSupported(22AddrSize, errc::not_supported, "address table at offset 0x%" PRIx64,23Offset))24return SizeErr;25if (DataSize % AddrSize != 0) {26invalidateLength();27return createStringError(errc::invalid_argument,28"address table at offset 0x%" PRIx6429" contains data of size 0x%" PRIx6430" which is not a multiple of addr size %" PRIu8,31Offset, DataSize, AddrSize);32}33Addrs.clear();34size_t Count = DataSize / AddrSize;35Addrs.reserve(Count);36while (Count--)37Addrs.push_back(Data.getRelocatedValue(AddrSize, OffsetPtr));38return Error::success();39}4041Error DWARFDebugAddrTable::extractV5(const DWARFDataExtractor &Data,42uint64_t *OffsetPtr, uint8_t CUAddrSize,43std::function<void(Error)> WarnCallback) {44Offset = *OffsetPtr;45llvm::Error Err = Error::success();46std::tie(Length, Format) = Data.getInitialLength(OffsetPtr, &Err);47if (Err) {48invalidateLength();49return createStringError(errc::invalid_argument,50"parsing address table at offset 0x%" PRIx6451": %s",52Offset, toString(std::move(Err)).c_str());53}5455if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, Length)) {56uint64_t DiagnosticLength = Length;57invalidateLength();58return createStringError(59errc::invalid_argument,60"section is not large enough to contain an address table "61"at offset 0x%" PRIx64 " with a unit_length value of 0x%" PRIx64,62Offset, DiagnosticLength);63}64uint64_t EndOffset = *OffsetPtr + Length;65// Ensure that we can read the remaining header fields.66if (Length < 4) {67uint64_t DiagnosticLength = Length;68invalidateLength();69return createStringError(70errc::invalid_argument,71"address table at offset 0x%" PRIx6472" has a unit_length value of 0x%" PRIx6473", which is too small to contain a complete header",74Offset, DiagnosticLength);75}7677Version = Data.getU16(OffsetPtr);78AddrSize = Data.getU8(OffsetPtr);79SegSize = Data.getU8(OffsetPtr);8081// Perform a basic validation of the header fields.82if (Version != 5)83return createStringError(errc::not_supported,84"address table at offset 0x%" PRIx6485" has unsupported version %" PRIu16,86Offset, Version);87// TODO: add support for non-zero segment selector size.88if (SegSize != 0)89return createStringError(errc::not_supported,90"address table at offset 0x%" PRIx6491" has unsupported segment selector size %" PRIu8,92Offset, SegSize);9394if (Error Err = extractAddresses(Data, OffsetPtr, EndOffset))95return Err;96if (CUAddrSize && AddrSize != CUAddrSize) {97WarnCallback(createStringError(98errc::invalid_argument,99"address table at offset 0x%" PRIx64 " has address size %" PRIu8100" which is different from CU address size %" PRIu8,101Offset, AddrSize, CUAddrSize));102}103return Error::success();104}105106Error DWARFDebugAddrTable::extractPreStandard(const DWARFDataExtractor &Data,107uint64_t *OffsetPtr,108uint16_t CUVersion,109uint8_t CUAddrSize) {110assert(CUVersion > 0 && CUVersion < 5);111112Offset = *OffsetPtr;113Length = 0;114Version = CUVersion;115AddrSize = CUAddrSize;116SegSize = 0;117118return extractAddresses(Data, OffsetPtr, Data.size());119}120121Error DWARFDebugAddrTable::extract(const DWARFDataExtractor &Data,122uint64_t *OffsetPtr,123uint16_t CUVersion,124uint8_t CUAddrSize,125std::function<void(Error)> WarnCallback) {126if (CUVersion > 0 && CUVersion < 5)127return extractPreStandard(Data, OffsetPtr, CUVersion, CUAddrSize);128if (CUVersion == 0)129WarnCallback(createStringError(errc::invalid_argument,130"DWARF version is not defined in CU,"131" assuming version 5"));132return extractV5(Data, OffsetPtr, CUAddrSize, WarnCallback);133}134135void DWARFDebugAddrTable::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {136if (DumpOpts.Verbose)137OS << format("0x%8.8" PRIx64 ": ", Offset);138if (Length) {139int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format);140OS << "Address table header: "141<< format("length = 0x%0*" PRIx64, OffsetDumpWidth, Length)142<< ", format = " << dwarf::FormatString(Format)143<< format(", version = 0x%4.4" PRIx16, Version)144<< format(", addr_size = 0x%2.2" PRIx8, AddrSize)145<< format(", seg_size = 0x%2.2" PRIx8, SegSize) << "\n";146}147148if (Addrs.size() > 0) {149const char *AddrFmt;150switch (AddrSize) {151case 2:152AddrFmt = "0x%4.4" PRIx64 "\n";153break;154case 4:155AddrFmt = "0x%8.8" PRIx64 "\n";156break;157case 8:158AddrFmt = "0x%16.16" PRIx64 "\n";159break;160default:161llvm_unreachable("unsupported address size");162}163OS << "Addrs: [\n";164for (uint64_t Addr : Addrs)165OS << format(AddrFmt, Addr);166OS << "]\n";167}168}169170Expected<uint64_t> DWARFDebugAddrTable::getAddrEntry(uint32_t Index) const {171if (Index < Addrs.size())172return Addrs[Index];173return createStringError(errc::invalid_argument,174"Index %" PRIu32 " is out of range of the "175"address table at offset 0x%" PRIx64,176Index, Offset);177}178179std::optional<uint64_t> DWARFDebugAddrTable::getFullLength() const {180if (Length == 0)181return std::nullopt;182return Length + dwarf::getUnitLengthFieldByteSize(Format);183}184185186