Skip to content
DwarfDebug.cpp 109 KiB
Newer Older
    Asm->OutStreamer.AddComment("Abbrev [" + Twine(AbbrevNumber) + "] 0x" +
                                Twine::utohexstr(Die->getOffset()) + ":0x" +
                                Twine::utohexstr(Die->getSize()) + " " +
                                dwarf::TagString(Abbrev->getTag()));
  Asm->EmitULEB128(AbbrevNumber);
  const SmallVectorImpl<DIEValue*> &Values = Die->getValues();
  const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev->getData();
  // Emit the DIE attribute values.
  for (unsigned i = 0, N = Values.size(); i < N; ++i) {
    unsigned Attr = AbbrevData[i].getAttribute();
    unsigned Form = AbbrevData[i].getForm();
    assert(Form && "Too many attributes for DIE (check abbreviation)");
      Asm->OutStreamer.AddComment(dwarf::AttributeString(Attr));
    switch (Attr) {
    case dwarf::DW_AT_abstract_origin: {
      DIEEntry *E = cast<DIEEntry>(Values[i]);
      DIE *Origin = E->getEntry();
      unsigned Addr = Origin->getOffset();
      if (Form == dwarf::DW_FORM_ref_addr) {
        // For DW_FORM_ref_addr, output the offset from beginning of debug info
        // section. Origin->getOffset() returns the offset from start of the
        // compile unit.
        DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
        Addr += Holder.getCUOffset(Origin->getCompileUnit());
      }
      Asm->OutStreamer.EmitIntValue(Addr,
          Form == dwarf::DW_FORM_ref_addr ? DIEEntry::getRefAddrSize(Asm) : 4);
    case dwarf::DW_AT_ranges: {
      // DW_AT_range Value encodes offset in debug_range section.
      DIEInteger *V = cast<DIEInteger>(Values[i]);
      if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) {
        Asm->EmitLabelPlusOffset(DwarfDebugRangeSectionSym,
                                 V->getValue(),
                                 4);
      } else {
        Asm->EmitLabelOffsetDifference(DwarfDebugRangeSectionSym,
                                       V->getValue(),
                                       DwarfDebugRangeSectionSym,
                                       4);
      }
    case dwarf::DW_AT_location: {
      if (DIELabel *L = dyn_cast<DIELabel>(Values[i])) {
        if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
Ulrich Weigand's avatar
 
Ulrich Weigand committed
          Asm->EmitLabelReference(L->getValue(), 4);
Ulrich Weigand's avatar
 
Ulrich Weigand committed
          Asm->EmitLabelDifference(L->getValue(), DwarfDebugLocSectionSym, 4);
        Values[i]->EmitValue(Asm, Form);
    }
    case dwarf::DW_AT_accessibility: {
      if (Asm->isVerbose()) {
        DIEInteger *V = cast<DIEInteger>(Values[i]);
        Asm->OutStreamer.AddComment(dwarf::AccessibilityString(V->getValue()));
      }
      Values[i]->EmitValue(Asm, Form);
      break;
    default:
      // Emit an attribute using the defined form.
      Values[i]->EmitValue(Asm, Form);
  // Emit the DIE children if any.
  if (Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes) {
    const std::vector<DIE *> &Children = Die->getChildren();
    for (unsigned j = 0, M = Children.size(); j < M; ++j)
      Asm->OutStreamer.AddComment("End Of Children Mark");
    Asm->EmitInt8(0);
// Emit the various dwarf units to the unit section USection with
// the abbreviations going into ASection.
void DwarfUnits::emitUnits(DwarfDebug *DD,
                           const MCSection *USection,
                           const MCSection *ASection,
                           const MCSymbol *ASectionSym) {
  Asm->OutStreamer.SwitchSection(USection);
  for (SmallVectorImpl<CompileUnit *>::iterator I = CUs.begin(),
         E = CUs.end(); I != E; ++I) {
    CompileUnit *TheCU = *I;
    DIE *Die = TheCU->getCUDie();
    // Emit the compile units header.
    Asm->OutStreamer
      .EmitLabel(Asm->GetTempSymbol(USection->getLabelBeginName(),
                                    TheCU->getUniqueID()));
    // Emit size of content not including length itself
    unsigned ContentSize = Die->getSize() +
      sizeof(int16_t) + // DWARF version number
      sizeof(int32_t) + // Offset Into Abbrev. Section
      sizeof(int8_t);   // Pointer Size (in bytes)
    Asm->OutStreamer.AddComment("Length of Compilation Unit Info");
    Asm->EmitInt32(ContentSize);
    Asm->OutStreamer.AddComment("DWARF version number");
    Asm->EmitInt16(DD->getDwarfVersion());
    Asm->OutStreamer.AddComment("Offset Into Abbrev. Section");
    Asm->EmitSectionOffset(Asm->GetTempSymbol(ASection->getLabelBeginName()),
                           ASectionSym);
    Asm->OutStreamer.AddComment("Address Size (in bytes)");
    Asm->EmitInt8(Asm->getDataLayout().getPointerSize());
    DD->emitDIE(Die, Abbreviations);
    Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol(USection->getLabelEndName(),
/// For a given compile unit DIE, returns offset from beginning of debug info.
unsigned DwarfUnits::getCUOffset(DIE *Die) {
  assert(Die->getTag() == dwarf::DW_TAG_compile_unit  &&
         "Input DIE should be compile unit in getCUOffset.");
Eric Christopher's avatar
Eric Christopher committed
  for (SmallVectorImpl<CompileUnit *>::iterator I = CUs.begin(), E = CUs.end();
       I != E; ++I) {
    CompileUnit *TheCU = *I;
    if (TheCU->getCUDie() == Die)
      return TheCU->getDebugInfoOffset();
  }
  llvm_unreachable("The compile unit DIE should belong to CUs in DwarfUnits.");
// Emit the debug info section.
void DwarfDebug::emitDebugInfo() {
  DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;

  Holder.emitUnits(this, Asm->getObjFileLowering().getDwarfInfoSection(),
                   Asm->getObjFileLowering().getDwarfAbbrevSection(),
                   DwarfAbbrevSectionSym);
// Emit the abbreviation section.
void DwarfDebug::emitAbbreviations() {
  if (!useSplitDwarf())
    emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection(),
                &Abbreviations);
  else
    emitSkeletonAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection());
}

void DwarfDebug::emitAbbrevs(const MCSection *Section,
                             std::vector<DIEAbbrev *> *Abbrevs) {
  // Check to see if it is worth the effort.
    // Start the debug abbrev section.
    Asm->OutStreamer.SwitchSection(Section);
    MCSymbol *Begin = Asm->GetTempSymbol(Section->getLabelBeginName());
    Asm->OutStreamer.EmitLabel(Begin);
    // For each abbrevation.
    for (unsigned i = 0, N = Abbrevs->size(); i < N; ++i) {
      // Get abbreviation data
      const DIEAbbrev *Abbrev = Abbrevs->at(i);
      // Emit the abbrevations code (base 1 index.)
      Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code");
      // Emit the abbreviations data.
    // Mark end of abbreviations.
    Asm->EmitULEB128(0, "EOM(3)");
    MCSymbol *End = Asm->GetTempSymbol(Section->getLabelEndName());
    Asm->OutStreamer.EmitLabel(End);
// Emit the last address of the section and the end of the line matrix.
void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) {
  // Define last address of section.
  Asm->OutStreamer.AddComment("Extended Op");
  Asm->EmitInt8(0);
  Asm->OutStreamer.AddComment("Op size");
  Asm->EmitInt8(Asm->getDataLayout().getPointerSize() + 1);
  Asm->OutStreamer.AddComment("DW_LNE_set_address");
  Asm->EmitInt8(dwarf::DW_LNE_set_address);

  Asm->OutStreamer.AddComment("Section end label");
  Asm->OutStreamer.EmitSymbolValue(Asm->GetTempSymbol("section_end",SectionEnd),
                                   Asm->getDataLayout().getPointerSize());
  // Mark end of matrix.
  Asm->OutStreamer.AddComment("DW_LNE_end_sequence");
  Asm->EmitInt8(0);
// Emit visible names into a hashed accelerator table section.
  DwarfAccelTable AT(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset,
                                           dwarf::DW_FORM_data4));
  for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
         E = CUMap.end(); I != E; ++I) {
    CompileUnit *TheCU = I->second;
    const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelNames();
    for (StringMap<std::vector<DIE*> >::const_iterator
           GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
      StringRef Name = GI->getKey();
      const std::vector<DIE *> &Entities = GI->second;
      for (std::vector<DIE *>::const_iterator DI = Entities.begin(),
             DE = Entities.end(); DI != DE; ++DI)
        AT.AddName(Name, (*DI));
    }
  }

  AT.FinalizeTable(Asm, "Names");
  Asm->OutStreamer.SwitchSection(
    Asm->getObjFileLowering().getDwarfAccelNamesSection());
  MCSymbol *SectionBegin = Asm->GetTempSymbol("names_begin");
  Asm->OutStreamer.EmitLabel(SectionBegin);

  // Emit the full data.
  AT.Emit(Asm, SectionBegin, &InfoHolder);
// Emit objective C classes and categories into a hashed accelerator table
// section.
  DwarfAccelTable AT(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset,
                                           dwarf::DW_FORM_data4));
  for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
         E = CUMap.end(); I != E; ++I) {
    CompileUnit *TheCU = I->second;
    const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelObjC();
    for (StringMap<std::vector<DIE*> >::const_iterator
           GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
      StringRef Name = GI->getKey();
      const std::vector<DIE *> &Entities = GI->second;
      for (std::vector<DIE *>::const_iterator DI = Entities.begin(),
             DE = Entities.end(); DI != DE; ++DI)
        AT.AddName(Name, (*DI));
    }
  }

  AT.FinalizeTable(Asm, "ObjC");
  Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering()
                                 .getDwarfAccelObjCSection());
  MCSymbol *SectionBegin = Asm->GetTempSymbol("objc_begin");
  Asm->OutStreamer.EmitLabel(SectionBegin);

  // Emit the full data.
  AT.Emit(Asm, SectionBegin, &InfoHolder);
// Emit namespace dies into a hashed accelerator table.
  DwarfAccelTable AT(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset,
                                           dwarf::DW_FORM_data4));
  for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
         E = CUMap.end(); I != E; ++I) {
    CompileUnit *TheCU = I->second;
    const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelNamespace();
    for (StringMap<std::vector<DIE*> >::const_iterator
           GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
      StringRef Name = GI->getKey();
      const std::vector<DIE *> &Entities = GI->second;
      for (std::vector<DIE *>::const_iterator DI = Entities.begin(),
             DE = Entities.end(); DI != DE; ++DI)
        AT.AddName(Name, (*DI));
    }
  }

  AT.FinalizeTable(Asm, "namespac");
  Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering()
                                 .getDwarfAccelNamespaceSection());
  MCSymbol *SectionBegin = Asm->GetTempSymbol("namespac_begin");
  Asm->OutStreamer.EmitLabel(SectionBegin);

  // Emit the full data.
  AT.Emit(Asm, SectionBegin, &InfoHolder);
// Emit type dies into a hashed accelerator table.
  std::vector<DwarfAccelTable::Atom> Atoms;
  Atoms.push_back(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset,
  Atoms.push_back(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag,
  Atoms.push_back(DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags,
                                        dwarf::DW_FORM_data1));
  DwarfAccelTable AT(Atoms);
  for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
         E = CUMap.end(); I != E; ++I) {
    CompileUnit *TheCU = I->second;
    const StringMap<std::vector<std::pair<DIE*, unsigned > > > &Names
      = TheCU->getAccelTypes();
    for (StringMap<std::vector<std::pair<DIE*, unsigned> > >::const_iterator
           GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
      StringRef Name = GI->getKey();
      const std::vector<std::pair<DIE *, unsigned> > &Entities = GI->second;
      for (std::vector<std::pair<DIE *, unsigned> >::const_iterator DI
             = Entities.begin(), DE = Entities.end(); DI !=DE; ++DI)
        AT.AddName(Name, (*DI).first, (*DI).second);
    }
  }

  AT.FinalizeTable(Asm, "types");
  Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering()
                                 .getDwarfAccelTypesSection());
  MCSymbol *SectionBegin = Asm->GetTempSymbol("types_begin");
  Asm->OutStreamer.EmitLabel(SectionBegin);

  // Emit the full data.
  AT.Emit(Asm, SectionBegin, &InfoHolder);
// Public name handling.
// The format for the various pubnames:
//
// dwarf pubnames - offset/name pairs where the offset is the offset into the CU
// for the DIE that is named.
//
// gnu pubnames - offset/index value/name tuples where the offset is the offset
// into the CU and the index value is computed according to the type of value
// for the DIE that is named.
//
// For type units the offset is the offset of the skeleton DIE. For split dwarf
// it's the offset within the debug_info/debug_types dwo section, however, the
// reference in the pubname header doesn't change.

/// computeIndexValue - Compute the gdb index value for the DIE and CU.
static dwarf::PubIndexEntryDescriptor computeIndexValue(CompileUnit *CU,
                                                        DIE *Die) {
  dwarf::GDBIndexEntryLinkage IsStatic =
      Die->findAttribute(dwarf::DW_AT_external) ? dwarf::GIEL_EXTERNAL
                                                : dwarf::GIEL_STATIC;

  switch (Die->getTag()) {
  case dwarf::DW_TAG_class_type:
  case dwarf::DW_TAG_structure_type:
  case dwarf::DW_TAG_union_type:
  case dwarf::DW_TAG_enumeration_type:
  case dwarf::DW_TAG_typedef:
  case dwarf::DW_TAG_base_type:
  case dwarf::DW_TAG_subrange_type:
    return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_TYPE, dwarf::GIEL_STATIC);
    return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_FUNCTION, IsStatic);
  case dwarf::DW_TAG_constant:
  case dwarf::DW_TAG_variable:
    return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_VARIABLE, IsStatic);
    return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_VARIABLE,
                                          dwarf::GIEL_STATIC);
