1259698Sdim//===-- DWARFUnit.cpp -----------------------------------------------------===//
2259698Sdim//
3259698Sdim//                     The LLVM Compiler Infrastructure
4259698Sdim//
5259698Sdim// This file is distributed under the University of Illinois Open Source
6259698Sdim// License. See LICENSE.TXT for details.
7259698Sdim//
8259698Sdim//===----------------------------------------------------------------------===//
9259698Sdim
10259698Sdim#include "DWARFUnit.h"
11259698Sdim#include "DWARFContext.h"
12259698Sdim#include "llvm/DebugInfo/DWARFFormValue.h"
13259698Sdim#include "llvm/Support/Dwarf.h"
14259698Sdim#include "llvm/Support/Path.h"
15259698Sdim#include <cstdio>
16259698Sdim
17259698Sdimusing namespace llvm;
18259698Sdimusing namespace dwarf;
19259698Sdim
20259698SdimDWARFUnit::DWARFUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS,
21259698Sdim                     StringRef RS, StringRef SS, StringRef SOS, StringRef AOS,
22259698Sdim                     const RelocAddrMap *M, bool LE)
23259698Sdim    : Abbrev(DA), InfoSection(IS), AbbrevSection(AS), RangeSection(RS),
24259698Sdim      StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS),
25259698Sdim      RelocMap(M), isLittleEndian(LE) {
26259698Sdim  clear();
27259698Sdim}
28259698Sdim
29259698SdimDWARFUnit::~DWARFUnit() {
30259698Sdim}
31259698Sdim
32259698Sdimbool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index,
33259698Sdim                                                uint64_t &Result) const {
34259698Sdim  uint32_t Offset = AddrOffsetSectionBase + Index * AddrSize;
35259698Sdim  if (AddrOffsetSection.size() < Offset + AddrSize)
36259698Sdim    return false;
37259698Sdim  DataExtractor DA(AddrOffsetSection, isLittleEndian, AddrSize);
38259698Sdim  Result = DA.getAddress(&Offset);
39259698Sdim  return true;
40259698Sdim}
41259698Sdim
42259698Sdimbool DWARFUnit::getStringOffsetSectionItem(uint32_t Index,
43259698Sdim                                                  uint32_t &Result) const {
44259698Sdim  // FIXME: string offset section entries are 8-byte for DWARF64.
45259698Sdim  const uint32_t ItemSize = 4;
46259698Sdim  uint32_t Offset = Index * ItemSize;
47259698Sdim  if (StringOffsetSection.size() < Offset + ItemSize)
48259698Sdim    return false;
49259698Sdim  DataExtractor DA(StringOffsetSection, isLittleEndian, 0);
50259698Sdim  Result = DA.getU32(&Offset);
51259698Sdim  return true;
52259698Sdim}
53259698Sdim
54259698Sdimbool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) {
55259698Sdim  Length = debug_info.getU32(offset_ptr);
56259698Sdim  Version = debug_info.getU16(offset_ptr);
57259698Sdim  uint64_t abbrOffset = debug_info.getU32(offset_ptr);
58259698Sdim  AddrSize = debug_info.getU8(offset_ptr);
59259698Sdim
60259698Sdim  bool lengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1);
61259698Sdim  bool versionOK = DWARFContext::isSupportedVersion(Version);
62259698Sdim  bool abbrOffsetOK = AbbrevSection.size() > abbrOffset;
63259698Sdim  bool addrSizeOK = AddrSize == 4 || AddrSize == 8;
64259698Sdim
65259698Sdim  if (!lengthOK || !versionOK || !addrSizeOK || !abbrOffsetOK)
66259698Sdim    return false;
67259698Sdim
68259698Sdim  Abbrevs = Abbrev->getAbbreviationDeclarationSet(abbrOffset);
69259698Sdim  return true;
70259698Sdim}
71259698Sdim
72259698Sdimbool DWARFUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) {
73259698Sdim  clear();
74259698Sdim
75259698Sdim  Offset = *offset_ptr;
76259698Sdim
77259698Sdim  if (debug_info.isValidOffset(*offset_ptr)) {
78259698Sdim    if (extractImpl(debug_info, offset_ptr))
79259698Sdim      return true;
80259698Sdim
81259698Sdim    // reset the offset to where we tried to parse from if anything went wrong
82259698Sdim    *offset_ptr = Offset;
83259698Sdim  }
84259698Sdim
85259698Sdim  return false;
86259698Sdim}
87259698Sdim
88259698Sdimbool DWARFUnit::extractRangeList(uint32_t RangeListOffset,
89259698Sdim                                        DWARFDebugRangeList &RangeList) const {
90259698Sdim  // Require that compile unit is extracted.
91259698Sdim  assert(DieArray.size() > 0);
92259698Sdim  DataExtractor RangesData(RangeSection, isLittleEndian, AddrSize);
93259698Sdim  uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset;
94259698Sdim  return RangeList.extract(RangesData, &ActualRangeListOffset);
95259698Sdim}
96259698Sdim
97259698Sdimvoid DWARFUnit::clear() {
98259698Sdim  Offset = 0;
99259698Sdim  Length = 0;
100259698Sdim  Version = 0;
101259698Sdim  Abbrevs = 0;
102259698Sdim  AddrSize = 0;
103259698Sdim  BaseAddr = 0;
104259698Sdim  RangeSectionBase = 0;
105259698Sdim  AddrOffsetSectionBase = 0;
106259698Sdim  clearDIEs(false);
107259698Sdim  DWO.reset();
108259698Sdim}
109259698Sdim
110259698Sdimconst char *DWARFUnit::getCompilationDir() {
111259698Sdim  extractDIEsIfNeeded(true);
112259698Sdim  if (DieArray.empty())
113259698Sdim    return 0;
114259698Sdim  return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0);
115259698Sdim}
116259698Sdim
117259698Sdimuint64_t DWARFUnit::getDWOId() {
118259698Sdim  extractDIEsIfNeeded(true);
119259698Sdim  const uint64_t FailValue = -1ULL;
120259698Sdim  if (DieArray.empty())
121259698Sdim    return FailValue;
122259698Sdim  return DieArray[0]
123259698Sdim      .getAttributeValueAsUnsignedConstant(this, DW_AT_GNU_dwo_id, FailValue);
124259698Sdim}
125259698Sdim
126259698Sdimvoid DWARFUnit::setDIERelations() {
127259698Sdim  if (DieArray.empty())
128259698Sdim    return;
129259698Sdim  DWARFDebugInfoEntryMinimal *die_array_begin = &DieArray.front();
130259698Sdim  DWARFDebugInfoEntryMinimal *die_array_end = &DieArray.back();
131259698Sdim  DWARFDebugInfoEntryMinimal *curr_die;
132259698Sdim  // We purposely are skipping the last element in the array in the loop below
133259698Sdim  // so that we can always have a valid next item
134259698Sdim  for (curr_die = die_array_begin; curr_die < die_array_end; ++curr_die) {
135259698Sdim    // Since our loop doesn't include the last element, we can always
136259698Sdim    // safely access the next die in the array.
137259698Sdim    DWARFDebugInfoEntryMinimal *next_die = curr_die + 1;
138259698Sdim
139259698Sdim    const DWARFAbbreviationDeclaration *curr_die_abbrev =
140259698Sdim      curr_die->getAbbreviationDeclarationPtr();
141259698Sdim
142259698Sdim    if (curr_die_abbrev) {
143259698Sdim      // Normal DIE
144259698Sdim      if (curr_die_abbrev->hasChildren())
145259698Sdim        next_die->setParent(curr_die);
146259698Sdim      else
147259698Sdim        curr_die->setSibling(next_die);
148259698Sdim    } else {
149259698Sdim      // NULL DIE that terminates a sibling chain
150259698Sdim      DWARFDebugInfoEntryMinimal *parent = curr_die->getParent();
151259698Sdim      if (parent)
152259698Sdim        parent->setSibling(next_die);
153259698Sdim    }
154259698Sdim  }
155259698Sdim
156259698Sdim  // Since we skipped the last element, we need to fix it up!
157259698Sdim  if (die_array_begin < die_array_end)
158259698Sdim    curr_die->setParent(die_array_begin);
159259698Sdim}
160259698Sdim
161259698Sdimvoid DWARFUnit::extractDIEsToVector(
162259698Sdim    bool AppendCUDie, bool AppendNonCUDies,
163259698Sdim    std::vector<DWARFDebugInfoEntryMinimal> &Dies) const {
164259698Sdim  if (!AppendCUDie && !AppendNonCUDies)
165259698Sdim    return;
166259698Sdim
167259698Sdim  // Set the offset to that of the first DIE and calculate the start of the
168259698Sdim  // next compilation unit header.
169259698Sdim  uint32_t Offset = getFirstDIEOffset();
170259698Sdim  uint32_t NextCUOffset = getNextUnitOffset();
171259698Sdim  DWARFDebugInfoEntryMinimal DIE;
172259698Sdim  uint32_t Depth = 0;
173259698Sdim  bool IsCUDie = true;
174259698Sdim
175259698Sdim  while (Offset < NextCUOffset && DIE.extractFast(this, &Offset)) {
176259698Sdim    if (IsCUDie) {
177259698Sdim      if (AppendCUDie)
178259698Sdim        Dies.push_back(DIE);
179259698Sdim      if (!AppendNonCUDies)
180259698Sdim        break;
181259698Sdim      // The average bytes per DIE entry has been seen to be
182259698Sdim      // around 14-20 so let's pre-reserve the needed memory for
183259698Sdim      // our DIE entries accordingly.
184259698Sdim      Dies.reserve(Dies.size() + getDebugInfoSize() / 14);
185259698Sdim      IsCUDie = false;
186259698Sdim    } else {
187259698Sdim      Dies.push_back(DIE);
188259698Sdim    }
189259698Sdim
190259698Sdim    const DWARFAbbreviationDeclaration *AbbrDecl =
191259698Sdim      DIE.getAbbreviationDeclarationPtr();
192259698Sdim    if (AbbrDecl) {
193259698Sdim      // Normal DIE
194259698Sdim      if (AbbrDecl->hasChildren())
195259698Sdim        ++Depth;
196259698Sdim    } else {
197259698Sdim      // NULL DIE.
198259698Sdim      if (Depth > 0)
199259698Sdim        --Depth;
200259698Sdim      if (Depth == 0)
201259698Sdim        break;  // We are done with this compile unit!
202259698Sdim    }
203259698Sdim  }
204259698Sdim
205259698Sdim  // Give a little bit of info if we encounter corrupt DWARF (our offset
206259698Sdim  // should always terminate at or before the start of the next compilation
207259698Sdim  // unit header).
208259698Sdim  if (Offset > NextCUOffset)
209259698Sdim    fprintf(stderr, "warning: DWARF compile unit extends beyond its "
210259698Sdim                    "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), Offset);
211259698Sdim}
212259698Sdim
213259698Sdimsize_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
214259698Sdim  if ((CUDieOnly && DieArray.size() > 0) ||
215259698Sdim      DieArray.size() > 1)
216259698Sdim    return 0; // Already parsed.
217259698Sdim
218259698Sdim  bool HasCUDie = DieArray.size() > 0;
219259698Sdim  extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray);
220259698Sdim
221259698Sdim  if (DieArray.empty())
222259698Sdim    return 0;
223259698Sdim
224259698Sdim  // If CU DIE was just parsed, copy several attribute values from it.
225259698Sdim  if (!HasCUDie) {
226259698Sdim    uint64_t BaseAddr =
227259698Sdim        DieArray[0].getAttributeValueAsAddress(this, DW_AT_low_pc, -1ULL);
228259698Sdim    if (BaseAddr == -1ULL)
229259698Sdim      BaseAddr = DieArray[0].getAttributeValueAsAddress(this, DW_AT_entry_pc, 0);
230259698Sdim    setBaseAddress(BaseAddr);
231259698Sdim    AddrOffsetSectionBase = DieArray[0].getAttributeValueAsSectionOffset(
232259698Sdim        this, DW_AT_GNU_addr_base, 0);
233259698Sdim    RangeSectionBase = DieArray[0].getAttributeValueAsSectionOffset(
234259698Sdim        this, DW_AT_GNU_ranges_base, 0);
235259698Sdim  }
236259698Sdim
237259698Sdim  setDIERelations();
238259698Sdim  return DieArray.size();
239259698Sdim}
240259698Sdim
241259698SdimDWARFUnit::DWOHolder::DWOHolder(object::ObjectFile *DWOFile)
242259698Sdim    : DWOFile(DWOFile),
243259698Sdim      DWOContext(cast<DWARFContext>(DIContext::getDWARFContext(DWOFile))),
244259698Sdim      DWOU(0) {
245259698Sdim  if (DWOContext->getNumDWOCompileUnits() > 0)
246259698Sdim    DWOU = DWOContext->getDWOCompileUnitAtIndex(0);
247259698Sdim}
248259698Sdim
249259698Sdimbool DWARFUnit::parseDWO() {
250259698Sdim  if (DWO.get() != 0)
251259698Sdim    return false;
252259698Sdim  extractDIEsIfNeeded(true);
253259698Sdim  if (DieArray.empty())
254259698Sdim    return false;
255259698Sdim  const char *DWOFileName =
256259698Sdim      DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, 0);
257259698Sdim  if (DWOFileName == 0)
258259698Sdim    return false;
259259698Sdim  const char *CompilationDir =
260259698Sdim      DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0);
261259698Sdim  SmallString<16> AbsolutePath;
262259698Sdim  if (sys::path::is_relative(DWOFileName) && CompilationDir != 0) {
263259698Sdim    sys::path::append(AbsolutePath, CompilationDir);
264259698Sdim  }
265259698Sdim  sys::path::append(AbsolutePath, DWOFileName);
266259698Sdim  object::ObjectFile *DWOFile =
267259698Sdim      object::ObjectFile::createObjectFile(AbsolutePath);
268259698Sdim  if (!DWOFile)
269259698Sdim    return false;
270259698Sdim  // Reset DWOHolder.
271259698Sdim  DWO.reset(new DWOHolder(DWOFile));
272259698Sdim  DWARFUnit *DWOCU = DWO->getUnit();
273259698Sdim  // Verify that compile unit in .dwo file is valid.
274259698Sdim  if (DWOCU == 0 || DWOCU->getDWOId() != getDWOId()) {
275259698Sdim    DWO.reset();
276259698Sdim    return false;
277259698Sdim  }
278259698Sdim  // Share .debug_addr and .debug_ranges section with compile unit in .dwo
279259698Sdim  DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase);
280259698Sdim  DWOCU->setRangesSection(RangeSection, RangeSectionBase);
281259698Sdim  return true;
282259698Sdim}
283259698Sdim
284259698Sdimvoid DWARFUnit::clearDIEs(bool KeepCUDie) {
285259698Sdim  if (DieArray.size() > (unsigned)KeepCUDie) {
286259698Sdim    // std::vectors never get any smaller when resized to a smaller size,
287259698Sdim    // or when clear() or erase() are called, the size will report that it
288259698Sdim    // is smaller, but the memory allocated remains intact (call capacity()
289259698Sdim    // to see this). So we need to create a temporary vector and swap the
290259698Sdim    // contents which will cause just the internal pointers to be swapped
291259698Sdim    // so that when temporary vector goes out of scope, it will destroy the
292259698Sdim    // contents.
293259698Sdim    std::vector<DWARFDebugInfoEntryMinimal> TmpArray;
294259698Sdim    DieArray.swap(TmpArray);
295259698Sdim    // Save at least the compile unit DIE
296259698Sdim    if (KeepCUDie)
297259698Sdim      DieArray.push_back(TmpArray.front());
298259698Sdim  }
299259698Sdim}
300259698Sdim
301259698Sdimvoid
302259698SdimDWARFUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
303259698Sdim                                         bool clear_dies_if_already_not_parsed,
304259698Sdim                                         uint32_t CUOffsetInAranges) {
305259698Sdim  // This function is usually called if there in no .debug_aranges section
306259698Sdim  // in order to produce a compile unit level set of address ranges that
307259698Sdim  // is accurate. If the DIEs weren't parsed, then we don't want all dies for
308259698Sdim  // all compile units to stay loaded when they weren't needed. So we can end
309259698Sdim  // up parsing the DWARF and then throwing them all away to keep memory usage
310259698Sdim  // down.
311259698Sdim  const bool clear_dies = extractDIEsIfNeeded(false) > 1 &&
312259698Sdim                          clear_dies_if_already_not_parsed;
313259698Sdim  DieArray[0].buildAddressRangeTable(this, debug_aranges, CUOffsetInAranges);
314259698Sdim  bool DWOCreated = parseDWO();
315259698Sdim  if (DWO.get()) {
316259698Sdim    // If there is a .dwo file for this compile unit, then skeleton CU DIE
317259698Sdim    // doesn't have children, and we should instead build address range table
318259698Sdim    // from DIEs in the .debug_info.dwo section of .dwo file.
319259698Sdim    DWO->getUnit()->buildAddressRangeTable(
320259698Sdim        debug_aranges, clear_dies_if_already_not_parsed, CUOffsetInAranges);
321259698Sdim  }
322259698Sdim  if (DWOCreated && clear_dies_if_already_not_parsed)
323259698Sdim    DWO.reset();
324259698Sdim
325259698Sdim  // Keep memory down by clearing DIEs if this generate function
326259698Sdim  // caused them to be parsed.
327259698Sdim  if (clear_dies)
328259698Sdim    clearDIEs(true);
329259698Sdim}
330259698Sdim
331259698Sdimconst DWARFDebugInfoEntryMinimal *
332259698SdimDWARFUnit::getSubprogramForAddress(uint64_t Address) {
333259698Sdim  extractDIEsIfNeeded(false);
334259698Sdim  for (size_t i = 0, n = DieArray.size(); i != n; i++)
335259698Sdim    if (DieArray[i].isSubprogramDIE() &&
336259698Sdim        DieArray[i].addressRangeContainsAddress(this, Address)) {
337259698Sdim      return &DieArray[i];
338259698Sdim    }
339259698Sdim  return 0;
340259698Sdim}
341259698Sdim
342259698SdimDWARFDebugInfoEntryInlinedChain
343259698SdimDWARFUnit::getInlinedChainForAddress(uint64_t Address) {
344259698Sdim  // First, find a subprogram that contains the given address (the root
345259698Sdim  // of inlined chain).
346259698Sdim  const DWARFUnit *ChainCU = 0;
347259698Sdim  const DWARFDebugInfoEntryMinimal *SubprogramDIE =
348259698Sdim      getSubprogramForAddress(Address);
349259698Sdim  if (SubprogramDIE) {
350259698Sdim    ChainCU = this;
351259698Sdim  } else {
352259698Sdim    // Try to look for subprogram DIEs in the DWO file.
353259698Sdim    parseDWO();
354259698Sdim    if (DWO.get()) {
355259698Sdim      SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address);
356259698Sdim      if (SubprogramDIE)
357259698Sdim        ChainCU = DWO->getUnit();
358259698Sdim    }
359259698Sdim  }
360259698Sdim
361259698Sdim  // Get inlined chain rooted at this subprogram DIE.
362259698Sdim  if (!SubprogramDIE)
363259698Sdim    return DWARFDebugInfoEntryInlinedChain();
364259698Sdim  return SubprogramDIE->getInlinedChainForAddress(ChainCU, Address);
365259698Sdim}
366