LCOV - code coverage report
Current view: top level - lib/DebugInfo/DWARF - DWARFDebugAddr.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 76 80 95.0 %
Date: 2018-10-20 13:21:21 Functions: 5 6 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- DWARFDebugAddr.cpp -------------------------------------------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : 
      10             : #include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h"
      11             : #include "llvm/BinaryFormat/Dwarf.h"
      12             : #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
      13             : 
      14             : using namespace llvm;
      15             : 
      16          30 : void DWARFDebugAddrTable::clear() {
      17          30 :   HeaderData = {};
      18             :   Addrs.clear();
      19             :   invalidateLength();
      20          30 : }
      21             : 
      22          30 : Error DWARFDebugAddrTable::extract(DWARFDataExtractor Data,
      23             :                                    uint32_t *OffsetPtr,
      24             :                                    uint16_t Version,
      25             :                                    uint8_t AddrSize,
      26             :                                    std::function<void(Error)> WarnCallback) {
      27          30 :   clear();
      28          30 :   HeaderOffset = *OffsetPtr;
      29             :   // Read and verify the length field.
      30             :   if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t)))
      31             :     return createStringError(errc::invalid_argument,
      32             :                        "section is not large enough to contain a "
      33             :                        ".debug_addr table length at offset 0x%"
      34           1 :                        PRIx32, *OffsetPtr);
      35             :   uint16_t UnitVersion;
      36          29 :   if (Version == 0) {
      37           6 :     WarnCallback(createStringError(errc::invalid_argument,
      38             :                        "DWARF version is not defined in CU,"
      39             :                        " assuming version 5"));
      40           6 :     UnitVersion = 5;
      41             :   } else {
      42          23 :     UnitVersion = Version;
      43             :   }
      44             :   // TODO: Add support for DWARF64.
      45          29 :   Format = dwarf::DwarfFormat::DWARF32;
      46          29 :   if (UnitVersion >= 5) {
      47          19 :     HeaderData.Length = Data.getU32(OffsetPtr);
      48          19 :     if (HeaderData.Length == 0xffffffffu) {
      49             :       invalidateLength();
      50             :       return createStringError(errc::not_supported,
      51             :           "DWARF64 is not supported in .debug_addr at offset 0x%" PRIx32,
      52           2 :           HeaderOffset);
      53             :     }
      54          18 :     if (HeaderData.Length + sizeof(uint32_t) < sizeof(Header)) {
      55           1 :       uint32_t TmpLength = getLength();
      56             :       invalidateLength();
      57             :       return createStringError(errc::invalid_argument,
      58             :                          ".debug_addr table at offset 0x%" PRIx32
      59             :                          " has too small length (0x%" PRIx32
      60             :                          ") to contain a complete header",
      61           2 :                          HeaderOffset, TmpLength);
      62             :     }
      63          17 :     uint32_t End = HeaderOffset + getLength();
      64          17 :     if (!Data.isValidOffsetForDataOfSize(HeaderOffset, End - HeaderOffset)) {
      65           1 :       uint32_t TmpLength = getLength();
      66             :       invalidateLength();
      67             :       return createStringError(errc::invalid_argument,
      68             :           "section is not large enough to contain a .debug_addr table "
      69             :           "of length 0x%" PRIx32 " at offset 0x%" PRIx32,
      70           2 :           TmpLength, HeaderOffset);
      71             :     }
      72             : 
      73          16 :     HeaderData.Version = Data.getU16(OffsetPtr);
      74          16 :     HeaderData.AddrSize = Data.getU8(OffsetPtr);
      75          16 :     HeaderData.SegSize = Data.getU8(OffsetPtr);
      76          16 :     DataSize = getDataSize();
      77             :   } else {
      78          10 :     HeaderData.Version = UnitVersion;
      79          10 :     HeaderData.AddrSize = AddrSize;
      80             :     // TODO: Support for non-zero SegSize.
      81          10 :     HeaderData.SegSize = 0;
      82          20 :     DataSize = Data.size();
      83             :   }
      84             : 
      85             :   // Perform basic validation of the remaining header fields.
      86             : 
      87             :   // We support DWARF version 5 for now as well as pre-DWARF5
      88             :   // implementations of .debug_addr table, which doesn't contain a header
      89             :   // and consists only of a series of addresses.
      90          26 :   if (HeaderData.Version > 5) {
      91             :     return createStringError(errc::not_supported, "version %" PRIu16
      92             :         " of .debug_addr section at offset 0x%" PRIx32 " is not supported",
      93           2 :         HeaderData.Version, HeaderOffset);
      94             :   }
      95             :   // FIXME: For now we just treat version mismatch as an error,
      96             :   // however the correct way to associate a .debug_addr table
      97             :   // with a .debug_info table is to look at the DW_AT_addr_base
      98             :   // attribute in the info table.
      99          25 :   if (HeaderData.Version != UnitVersion)
     100             :     return createStringError(errc::invalid_argument,
     101             :                        ".debug_addr table at offset 0x%" PRIx32
     102             :                        " has version %" PRIu16
     103             :                        " which is different from the version suggested"
     104             :                        " by the DWARF unit header: %" PRIu16,
     105           2 :                        HeaderOffset, HeaderData.Version, UnitVersion);
     106          24 :   if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8)
     107             :     return createStringError(errc::not_supported,
     108             :                        ".debug_addr table at offset 0x%" PRIx32
     109             :                        " has unsupported address size %" PRIu8,
     110           2 :                        HeaderOffset, HeaderData.AddrSize);
     111          23 :   if (HeaderData.AddrSize != AddrSize && AddrSize != 0)
     112             :     return createStringError(errc::invalid_argument,
     113             :                        ".debug_addr table at offset 0x%" PRIx32
     114             :                        " has address size %" PRIu8
     115             :                        " which is different from CU address size %" PRIu8,
     116           2 :                        HeaderOffset, HeaderData.AddrSize, AddrSize);
     117             : 
     118             :   // TODO: add support for non-zero segment selector size.
     119          22 :   if (HeaderData.SegSize != 0)
     120             :     return createStringError(errc::not_supported,
     121             :                        ".debug_addr table at offset 0x%" PRIx32
     122             :                        " has unsupported segment selector size %" PRIu8,
     123           2 :                        HeaderOffset, HeaderData.SegSize);
     124          21 :   if (DataSize % HeaderData.AddrSize != 0) {
     125             :     invalidateLength();
     126             :     return createStringError(errc::invalid_argument,
     127             :                        ".debug_addr table at offset 0x%" PRIx32
     128             :                        " contains data of size %" PRIu32
     129             :                        " which is not a multiple of addr size %" PRIu8,
     130           2 :                        HeaderOffset, DataSize, HeaderData.AddrSize);
     131             :   }
     132             :   Data.setAddressSize(HeaderData.AddrSize);
     133          20 :   uint32_t AddrCount = DataSize / HeaderData.AddrSize;
     134          80 :   for (uint32_t I = 0; I < AddrCount; ++I)
     135          60 :     if (HeaderData.AddrSize == 4)
     136          14 :       Addrs.push_back(Data.getU32(OffsetPtr));
     137             :     else
     138          46 :       Addrs.push_back(Data.getU64(OffsetPtr));
     139             :   return Error::success();
     140             : }
     141             : 
     142          20 : void DWARFDebugAddrTable::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
     143          20 :   if (DumpOpts.Verbose)
     144          24 :     OS << format("0x%8.8" PRIx32 ": ", HeaderOffset);
     145          20 :   OS << format("Addr Section: length = 0x%8.8" PRIx32
     146             :                ", version = 0x%4.4" PRIx16 ", "
     147             :                "addr_size = 0x%2.2" PRIx8 ", seg_size = 0x%2.2" PRIx8 "\n",
     148             :                HeaderData.Length, HeaderData.Version, HeaderData.AddrSize,
     149          20 :                HeaderData.SegSize);
     150             : 
     151             :   static const char *Fmt32 = "0x%8.8" PRIx32;
     152             :   static const char *Fmt64 = "0x%16.16" PRIx64;
     153          20 :   std::string AddrFmt = "\n";
     154          20 :   std::string AddrFmtVerbose = " => ";
     155          20 :   if (HeaderData.AddrSize == 4) {
     156           8 :     AddrFmt.append(Fmt32);
     157           8 :     AddrFmtVerbose.append(Fmt32);
     158             :   }
     159             :   else {
     160          12 :     AddrFmt.append(Fmt64);
     161          12 :     AddrFmtVerbose.append(Fmt64);
     162             :   }
     163             : 
     164          20 :   if (Addrs.size() > 0) {
     165          19 :     OS << "Addrs: [";
     166          79 :     for (uint64_t Addr : Addrs) {
     167          60 :       OS << format(AddrFmt.c_str(), Addr);
     168          60 :       if (DumpOpts.Verbose)
     169          44 :         OS << format(AddrFmtVerbose.c_str(),
     170          88 :                      Addr + HeaderOffset + sizeof(HeaderData));
     171             :     }
     172          19 :     OS << "\n]\n";
     173             :   }
     174          20 : }
     175             : 
     176           0 : Expected<uint64_t> DWARFDebugAddrTable::getAddrEntry(uint32_t Index) const {
     177           0 :   if (Index < Addrs.size())
     178             :     return Addrs[Index];
     179           0 :   return createStringError(errc::invalid_argument,
     180             :                            "Index %" PRIu32 " is out of range of the "
     181             :                            ".debug_addr table at offset 0x%" PRIx32,
     182           0 :                            Index, HeaderOffset);
     183             : }
     184             : 
     185          66 : uint32_t DWARFDebugAddrTable::getLength() const {
     186          66 :   if (HeaderData.Length == 0)
     187             :     return 0;
     188             :   // TODO: DWARF64 support.
     189          61 :   return HeaderData.Length + sizeof(uint32_t);
     190             : }
     191             : 
     192          16 : uint32_t DWARFDebugAddrTable::getDataSize() const {
     193          16 :   if (DataSize != 0)
     194             :     return DataSize;
     195          16 :   if (getLength() == 0)
     196             :     return 0;
     197          16 :   return getLength() - getHeaderSize();
     198             : }

Generated by: LCOV version 1.13