/// emitDebugPubNames - Emit visible names into a debug pubnames section.
void DwarfDebug::emitDebugPubNames(bool GnuStyle) {
  const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection();
  const MCSection *PSec =
      GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubNamesSection()
               : Asm->getObjFileLowering().getDwarfPubNamesSection();

  typedef DenseMap<const MDNode*, CompileUnit*> CUMapType;
  for (CUMapType::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) {
    CompileUnit *TheCU = I->second;
    unsigned ID = TheCU->getUniqueID();

    if (TheCU->getGlobalNames().empty())
      continue;

    // Start the dwarf pubnames section.
    Asm->OutStreamer.SwitchSection(PSec);
    Asm->OutStreamer.AddComment("Length of Public Names Info");
    Asm->EmitLabelDifference(Asm->GetTempSymbol("pubnames_end", ID),
                             Asm->GetTempSymbol("pubnames_begin", ID), 4);

    Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_begin", ID));

    Asm->OutStreamer.AddComment("DWARF Version");

    Asm->OutStreamer.AddComment("Offset of Compilation Unit Info");
    Asm->EmitSectionOffset(Asm->GetTempSymbol(ISec->getLabelBeginName(), ID),
                           DwarfInfoSectionSym);

    Asm->OutStreamer.AddComment("Compilation Unit Length");
    Asm->EmitLabelDifference(Asm->GetTempSymbol(ISec->getLabelEndName(), ID),
                             Asm->GetTempSymbol(ISec->getLabelBeginName(), ID),
                             4);

    // Emit the pubnames for this compilation unit.
    const StringMap<DIE*> &Globals = TheCU->getGlobalNames();
    for (StringMap<DIE*>::const_iterator
           GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) {
      const char *Name = GI->getKeyData();

      Asm->OutStreamer.AddComment("DIE offset");
      Asm->EmitInt32(Entity->getOffset());

        dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheCU, Entity);
        Asm->OutStreamer.AddComment(
            Twine("Kind: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + ", " +
            dwarf::GDBIndexEntryLinkageString(Desc.Linkage));
        Asm->EmitInt8(Desc.toBits());
      if (Asm->isVerbose())
        Asm->OutStreamer.AddComment("External Name");
      Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength()+1));
    }

    Asm->OutStreamer.AddComment("End Mark");
    Asm->EmitInt32(0);
    Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_end", ID));
  }
}

