Example #1
0
void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) {
  DWARFDie UnitDie = getUnitDIE();
  if (!UnitDie)
    return;
  // First, check if unit DIE describes address ranges for the whole unit.
  const auto &CUDIERanges = UnitDie.getAddressRanges();
  if (!CUDIERanges.empty()) {
    CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end());
    return;
  }

  // This function is usually called if there in no .debug_aranges section
  // in order to produce a compile unit level set of address ranges that
  // is accurate. If the DIEs weren't parsed, then we don't want all dies for
  // all compile units to stay loaded when they weren't needed. So we can end
  // up parsing the DWARF and then throwing them all away to keep memory usage
  // down.
  const bool ClearDIEs = extractDIEsIfNeeded(false) > 1;
  getUnitDIE().collectChildrenAddressRanges(CURanges);

  // Collect address ranges from DIEs in .dwo if necessary.
  bool DWOCreated = parseDWO();
  if (DWO.get())
    DWO->getUnit()->collectAddressRanges(CURanges);
  if (DWOCreated)
    DWO.reset();

  // Keep memory down by clearing DIEs if this generate function
  // caused them to be parsed.
  if (ClearDIEs)
    clearDIEs(true);
}
Example #2
0
void DWARFUnit::updateAddressDieMap(DWARFDie Die) {
  if (Die.isSubroutineDIE()) {
    auto DIERangesOrError = Die.getAddressRanges();
    if (DIERangesOrError) {
      for (const auto &R : DIERangesOrError.get()) {
        // Ignore 0-sized ranges.
        if (R.LowPC == R.HighPC)
          continue;
        auto B = AddrDieMap.upper_bound(R.LowPC);
        if (B != AddrDieMap.begin() && R.LowPC < (--B)->second.first) {
          // The range is a sub-range of existing ranges, we need to split the
          // existing range.
          if (R.HighPC < B->second.first)
            AddrDieMap[R.HighPC] = B->second;
          if (R.LowPC > B->first)
            AddrDieMap[B->first].first = R.LowPC;
        }
        AddrDieMap[R.LowPC] = std::make_pair(R.HighPC, Die);
      }
    } else
      llvm::consumeError(DIERangesOrError.takeError());
  }
  // Parent DIEs are added to the AddrDieMap prior to the Children DIEs to
  // simplify the logic to update AddrDieMap. The child's range will always
  // be equal or smaller than the parent's range. With this assumption, when
  // adding one range into the map, it will at most split a range into 3
  // sub-ranges.
  for (DWARFDie Child = Die.getFirstChild(); Child; Child = Child.getSibling())
    updateAddressDieMap(Child);
}
Example #3
0
unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die,
                                        DieRangeInfo &ParentRI) {
  unsigned NumErrors = 0;

  if (!Die.isValid())
    return NumErrors;

  DWARFAddressRangesVector Ranges = Die.getAddressRanges();

  // Build RI for this DIE and check that ranges within this DIE do not
  // overlap.
  DieRangeInfo RI(Die);
  for (auto Range : Ranges) {
    if (!Range.valid()) {
      ++NumErrors;
      error() << "Invalid address range " << Range << "\n";
      continue;
    }

    // Verify that ranges don't intersect.
    const auto IntersectingRange = RI.insert(Range);
    if (IntersectingRange != RI.Ranges.end()) {
      ++NumErrors;
      error() << "DIE has overlapping address ranges: " << Range << " and "
              << *IntersectingRange << "\n";
      break;
    }
  }

  // Verify that children don't intersect.
  const auto IntersectingChild = ParentRI.insert(RI);
  if (IntersectingChild != ParentRI.Children.end()) {
    ++NumErrors;
    error() << "DIEs have overlapping address ranges:";
    Die.dump(OS, 0);
    IntersectingChild->Die.dump(OS, 0);
    OS << "\n";
  }

  // Verify that ranges are contained within their parent.
  bool ShouldBeContained = !Ranges.empty() && !ParentRI.Ranges.empty() &&
                           !(Die.getTag() == DW_TAG_subprogram &&
                             ParentRI.Die.getTag() == DW_TAG_subprogram);
  if (ShouldBeContained && !ParentRI.contains(RI)) {
    ++NumErrors;
    error() << "DIE address ranges are not "
               "contained in its parent's ranges:";
    Die.dump(OS, 0);
    ParentRI.Die.dump(OS, 0);
    OS << "\n";
  }

  // Recursively check children.
  for (DWARFDie Child : Die)
    NumErrors += verifyDieRanges(Child, RI);

  return NumErrors;
}
Example #4
0
unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die) {
  unsigned NumErrors = 0;
  for (auto Range : Die.getAddressRanges()) {
    if (Range.LowPC >= Range.HighPC) {
      ++NumErrors;
      OS << format("error: Invalid address range [0x%08" PRIx64
                   " - 0x%08" PRIx64 "].\n",
                   Range.LowPC, Range.HighPC);
    }
  }
  return NumErrors;
}
Example #5
0
static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
                          uint32_t *OffsetPtr, dwarf::Attribute Attr,
                          dwarf::Form Form, unsigned Indent) {
  if (!Die.isValid())
    return;
  const char BaseIndent[] = "            ";
  OS << BaseIndent;
  OS.indent(Indent+2);
  auto attrString = AttributeString(Attr);
  if (!attrString.empty())
    WithColor(OS, syntax::Attribute) << attrString;
  else
    WithColor(OS, syntax::Attribute).get() << format("DW_AT_Unknown_%x", Attr);
  
  auto formString = FormEncodingString(Form);
  if (!formString.empty())
    OS << " [" << formString << ']';
  else
    OS << format(" [DW_FORM_Unknown_%x]", Form);
  
  DWARFUnit *U = Die.getDwarfUnit();
  DWARFFormValue formValue(Form);
  
  if (!formValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr, U))
    return;
  
  OS << "\t(";
  
  StringRef Name;
  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;
      }
  } else if (Optional<uint64_t> Val = formValue.getAsUnsignedConstant())
    Name = AttributeValueString(Attr, *Val);
  
  if (!Name.empty())
    WithColor(OS, Color) << Name;
  else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line)
    OS << *formValue.getAsUnsignedConstant();
  else
    formValue.dump(OS);
  
  // 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) {
    if (const char *Name = Die.getAttributeValueAsReferencedDie(Attr).getName(DINameKind::LinkageName))
        OS << " \"" << Name << '\"';
  } 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, Die.getAddressRanges(), U->getAddressByteSize(),
               sizeof(BaseIndent)+Indent+4);
  }
  
  OS << ")\n";
}
Example #6
0
static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
                          uint32_t *OffsetPtr, dwarf::Attribute Attr,
                          dwarf::Form Form, unsigned Indent,
                          DIDumpOptions DumpOpts) {
  if (!Die.isValid())
    return;
  const char BaseIndent[] = "            ";
  OS << BaseIndent;
  OS.indent(Indent + 2);
  WithColor(OS, HighlightColor::Attribute) << formatv("{0}", Attr);

  if (DumpOpts.Verbose || DumpOpts.ShowForm)
    OS << formatv(" [{0}]", Form);

  DWARFUnit *U = Die.getDwarfUnit();
  DWARFFormValue FormValue = DWARFFormValue::createFromUnit(Form, U, OffsetPtr);

  OS << "\t(";

  StringRef Name;
  std::string File;
  auto Color = HighlightColor::Enumerator;
  if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) {
    Color = HighlightColor::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;
      }
  } else if (Optional<uint64_t> Val = FormValue.getAsUnsignedConstant())
    Name = AttributeValueString(Attr, *Val);

  if (!Name.empty())
    WithColor(OS, Color) << Name;
  else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line)
    OS << *FormValue.getAsUnsignedConstant();
  else if (Attr == DW_AT_high_pc && !DumpOpts.ShowForm && !DumpOpts.Verbose &&
           FormValue.getAsUnsignedConstant()) {
    if (DumpOpts.ShowAddresses) {
      // Print the actual address rather than the offset.
      uint64_t LowPC, HighPC, Index;
      if (Die.getLowAndHighPC(LowPC, HighPC, Index))
        OS << format("0x%016" PRIx64, HighPC);
      else
        FormValue.dump(OS, DumpOpts);
    }
  } else if (DWARFAttribute::mayHaveLocationDescription(Attr))
    dumpLocation(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4, DumpOpts);
  else
    FormValue.dump(OS, DumpOpts);

  std::string Space = DumpOpts.ShowAddresses ? " " : "";

  // 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) {
    if (const char *Name =
            Die.getAttributeValueAsReferencedDie(FormValue).getName(
                DINameKind::LinkageName))
      OS << Space << "\"" << Name << '\"';
  } else if (Attr == DW_AT_type) {
    OS << Space << "\"";
    dumpTypeName(OS, Die.getAttributeValueAsReferencedDie(FormValue));
    OS << '"';
  } else if (Attr == DW_AT_APPLE_property_attribute) {
    if (Optional<uint64_t> OptVal = FormValue.getAsUnsignedConstant())
      dumpApplePropertyAttribute(OS, *OptVal);
  } else if (Attr == DW_AT_ranges) {
    const DWARFObject &Obj = Die.getDwarfUnit()->getContext().getDWARFObj();
    // For DW_FORM_rnglistx we need to dump the offset separately, since
    // we have only dumped the index so far.
    if (FormValue.getForm() == DW_FORM_rnglistx)
      if (auto RangeListOffset =
              U->getRnglistOffset(*FormValue.getAsSectionOffset())) {
        DWARFFormValue FV = DWARFFormValue::createFromUValue(
            dwarf::DW_FORM_sec_offset, *RangeListOffset);
        FV.dump(OS, DumpOpts);
      }
    if (auto RangesOrError = Die.getAddressRanges())
      dumpRanges(Obj, OS, RangesOrError.get(), U->getAddressByteSize(),
                 sizeof(BaseIndent) + Indent + 4, DumpOpts);
    else
      WithColor::error() << "decoding address ranges: "
                         << toString(RangesOrError.takeError()) << '\n';
  }

  OS << ")\n";
}
Example #7
0
static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
                          uint32_t *OffsetPtr, dwarf::Attribute Attr,
                          dwarf::Form Form, unsigned Indent,
                          DIDumpOptions DumpOpts) {
  if (!Die.isValid())
    return;
  const char BaseIndent[] = "            ";
  OS << BaseIndent;
  OS.indent(Indent + 2);
  auto attrString = AttributeString(Attr);
  if (!attrString.empty())
    WithColor(OS, HighlightColor::Attribute) << attrString;
  else
    WithColor(OS, HighlightColor::Attribute).get()
        << format("DW_AT_Unknown_%x", Attr);

  if (DumpOpts.Verbose || DumpOpts.ShowForm) {
    auto formString = FormEncodingString(Form);
    if (!formString.empty())
      OS << " [" << formString << ']';
    else
      OS << format(" [DW_FORM_Unknown_%x]", Form);
  }

  DWARFUnit *U = Die.getDwarfUnit();
  DWARFFormValue formValue(Form);

  if (!formValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr,
                              U->getFormParams(), U))
    return;

  OS << "\t(";

  StringRef Name;
  std::string File;
  auto Color = HighlightColor::Enumerator;
  if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) {
    Color = HighlightColor::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;
      }
  } else if (Optional<uint64_t> Val = formValue.getAsUnsignedConstant())
    Name = AttributeValueString(Attr, *Val);

  if (!Name.empty())
    WithColor(OS, Color) << Name;
  else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line)
    OS << *formValue.getAsUnsignedConstant();
  else if (Attr == DW_AT_high_pc && !DumpOpts.ShowForm && !DumpOpts.Verbose &&
           formValue.getAsUnsignedConstant()) {
    if (DumpOpts.ShowAddresses) {
      // Print the actual address rather than the offset.
      uint64_t LowPC, HighPC, Index;
      if (Die.getLowAndHighPC(LowPC, HighPC, Index))
        OS << format("0x%016" PRIx64, HighPC);
      else
        formValue.dump(OS, DumpOpts);
    }
  } else if (Attr == DW_AT_location || Attr == DW_AT_frame_base ||
             Attr == DW_AT_data_member_location ||
             Attr == DW_AT_GNU_call_site_value)
    dumpLocation(OS, formValue, U, sizeof(BaseIndent) + Indent + 4, DumpOpts);
  else
    formValue.dump(OS, DumpOpts);

  // 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) {
    if (const char *Name = Die.getAttributeValueAsReferencedDie(Attr).getName(
            DINameKind::LinkageName))
      OS << " \"" << Name << '\"';
  } else if (Attr == DW_AT_type) {
    OS << " \"";
    dumpTypeName(OS, Die);
    OS << '"';
  } else if (Attr == DW_AT_APPLE_property_attribute) {
    if (Optional<uint64_t> OptVal = formValue.getAsUnsignedConstant())
      dumpApplePropertyAttribute(OS, *OptVal);
  } else if (Attr == DW_AT_ranges) {
    const DWARFObject &Obj = Die.getDwarfUnit()->getContext().getDWARFObj();
    dumpRanges(Obj, OS, Die.getAddressRanges(), U->getAddressByteSize(),
               sizeof(BaseIndent) + Indent + 4, DumpOpts);
  }

  OS << ")\n";
}