123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- //===- DWARFDebugAddr.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/DWARF/DWARFDebugAddr.h"
- #include "llvm/BinaryFormat/Dwarf.h"
- #include "llvm/DebugInfo/DWARF/DWARFContext.h"
- using namespace llvm;
- Error DWARFDebugAddrTable::extractAddresses(const DWARFDataExtractor &Data,
- uint64_t *OffsetPtr,
- uint64_t EndOffset) {
- assert(EndOffset >= *OffsetPtr);
- uint64_t DataSize = EndOffset - *OffsetPtr;
- assert(Data.isValidOffsetForDataOfSize(*OffsetPtr, DataSize));
- if (Error SizeErr = DWARFContext::checkAddressSizeSupported(
- AddrSize, errc::not_supported, "address table at offset 0x%" PRIx64,
- Offset))
- return SizeErr;
- if (DataSize % AddrSize != 0) {
- invalidateLength();
- return createStringError(errc::invalid_argument,
- "address table at offset 0x%" PRIx64
- " contains data of size 0x%" PRIx64
- " which is not a multiple of addr size %" PRIu8,
- Offset, DataSize, AddrSize);
- }
- Addrs.clear();
- size_t Count = DataSize / AddrSize;
- Addrs.reserve(Count);
- while (Count--)
- Addrs.push_back(Data.getRelocatedValue(AddrSize, OffsetPtr));
- return Error::success();
- }
- Error DWARFDebugAddrTable::extractV5(const DWARFDataExtractor &Data,
- uint64_t *OffsetPtr, uint8_t CUAddrSize,
- std::function<void(Error)> WarnCallback) {
- Offset = *OffsetPtr;
- llvm::Error Err = Error::success();
- std::tie(Length, Format) = Data.getInitialLength(OffsetPtr, &Err);
- if (Err) {
- invalidateLength();
- return createStringError(errc::invalid_argument,
- "parsing address table at offset 0x%" PRIx64
- ": %s",
- Offset, toString(std::move(Err)).c_str());
- }
- if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, Length)) {
- uint64_t DiagnosticLength = Length;
- invalidateLength();
- return createStringError(
- errc::invalid_argument,
- "section is not large enough to contain an address table "
- "at offset 0x%" PRIx64 " with a unit_length value of 0x%" PRIx64,
- Offset, DiagnosticLength);
- }
- uint64_t EndOffset = *OffsetPtr + Length;
- // Ensure that we can read the remaining header fields.
- if (Length < 4) {
- uint64_t DiagnosticLength = Length;
- invalidateLength();
- return createStringError(
- errc::invalid_argument,
- "address table at offset 0x%" PRIx64
- " has a unit_length value of 0x%" PRIx64
- ", which is too small to contain a complete header",
- Offset, DiagnosticLength);
- }
- Version = Data.getU16(OffsetPtr);
- AddrSize = Data.getU8(OffsetPtr);
- SegSize = Data.getU8(OffsetPtr);
- // Perform a basic validation of the header fields.
- if (Version != 5)
- return createStringError(errc::not_supported,
- "address table at offset 0x%" PRIx64
- " has unsupported version %" PRIu16,
- Offset, Version);
- // TODO: add support for non-zero segment selector size.
- if (SegSize != 0)
- return createStringError(errc::not_supported,
- "address table at offset 0x%" PRIx64
- " has unsupported segment selector size %" PRIu8,
- Offset, SegSize);
- if (Error Err = extractAddresses(Data, OffsetPtr, EndOffset))
- return Err;
- if (CUAddrSize && AddrSize != CUAddrSize) {
- WarnCallback(createStringError(
- errc::invalid_argument,
- "address table at offset 0x%" PRIx64 " has address size %" PRIu8
- " which is different from CU address size %" PRIu8,
- Offset, AddrSize, CUAddrSize));
- }
- return Error::success();
- }
- Error DWARFDebugAddrTable::extractPreStandard(const DWARFDataExtractor &Data,
- uint64_t *OffsetPtr,
- uint16_t CUVersion,
- uint8_t CUAddrSize) {
- assert(CUVersion > 0 && CUVersion < 5);
- Offset = *OffsetPtr;
- Length = 0;
- Version = CUVersion;
- AddrSize = CUAddrSize;
- SegSize = 0;
- return extractAddresses(Data, OffsetPtr, Data.size());
- }
- Error DWARFDebugAddrTable::extract(const DWARFDataExtractor &Data,
- uint64_t *OffsetPtr,
- uint16_t CUVersion,
- uint8_t CUAddrSize,
- std::function<void(Error)> WarnCallback) {
- if (CUVersion > 0 && CUVersion < 5)
- return extractPreStandard(Data, OffsetPtr, CUVersion, CUAddrSize);
- if (CUVersion == 0)
- WarnCallback(createStringError(errc::invalid_argument,
- "DWARF version is not defined in CU,"
- " assuming version 5"));
- return extractV5(Data, OffsetPtr, CUAddrSize, WarnCallback);
- }
- void DWARFDebugAddrTable::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
- if (DumpOpts.Verbose)
- OS << format("0x%8.8" PRIx64 ": ", Offset);
- if (Length) {
- int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format);
- OS << "Address table header: "
- << format("length = 0x%0*" PRIx64, OffsetDumpWidth, Length)
- << ", format = " << dwarf::FormatString(Format)
- << format(", version = 0x%4.4" PRIx16, Version)
- << format(", addr_size = 0x%2.2" PRIx8, AddrSize)
- << format(", seg_size = 0x%2.2" PRIx8, SegSize) << "\n";
- }
- if (Addrs.size() > 0) {
- const char *AddrFmt;
- switch (AddrSize) {
- case 2:
- AddrFmt = "0x%4.4" PRIx64 "\n";
- break;
- case 4:
- AddrFmt = "0x%8.8" PRIx64 "\n";
- break;
- case 8:
- AddrFmt = "0x%16.16" PRIx64 "\n";
- break;
- default:
- llvm_unreachable("unsupported address size");
- }
- OS << "Addrs: [\n";
- for (uint64_t Addr : Addrs)
- OS << format(AddrFmt, Addr);
- OS << "]\n";
- }
- }
- Expected<uint64_t> DWARFDebugAddrTable::getAddrEntry(uint32_t Index) const {
- if (Index < Addrs.size())
- return Addrs[Index];
- return createStringError(errc::invalid_argument,
- "Index %" PRIu32 " is out of range of the "
- "address table at offset 0x%" PRIx64,
- Index, Offset);
- }
- Optional<uint64_t> DWARFDebugAddrTable::getFullLength() const {
- if (Length == 0)
- return None;
- return Length + dwarf::getUnitLengthFieldByteSize(Format);
- }
|