void DwarfDebug::emitDebugPubTypes(bool GnuStyle) {
  const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection();
  const MCSection *PSec = Asm->getObjFileLowering().getDwarfPubTypesSection();

  for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
                                                         E = CUMap.end();
       I != E; ++I) {
    CompileUnit *TheCU = I->second;
Eric Christopher's avatar
Eric Christopher committed
    // Start the dwarf pubtypes section.
    Asm->OutStreamer.SwitchSection(PSec);
    Asm->OutStreamer.AddComment("Length of Public Types Info");
    Asm->EmitLabelDifference(
        Asm->GetTempSymbol("pubtypes_end", TheCU->getUniqueID()),
        Asm->GetTempSymbol("pubtypes_begin", TheCU->getUniqueID()), 4);
    Asm->OutStreamer.EmitLabel(
        Asm->GetTempSymbol("pubtypes_begin", TheCU->getUniqueID()));
    if (Asm->isVerbose())
      Asm->OutStreamer.AddComment("DWARF Version");
    Asm->OutStreamer.AddComment("Offset of Compilation Unit Info");
    Asm->EmitSectionOffset(
        Asm->GetTempSymbol(ISec->getLabelBeginName(), TheCU->getUniqueID()),
        DwarfInfoSectionSym);
    Asm->OutStreamer.AddComment("Compilation Unit Length");
    Asm->EmitLabelDifference(
        Asm->GetTempSymbol(ISec->getLabelEndName(), TheCU->getUniqueID()),
        Asm->GetTempSymbol(ISec->getLabelBeginName(), TheCU->getUniqueID()), 4);
    const StringMap<DIE *> &Globals = TheCU->getGlobalTypes();
    for (StringMap<DIE *>::const_iterator GI = Globals.begin(),
                                          GE = Globals.end();
         GI != GE; ++GI) {
      const char *Name = GI->getKeyData();
      if (Asm->isVerbose())
        Asm->OutStreamer.AddComment("DIE offset");
      Asm->EmitInt32(Entity->getOffset());
        dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheCU, Entity);
        Asm->OutStreamer.AddComment(
            Twine("Kind: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + ", " +
            dwarf::GDBIndexEntryLinkageString(Desc.Linkage));
        Asm->EmitInt8(Desc.toBits());
      if (Asm->isVerbose())
        Asm->OutStreamer.AddComment("External Name");

Benjamin Kramer's avatar
Benjamin Kramer committed
      // Emit the name with a terminating null byte.
      Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength() + 1));
    Asm->OutStreamer.AddComment("End Mark");
    Asm->EmitInt32(0);
    Asm->OutStreamer.EmitLabel(
        Asm->GetTempSymbol("pubtypes_end", TheCU->getUniqueID()));
