void DWARFCompileUnit::setDIERelations() {
  if (DieArray.empty())
    return;
  DWARFDebugInfoEntryMinimal *die_array_begin = &DieArray.front();
  DWARFDebugInfoEntryMinimal *die_array_end = &DieArray.back();
  DWARFDebugInfoEntryMinimal *curr_die;
  // We purposely are skipping the last element in the array in the loop below
  // so that we can always have a valid next item
  for (curr_die = die_array_begin; curr_die < die_array_end; ++curr_die) {
    // Since our loop doesn't include the last element, we can always
    // safely access the next die in the array.
    DWARFDebugInfoEntryMinimal *next_die = curr_die + 1;

    const DWARFAbbreviationDeclaration *curr_die_abbrev =
      curr_die->getAbbreviationDeclarationPtr();

    if (curr_die_abbrev) {
      // Normal DIE
      if (curr_die_abbrev->hasChildren())
        next_die->setParent(curr_die);
      else
        curr_die->setSibling(next_die);
    } else {
      // NULL DIE that terminates a sibling chain
      DWARFDebugInfoEntryMinimal *parent = curr_die->getParent();
      if (parent)
        parent->setSibling(next_die);
    }
  }

  // Since we skipped the last element, we need to fix it up!
  if (die_array_begin < die_array_end)
    curr_die->setParent(die_array_begin);
}
Esempio n. 2
0
void DWARFUnit::setDIERelations() {
  if (DieArray.size() <= 1)
    return;

  std::vector<DWARFDebugInfoEntryMinimal *> ParentChain;
  DWARFDebugInfoEntryMinimal *SiblingChain = nullptr;
  for (auto &DIE : DieArray) {
    if (SiblingChain) {
      SiblingChain->setSibling(&DIE);
    }
    if (const DWARFAbbreviationDeclaration *AbbrDecl =
            DIE.getAbbreviationDeclarationPtr()) {
      // Normal DIE.
      if (AbbrDecl->hasChildren()) {
        ParentChain.push_back(&DIE);
        SiblingChain = nullptr;
      } else {
        SiblingChain = &DIE;
      }
    } else {
      // NULL entry terminates the sibling chain.
      SiblingChain = ParentChain.back();
      ParentChain.pop_back();
    }
  }
  assert(SiblingChain == nullptr || SiblingChain == &DieArray[0]);
  assert(ParentChain.empty());
}
void DWARFCompileUnit::extractDIEsToVector(
    bool AppendCUDie, bool AppendNonCUDies,
    std::vector<DWARFDebugInfoEntryMinimal> &Dies) const {
  if (!AppendCUDie && !AppendNonCUDies)
    return;

  // Set the offset to that of the first DIE and calculate the start of the
  // next compilation unit header.
  uint32_t Offset = getFirstDIEOffset();
  uint32_t NextCUOffset = getNextCompileUnitOffset();
  DWARFDebugInfoEntryMinimal DIE;
  uint32_t Depth = 0;
  const uint8_t *FixedFormSizes =
    DWARFFormValue::getFixedFormSizes(getAddressByteSize(), getVersion());
  bool IsCUDie = true;

  while (Offset < NextCUOffset &&
         DIE.extractFast(this, FixedFormSizes, &Offset)) {
    if (IsCUDie) {
      if (AppendCUDie)
        Dies.push_back(DIE);
      if (!AppendNonCUDies)
        break;
      // The average bytes per DIE entry has been seen to be
      // around 14-20 so let's pre-reserve the needed memory for
      // our DIE entries accordingly.
      Dies.reserve(Dies.size() + getDebugInfoSize() / 14);
      IsCUDie = false;
    } else {
      Dies.push_back(DIE);
    }

    const DWARFAbbreviationDeclaration *AbbrDecl =
      DIE.getAbbreviationDeclarationPtr();
    if (AbbrDecl) {
      // Normal DIE
      if (AbbrDecl->hasChildren())
        ++Depth;
    } else {
      // NULL DIE.
      if (Depth > 0)
        --Depth;
      if (Depth == 0)
        break;  // We are done with this compile unit!
    }
  }

  // Give a little bit of info if we encounter corrupt DWARF (our offset
  // should always terminate at or before the start of the next compilation
  // unit header).
  if (Offset > NextCUOffset)
    fprintf(stderr, "warning: DWARF compile unit extends beyond its "
                    "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), Offset);
}
Esempio n. 4
0
void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS,
                                               DWARFUnit *u,
                                               uint32_t *offset_ptr,
                                               uint16_t attr, uint16_t form,
                                               unsigned indent) const {
  const char BaseIndent[] = "            ";
  OS << BaseIndent;
  OS.indent(indent+2);
  const char *attrString = AttributeString(attr);
  if (attrString)
    WithColor(OS, syntax::Attribute) << attrString;
  else
    WithColor(OS, syntax::Attribute).get() << format("DW_AT_Unknown_%x", attr);

  const char *formString = FormEncodingString(form);
  if (formString)
    OS << " [" << formString << ']';
  else
    OS << format(" [DW_FORM_Unknown_%x]", form);

  DWARFFormValue formValue(form);

  if (!formValue.extractValue(u->getDebugInfoExtractor(), offset_ptr, u))
    return;

  OS << "\t(";

  const char *Name = nullptr;
  std::string File;
  auto Color = syntax::Enumerator;
  if (attr == DW_AT_decl_file || attr == DW_AT_call_file) {
  Color = syntax::String;
    if (const auto *LT = u->getContext().getLineTableForUnit(u))
      if (LT->getFileNameByIndex(
             formValue.getAsUnsignedConstant().getValue(),
             u->getCompilationDir(),
             DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) {
        File = '"' + File + '"';
        Name = File.c_str();
      }
  } else if (Optional<uint64_t> Val = formValue.getAsUnsignedConstant())
    Name = AttributeValueString(attr, *Val);

  if (Name)
    WithColor(OS, Color) << Name;
  else if (attr == DW_AT_decl_line || attr == DW_AT_call_line)
    OS << *formValue.getAsUnsignedConstant();
  else
    formValue.dump(OS, u);

  // We have dumped the attribute raw value. For some attributes
  // having both the raw value and the pretty-printed value is
  // interesting. These attributes are handled below.
  if ((attr == DW_AT_specification || attr == DW_AT_abstract_origin) &&
      // The signature references aren't handled.
      formValue.getForm() != DW_FORM_ref_sig8) {
    uint32_t Ref = formValue.getAsReference(u).getValue();
    DWARFDebugInfoEntryMinimal DIE;
    if (const DWARFUnit *RefU = findUnitAndExtractFast(DIE, u, &Ref))
      if (const char *Ref = DIE.getName(RefU, DINameKind::LinkageName))
        OS << " \"" << Ref << '\"';
  } else if (attr == DW_AT_APPLE_property_attribute) {
    if (Optional<uint64_t> OptVal = formValue.getAsUnsignedConstant())
      dumpApplePropertyAttribute(OS, *OptVal);
  } else if (attr == DW_AT_ranges) {
    dumpRanges(OS, getAddressRanges(u), u->getAddressByteSize(),
               sizeof(BaseIndent)+indent+4);
  }

  OS << ")\n";
}
size_t DWARFCompileUnit::extractDIEsIfNeeded(bool cu_die_only) {
  const size_t initial_die_array_size = DieArray.size();
  if ((cu_die_only && initial_die_array_size > 0) ||
      initial_die_array_size > 1)
    return 0; // Already parsed

  // Set the offset to that of the first DIE and calculate the start of the
  // next compilation unit header.
  uint32_t offset = getFirstDIEOffset();
  uint32_t next_cu_offset = getNextCompileUnitOffset();

  DWARFDebugInfoEntryMinimal die;
  // Keep a flat array of the DIE for binary lookup by DIE offset
  uint32_t depth = 0;
  // We are in our compile unit, parse starting at the offset
  // we were told to parse

  const uint8_t *fixed_form_sizes =
    DWARFFormValue::getFixedFormSizes(getAddressByteSize(), getVersion());

  while (offset < next_cu_offset &&
         die.extractFast(this, fixed_form_sizes, &offset)) {

    if (depth == 0) {
      uint64_t base_addr =
        die.getAttributeValueAsUnsigned(this, DW_AT_low_pc, -1U);
      if (base_addr == -1U)
        base_addr = die.getAttributeValueAsUnsigned(this, DW_AT_entry_pc, 0);
      setBaseAddress(base_addr);
    }

    if (cu_die_only) {
      addDIE(die);
      return 1;
    }
    else if (depth == 0 && initial_die_array_size == 1)
      // Don't append the CU die as we already did that
      ;
    else
      addDIE(die);

    const DWARFAbbreviationDeclaration *abbrDecl =
      die.getAbbreviationDeclarationPtr();
    if (abbrDecl) {
      // Normal DIE
      if (abbrDecl->hasChildren())
        ++depth;
    } else {
      // NULL DIE.
      if (depth > 0)
        --depth;
      if (depth == 0)
        break;  // We are done with this compile unit!
    }

  }

  // Give a little bit of info if we encounter corrupt DWARF (our offset
  // should always terminate at or before the start of the next compilation
  // unit header).
  if (offset > next_cu_offset)
    fprintf(stderr, "warning: DWARF compile unit extends beyond its "
                    "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), offset);

  setDIERelations();
  return DieArray.size();
}