1358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer//===-- DWARFDebugArangeSet.cpp -------------------------------------------===//
2358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer//
3358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer//                     The LLVM Compiler Infrastructure
4358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer//
5358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer// This file is distributed under the University of Illinois Open Source
6358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer// License. See LICENSE.TXT for details.
7358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer//
8358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer//===----------------------------------------------------------------------===//
9358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
10358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer#include "DWARFDebugArangeSet.h"
11358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer#include "llvm/Support/Format.h"
12358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer#include "llvm/Support/raw_ostream.h"
13553f93396367fd1e1372d41c02583b2dc060947fBenjamin Kramer#include <algorithm>
14358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer#include <cassert>
15358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramerusing namespace llvm;
16358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
17358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramervoid DWARFDebugArangeSet::clear() {
18358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer  Offset = -1U;
197b1bea3ccbf2d1cff66d4287e0cb7bc045802d31Rafael Espindola  std::memset(&HeaderData, 0, sizeof(Header));
20358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer  ArangeDescriptors.clear();
21358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer}
22358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
23358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramerbool
24358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin KramerDWARFDebugArangeSet::extract(DataExtractor data, uint32_t *offset_ptr) {
25358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer  if (data.isValidOffset(*offset_ptr)) {
26358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    ArangeDescriptors.clear();
27358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    Offset = *offset_ptr;
28358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
29358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    // 7.20 Address Range Table
30358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    //
31358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    // Each set of entries in the table of address ranges contained in
32358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    // the .debug_aranges section begins with a header consisting of: a
33358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    // 4-byte length containing the length of the set of entries for this
34358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    // compilation unit, not including the length field itself; a 2-byte
35358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    // version identifier containing the value 2 for DWARF Version 2; a
36358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    // 4-byte offset into the.debug_infosection; a 1-byte unsigned integer
37358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    // containing the size in bytes of an address (or the offset portion of
38358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    // an address for segmented addressing) on the target system; and a
39358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    // 1-byte unsigned integer containing the size in bytes of a segment
40358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    // descriptor on the target system. This header is followed by a series
41358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    // of tuples. Each tuple consists of an address and a length, each in
42358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    // the size appropriate for an address on the target architecture.
437b1bea3ccbf2d1cff66d4287e0cb7bc045802d31Rafael Espindola    HeaderData.Length = data.getU32(offset_ptr);
447b1bea3ccbf2d1cff66d4287e0cb7bc045802d31Rafael Espindola    HeaderData.Version = data.getU16(offset_ptr);
457b1bea3ccbf2d1cff66d4287e0cb7bc045802d31Rafael Espindola    HeaderData.CuOffset = data.getU32(offset_ptr);
467b1bea3ccbf2d1cff66d4287e0cb7bc045802d31Rafael Espindola    HeaderData.AddrSize = data.getU8(offset_ptr);
477b1bea3ccbf2d1cff66d4287e0cb7bc045802d31Rafael Espindola    HeaderData.SegSize = data.getU8(offset_ptr);
48358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
491c0b24f91a5a6f3aeca483e753e7fd27357ecb71Benjamin Kramer    // Perform basic validation of the header fields.
507b1bea3ccbf2d1cff66d4287e0cb7bc045802d31Rafael Espindola    if (!data.isValidOffsetForDataOfSize(Offset, HeaderData.Length) ||
517b1bea3ccbf2d1cff66d4287e0cb7bc045802d31Rafael Espindola        (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8)) {
521c0b24f91a5a6f3aeca483e753e7fd27357ecb71Benjamin Kramer      clear();
531c0b24f91a5a6f3aeca483e753e7fd27357ecb71Benjamin Kramer      return false;
541c0b24f91a5a6f3aeca483e753e7fd27357ecb71Benjamin Kramer    }
551c0b24f91a5a6f3aeca483e753e7fd27357ecb71Benjamin Kramer
56358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    // The first tuple following the header in each set begins at an offset
57358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    // that is a multiple of the size of a single tuple (that is, twice the
58358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    // size of an address). The header is padded, if necessary, to the
59358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    // appropriate boundary.
60358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    const uint32_t header_size = *offset_ptr - Offset;
617b1bea3ccbf2d1cff66d4287e0cb7bc045802d31Rafael Espindola    const uint32_t tuple_size = HeaderData.AddrSize * 2;
62358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    uint32_t first_tuple_offset = 0;
63358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    while (first_tuple_offset < header_size)
64358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer      first_tuple_offset += tuple_size;
65358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
66358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    *offset_ptr = Offset + first_tuple_offset;
67358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
68358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    Descriptor arangeDescriptor;
69358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
7036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    static_assert(sizeof(arangeDescriptor.Address) ==
7136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                      sizeof(arangeDescriptor.Length),
7236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                  "Different datatypes for addresses and sizes!");
737b1bea3ccbf2d1cff66d4287e0cb7bc045802d31Rafael Espindola    assert(sizeof(arangeDescriptor.Address) >= HeaderData.AddrSize);
74358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
75358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    while (data.isValidOffset(*offset_ptr)) {
767b1bea3ccbf2d1cff66d4287e0cb7bc045802d31Rafael Espindola      arangeDescriptor.Address = data.getUnsigned(offset_ptr, HeaderData.AddrSize);
777b1bea3ccbf2d1cff66d4287e0cb7bc045802d31Rafael Espindola      arangeDescriptor.Length = data.getUnsigned(offset_ptr, HeaderData.AddrSize);
78358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
79358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer      // Each set of tuples is terminated by a 0 for the address and 0
80358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer      // for the length.
81358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer      if (arangeDescriptor.Address || arangeDescriptor.Length)
82358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer        ArangeDescriptors.push_back(arangeDescriptor);
83358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer      else
84358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer        break; // We are done if we get a zero address and length
85358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    }
86358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
87358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer    return !ArangeDescriptors.empty();
88358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer  }
89358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer  return false;
90358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer}
91358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
92358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramervoid DWARFDebugArangeSet::dump(raw_ostream &OS) const {
93358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer  OS << format("Address Range Header: length = 0x%8.8x, version = 0x%4.4x, ",
947b1bea3ccbf2d1cff66d4287e0cb7bc045802d31Rafael Espindola               HeaderData.Length, HeaderData.Version)
95358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer     << format("cu_offset = 0x%8.8x, addr_size = 0x%2.2x, seg_size = 0x%2.2x\n",
967b1bea3ccbf2d1cff66d4287e0cb7bc045802d31Rafael Espindola               HeaderData.CuOffset, HeaderData.AddrSize, HeaderData.SegSize);
97358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer
987b1bea3ccbf2d1cff66d4287e0cb7bc045802d31Rafael Espindola  const uint32_t hex_width = HeaderData.AddrSize * 2;
9936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (const auto &Desc : ArangeDescriptors) {
10036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    OS << format("[0x%*.*" PRIx64 " -", hex_width, hex_width, Desc.Address)
10141a964931a0e0943ceef28b0c691843bf8ca87b7Benjamin Kramer       << format(" 0x%*.*" PRIx64 ")\n",
10236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                 hex_width, hex_width, Desc.getEndAddress());
10336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
104358f4fd9ee078b3c79597fc688855fb48bc1f356Benjamin Kramer}
105