// Emit strings into a string section.
void DwarfUnits::emitStrings(const MCSection *StrSection,
                             const MCSection *OffsetSection = NULL,
                             const MCSymbol *StrSecSym = NULL) {
  Asm->OutStreamer.SwitchSection(StrSection);
  // Get all of the string pool entries and put them in an array by their ID so
  // we can sort them.
  SmallVector<std::pair<unsigned,
Eric Christopher's avatar
Eric Christopher committed
                 StringMapEntry<std::pair<MCSymbol*, unsigned> >*>, 64> Entries;
  for (StringMap<std::pair<MCSymbol*, unsigned> >::iterator
         I = StringPool.begin(), E = StringPool.end();
       I != E; ++I)
    Entries.push_back(std::make_pair(I->second.second, &*I));
  array_pod_sort(Entries.begin(), Entries.end());
  for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
    // Emit a label for reference from debug information entries.
    Asm->OutStreamer.EmitLabel(Entries[i].second->getValue().first);
Benjamin Kramer's avatar
Benjamin Kramer committed
    // Emit the string itself with a terminating null byte.
    Asm->OutStreamer.EmitBytes(StringRef(Entries[i].second->getKeyData(),
                                         Entries[i].second->getKeyLength()+1));

  // If we've got an offset section go ahead and emit that now as well.
  if (OffsetSection) {
    Asm->OutStreamer.SwitchSection(OffsetSection);
    unsigned offset = 0;
    unsigned size = 4; // FIXME: DWARF64 is 8.
    for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
      Asm->OutStreamer.EmitIntValue(offset, size);
      offset += Entries[i].second->getKeyLength() + 1;
    }
  }
// Emit strings into a string section.
void DwarfUnits::emitAddresses(const MCSection *AddrSection) {

  if (AddressPool.empty()) return;

  // Start the dwarf addr section.
  Asm->OutStreamer.SwitchSection(AddrSection);

  // Order the address pool entries by ID
  SmallVector<const MCExpr *, 64> Entries(AddressPool.size());
  for (DenseMap<const MCExpr *, unsigned>::iterator I = AddressPool.begin(),
                                                    E = AddressPool.end();
    Entries[I->second] = I->first;

  for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
Ulrich Weigand's avatar
 
Ulrich Weigand committed
    // Emit an expression for reference from debug information entries.
    if (const MCExpr *Expr = Entries[i])
Ulrich Weigand's avatar
 
Ulrich Weigand committed
      Asm->OutStreamer.EmitValue(Expr, Asm->getDataLayout().getPointerSize());
    else
      Asm->OutStreamer.EmitIntValue(0, Asm->getDataLayout().getPointerSize());
  }

}

// Emit visible names into a debug str section.
void DwarfDebug::emitDebugStr() {
  DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
  Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection());
}

Eric Christopher's avatar
Eric Christopher committed
// Emit locations into the debug loc section.
void DwarfDebug::emitDebugLoc() {
  if (DotDebugLocEntries.empty())
    return;

  for (SmallVectorImpl<DotDebugLocEntry>::iterator
         I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end();
       I != E; ++I) {
    DotDebugLocEntry &Entry = *I;
    if (I + 1 != DotDebugLocEntries.end())
      Entry.Merge(I+1);
  }

  Asm->OutStreamer.SwitchSection(
    Asm->getObjFileLowering().getDwarfLocSection());
  unsigned char Size = Asm->getDataLayout().getPointerSize();
  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", 0));
  unsigned index = 1;
  for (SmallVectorImpl<DotDebugLocEntry>::iterator
         I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end();
Devang Patel's avatar
Devang Patel committed
       I != E; ++I, ++index) {
    DotDebugLocEntry &Entry = *I;
    if (Entry.isMerged()) continue;
    if (Entry.isEmpty()) {
      Asm->OutStreamer.EmitIntValue(0, Size);
      Asm->OutStreamer.EmitIntValue(0, Size);
      Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", index));
      Asm->OutStreamer.EmitSymbolValue(Entry.getBeginSym(), Size);
      Asm->OutStreamer.EmitSymbolValue(Entry.getEndSym(), Size);
      DIVariable DV(Entry.getVariable());
      Asm->OutStreamer.AddComment("Loc expr size");
      MCSymbol *begin = Asm->OutStreamer.getContext().CreateTempSymbol();
      MCSymbol *end = Asm->OutStreamer.getContext().CreateTempSymbol();
      Asm->EmitLabelDifference(end, begin, 2);
      Asm->OutStreamer.EmitLabel(begin);
Eric Christopher's avatar
Eric Christopher committed
            (BTy.getEncoding()  == dwarf::DW_ATE_signed
             || BTy.getEncoding() == dwarf::DW_ATE_signed_char)) {
          Asm->OutStreamer.AddComment("DW_OP_consts");
          Asm->EmitInt8(dwarf::DW_OP_consts);
        } else {
          Asm->OutStreamer.AddComment("DW_OP_constu");
          Asm->EmitInt8(dwarf::DW_OP_constu);
        MachineLocation Loc = Entry.getLoc();
Eric Christopher's avatar
Eric Christopher committed
        if (!DV.hasComplexAddress())
          Asm->EmitDwarfRegOp(Loc, DV.isIndirect());
        else {
          // Complex address entry.
          unsigned N = DV.getNumAddrElements();
          unsigned i = 0;
          if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpPlus) {
              Asm->EmitDwarfRegOp(Loc, DV.isIndirect());
              Asm->OutStreamer.AddComment("DW_OP_deref");
              Asm->EmitInt8(dwarf::DW_OP_deref);
              Asm->OutStreamer.AddComment("DW_OP_plus_uconst");
              Asm->EmitInt8(dwarf::DW_OP_plus_uconst);
              Asm->EmitSLEB128(DV.getAddrElement(1));
            } else {
              // If first address element is OpPlus then emit
              // DW_OP_breg + Offset instead of DW_OP_reg + Offset.
              MachineLocation TLoc(Loc.getReg(), DV.getAddrElement(1));
              Asm->EmitDwarfRegOp(TLoc, DV.isIndirect());
            Asm->EmitDwarfRegOp(Loc, DV.isIndirect());
          // Emit remaining complex address elements.
          for (; i < N; ++i) {
            uint64_t Element = DV.getAddrElement(i);
            if (Element == DIBuilder::OpPlus) {
              Asm->EmitInt8(dwarf::DW_OP_plus_uconst);
              Asm->EmitULEB128(DV.getAddrElement(++i));
            } else if (Element == DIBuilder::OpDeref) {
                Asm->EmitInt8(dwarf::DW_OP_deref);
            } else
              llvm_unreachable("unknown Opcode found in complex address");
      // else ... ignore constant fp. There is not any good way to
      // to represent them here in dwarf.
      Asm->OutStreamer.EmitLabel(end);
struct SymbolCUSorter {
  SymbolCUSorter(const MCStreamer &s) : Streamer(s) {}
  const MCStreamer &Streamer;

  bool operator() (const SymbolCU &A, const SymbolCU &B) {
    unsigned IA = A.Sym ? Streamer.GetSymbolOrder(A.Sym) : 0;
    unsigned IB = B.Sym ? Streamer.GetSymbolOrder(B.Sym) : 0;

    // Symbols with no order assigned should be placed at the end.
    // (e.g. section end labels)
    if (IA == 0)
      IA = (unsigned)(-1);
    if (IB == 0)
      IB = (unsigned)(-1);
    return IA < IB;
  }
};

static bool SectionSort(const MCSection *A, const MCSection *B) {
    std::string LA = (A ? A->getLabelBeginName() : "");
    std::string LB = (B ? B->getLabelBeginName() : "");
    return LA < LB;
}

static bool CUSort(const CompileUnit *A, const CompileUnit *B) {
    return (A->getUniqueID() < B->getUniqueID());
}

struct ArangeSpan {
  const MCSymbol *Start, *End;
};

// Emit a debug aranges section, containing a CU lookup for any
// address we can tie back to a CU.
void DwarfDebug::emitDebugARanges() {
  // Start the dwarf aranges section.
Eric Christopher's avatar
Eric Christopher committed
  Asm->OutStreamer
      .SwitchSection(Asm->getObjFileLowering().getDwarfARangesSection());

  typedef DenseMap<CompileUnit *, std::vector<ArangeSpan> > SpansType;

  SpansType Spans;

  // Build a list of sections used.
  std::vector<const MCSection *> Sections;
  for (SectionMapType::iterator it = SectionMap.begin(); it != SectionMap.end();
       it++) {
    const MCSection *Section = it->first;
    Sections.push_back(Section);
  }

  // Sort the sections into order.
  // This is only done to ensure consistent output order across different runs.
  std::sort(Sections.begin(), Sections.end(), SectionSort);

  // Build a set of address spans, sorted by CU.
  for (size_t SecIdx=0;SecIdx<Sections.size();SecIdx++) {
    const MCSection *Section = Sections[SecIdx];
    SmallVector<SymbolCU, 8> &List = SectionMap[Section];
    if (List.size() < 2)
      continue;

    // Sort the symbols by offset within the section.
    SymbolCUSorter sorter(Asm->OutStreamer);
    std::sort(List.begin(), List.end(), sorter);

    // If we have no section (e.g. common), just write out
    // individual spans for each symbol.
    if (Section == NULL) {
      for (size_t n = 0; n < List.size(); n++) {
        const SymbolCU &Cur = List[n];

        ArangeSpan Span;
        Span.Start = Cur.Sym;
        Span.End = NULL;
        if (Cur.CU)
          Spans[Cur.CU].push_back(Span);
      }
    } else {
      // Build spans between each label.
      const MCSymbol *StartSym = List[0].Sym;
      for (size_t n = 1; n < List.size(); n++) {
        const SymbolCU &Prev = List[n - 1];
        const SymbolCU &Cur = List[n];

        // Try and build the longest span we can within the same CU.
        if (Cur.CU != Prev.CU) {
          ArangeSpan Span;
          Span.Start = StartSym;
          Span.End = Cur.Sym;
          Spans[Prev.CU].push_back(Span);
          StartSym = Cur.Sym;
        }
      }
    }
  }

  const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection();
  unsigned PtrSize = Asm->getDataLayout().getPointerSize();

  // Build a list of CUs used.
  std::vector<CompileUnit *> CUs;
  for (SpansType::iterator it = Spans.begin(); it != Spans.end(); it++) {
    CompileUnit *CU = it->first;
    CUs.push_back(CU);
  }

  // Sort the CU list (again, to ensure consistent output order).
  std::sort(CUs.begin(), CUs.end(), CUSort);

  // Emit an arange table for each CU we used.
  for (size_t CUIdx=0;CUIdx<CUs.size();CUIdx++) {
    CompileUnit *CU = CUs[CUIdx];
    std::vector<ArangeSpan> &List = Spans[CU];

    // Emit size of content not including length itself.
    unsigned ContentSize
        = sizeof(int16_t) // DWARF ARange version number
        + sizeof(int32_t) // Offset of CU in the .debug_info section
        + sizeof(int8_t)  // Pointer Size (in bytes)
        + sizeof(int8_t); // Segment Size (in bytes)

    unsigned TupleSize = PtrSize * 2;

    // 7.20 in the Dwarf specs requires the table to be aligned to a tuple.
    unsigned Padding = 0;
    while (((sizeof(int32_t) + ContentSize + Padding) % TupleSize) != 0)
      Padding++;

    ContentSize += Padding;
    ContentSize += (List.size() + 1) * TupleSize;

    // For each compile unit, write the list of spans it covers.
    Asm->OutStreamer.AddComment("Length of ARange Set");
    Asm->EmitInt32(ContentSize);
    Asm->OutStreamer.AddComment("DWARF Arange version number");
    Asm->EmitInt16(dwarf::DW_ARANGES_VERSION);
    Asm->OutStreamer.AddComment("Offset Into Debug Info Section");
    Asm->EmitSectionOffset(
        Asm->GetTempSymbol(ISec->getLabelBeginName(), CU->getUniqueID()),
        DwarfInfoSectionSym);
    Asm->OutStreamer.AddComment("Address Size (in bytes)");
    Asm->EmitInt8(PtrSize);
    Asm->OutStreamer.AddComment("Segment Size (in bytes)");
    Asm->EmitInt8(0);

    for (unsigned n = 0; n < Padding; n++)
      Asm->EmitInt8(0xff);

    for (unsigned n = 0; n < List.size(); n++) {
      const ArangeSpan &Span = List[n];
      Asm->EmitLabelReference(Span.Start, PtrSize);

      // Calculate the size as being from the span start to it's end.
      // If we have no valid end symbol, then we just cover the first byte.
      // (this sucks, but I can't seem to figure out how to get the size)
      if (Span.End)
        Asm->EmitLabelDifference(Span.End, Span.Start, PtrSize);
      else
        Asm->OutStreamer.EmitIntValue(1, PtrSize);
    }

    Asm->OutStreamer.AddComment("ARange terminator");
    Asm->OutStreamer.EmitIntValue(0, PtrSize);
    Asm->OutStreamer.EmitIntValue(0, PtrSize);
  }
// Emit visible names into a debug ranges section.
void DwarfDebug::emitDebugRanges() {
  // Start the dwarf ranges section.
Eric Christopher's avatar
Eric Christopher committed
  Asm->OutStreamer
      .SwitchSection(Asm->getObjFileLowering().getDwarfRangesSection());
  unsigned char Size = Asm->getDataLayout().getPointerSize();
  for (SmallVectorImpl<const MCSymbol *>::iterator
         I = DebugRangeSymbols.begin(), E = DebugRangeSymbols.end();
      Asm->OutStreamer.EmitSymbolValue(const_cast<MCSymbol*>(*I), Size);
      Asm->OutStreamer.EmitIntValue(0, Size);
// Emit visible names into a debug macinfo section.
void DwarfDebug::emitDebugMacInfo() {
  if (const MCSection *LineInfo =
      Asm->getObjFileLowering().getDwarfMacroInfoSection()) {
    // Start the dwarf macinfo section.
    Asm->OutStreamer.SwitchSection(LineInfo);
Eric Christopher's avatar
Eric Christopher committed
// DWARF5 Experimental Separate Dwarf emitters.

// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list,
// DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id,
// DW_AT_ranges_base, DW_AT_addr_base. If DW_AT_ranges is present,
// DW_AT_low_pc and DW_AT_high_pc are not used, and vice versa.
CompileUnit *DwarfDebug::constructSkeletonCU(const CompileUnit *CU) {

  DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
  CompileUnit *NewCU = new CompileUnit(CU->getUniqueID(), Die, CU->getNode(),
                                       Asm, this, &SkeletonHolder);
  NewCU->addLocalString(Die, dwarf::DW_AT_GNU_dwo_name,
                        DICompileUnit(CU->getNode()).getSplitDebugFilename());
Eric Christopher's avatar
Eric Christopher committed
  // Relocate to the beginning of the addr_base section, else 0 for the
  // beginning of the one for this compile unit.
  if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
    NewCU->addLabel(Die, dwarf::DW_AT_GNU_addr_base, dwarf::DW_FORM_sec_offset,
                    DwarfAddrSectionSym);
  else
Eric Christopher's avatar
Eric Christopher committed
    NewCU->addUInt(Die, dwarf::DW_AT_GNU_addr_base,
                   dwarf::DW_FORM_sec_offset, 0);

  // 2.17.1 requires that we use DW_AT_low_pc for a single entry point
  // into an entity. We're using 0, or a NULL label for this.
  NewCU->addUInt(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0);
  // DW_AT_stmt_list is a offset of line number information for this
  // compile unit in debug_line section.
  // FIXME: Should handle multiple compile units.
  if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
    NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset,
    NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset, 0);
    NewCU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
  // Flag to let the linker know we have emitted new style pubnames.
  if (GenerateGnuPubSections)
    NewCU->addFlag(Die, dwarf::DW_AT_GNU_pubnames);

void DwarfDebug::emitSkeletonAbbrevs(const MCSection *Section) {
  assert(useSplitDwarf() && "No split dwarf debug info?");
  emitAbbrevs(Section, &SkeletonAbbrevs);
Eric Christopher's avatar
Eric Christopher committed
// Emit the .debug_info.dwo section for separated dwarf. This contains the
// compile units that would normally be in debug_info.
void DwarfDebug::emitDebugInfoDWO() {
  assert(useSplitDwarf() && "No split dwarf debug info?");
  InfoHolder.emitUnits(this, Asm->getObjFileLowering().getDwarfInfoDWOSection(),
                       Asm->getObjFileLowering().getDwarfAbbrevDWOSection(),
                       DwarfAbbrevDWOSectionSym);
}

// Emit the .debug_abbrev.dwo section for separated dwarf. This contains the
// abbreviations for the .debug_info.dwo section.
void DwarfDebug::emitDebugAbbrevDWO() {
  assert(useSplitDwarf() && "No split dwarf?");
  emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevDWOSection(),
              &Abbreviations);

// Emit the .debug_str.dwo section for separated dwarf. This contains the
// string section and is identical in format to traditional .debug_str
// sections.
void DwarfDebug::emitDebugStrDWO() {
  assert(useSplitDwarf() && "No split dwarf?");
Eric Christopher's avatar
Eric Christopher committed
  const MCSection *OffSec = Asm->getObjFileLowering()
                            .getDwarfStrOffDWOSection();
  const MCSymbol *StrSym = DwarfStrSectionSym;
  InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(),
                         OffSec, StrSym);