Skip to content
DwarfDebug.cpp 104 KiB
Newer Older
  // Emit function debug frame information
  for (std::vector<FunctionDebugFrameInfo>::iterator I = DebugFrames.begin(),
         E = DebugFrames.end(); I != E; ++I)
    EmitFunctionDebugFrame(*I);
  // Compute DIE offsets and sizes.
  SizeAndOffsets();
  // Emit all the DIEs into a debug info section
  EmitDebugInfo();
  // Corresponding abbreviations into a abbrev section.
  EmitAbbreviations();
  // Emit source line correspondence into a debug line section.
  EmitDebugLines();
  // Emit info into a debug pubnames section.
  EmitDebugPubNames();
  // Emit info into a debug str section.
  EmitDebugStr();
  // Emit info into a debug loc section.
  EmitDebugLoc();
  // Emit info into a debug aranges section.
  EmitDebugARanges();
  // Emit info into a debug ranges section.
  EmitDebugRanges();
  // Emit info into a debug macinfo section.
  EmitDebugMacInfo();
  // Emit inline info.
  EmitDebugInlineInfo();
  if (TimePassesIsEnabled)
    DebugTimer->stopTimer();
}
/// findAbstractVariable - Find abstract variable, if any, associated with Var.
DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &Var, unsigned FrameIdx,
                                              DILocation &ScopeLoc) {

  DbgVariable *AbsDbgVariable = AbstractVariables.lookup(Var.getNode());
  if (AbsDbgVariable)
    return AbsDbgVariable;

  DbgScope *Scope = AbstractScopes.lookup(ScopeLoc.getScope().getNode());
  if (!Scope)
    return NULL;

  AbsDbgVariable = new DbgVariable(Var, FrameIdx);
  Scope->AddVariable(AbsDbgVariable);
  AbstractVariables[Var.getNode()] = AbsDbgVariable;
  return AbsDbgVariable;
}

/// CollectVariableInfo - Populate DbgScope entries with variables' info.
void DwarfDebug::CollectVariableInfo() {
  if (!MMI) return;
  MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo();
  for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(),
         VE = VMap.end(); VI != VE; ++VI) {
    MetadataBase *MB = VI->first;
    MDNode *Var = dyn_cast_or_null<MDNode>(MB);
    if (!Var) continue;
    std::pair< unsigned, MDNode *> VP = VI->second;
    DILocation ScopeLoc(VP.second);

    DbgScope *Scope =
      ConcreteScopes.lookup(ScopeLoc.getOrigLocation().getNode());
    if (!Scope)
      Scope = DbgScopeMap.lookup(ScopeLoc.getScope().getNode()); 
    // If variable scope is not found then skip this variable.
    if (!Scope)
      continue;

    DbgVariable *RegVar = new DbgVariable(DV, VP.first);
    Scope->AddVariable(RegVar);
    if (DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VP.first, ScopeLoc))
      RegVar->setAbstractVariable(AbsDbgVariable);
/// BeginScope - Process beginning of a scope starting at Label.
void DwarfDebug::BeginScope(const MachineInstr *MI, unsigned Label) {
  InsnToDbgScopeMapTy::iterator I = DbgScopeBeginMap.find(MI);
  if (I == DbgScopeBeginMap.end())
    return;
  ScopeVector &SD = DbgScopeBeginMap[MI];
  for (ScopeVector::iterator SDI = SD.begin(), SDE = SD.end();
       SDI != SDE; ++SDI) 
    (*SDI)->setStartLabelID(Label);
}

/// EndScope - Process end of a scope.
void DwarfDebug::EndScope(const MachineInstr *MI) {
  InsnToDbgScopeMapTy::iterator I = DbgScopeEndMap.find(MI);
Devang Patel's avatar
Devang Patel committed
  if (I == DbgScopeEndMap.end())

  unsigned Label = MMI->NextLabelID();
  Asm->printLabel(Label);

  SmallVector<DbgScope *, 2> &SD = I->second;
  for (SmallVector<DbgScope *, 2>::iterator SDI = SD.begin(), SDE = SD.end();
       SDI != SDE; ++SDI) 
    (*SDI)->setEndLabelID(Label);
  return;
}

/// createDbgScope - Create DbgScope for the scope.
void DwarfDebug::createDbgScope(MDNode *Scope, MDNode *InlinedAt) {

  if (!InlinedAt) {
    DbgScope *WScope = DbgScopeMap.lookup(Scope);
    if (WScope)
      return;
    WScope = new DbgScope(NULL, DIDescriptor(Scope), NULL);
    DbgScopeMap.insert(std::make_pair(Scope, WScope));
    return;
  }

  DbgScope *WScope = DbgScopeMap.lookup(InlinedAt);
  if (WScope)
    return;

  WScope = new DbgScope(NULL, DIDescriptor(Scope), InlinedAt);
  DbgScopeMap.insert(std::make_pair(InlinedAt, WScope));
  DILocation DL(InlinedAt);
  createDbgScope(DL.getScope().getNode(), DL.getOrigLocation().getNode());
/// ExtractScopeInformation - Scan machine instructions in this function
/// and collect DbgScopes. Return true, if atleast one scope was found.
bool DwarfDebug::ExtractScopeInformation(MachineFunction *MF) {
  // If scope information was extracted using .dbg intrinsics then there is not
  // any need to extract these information by scanning each instruction.
  if (!DbgScopeMap.empty())
    return false;

  // Scan each instruction and create scopes. First build working set of scopes.
  for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
       I != E; ++I) {
    for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
         II != IE; ++II) {
      const MachineInstr *MInsn = II;
      DebugLoc DL = MInsn->getDebugLoc();
      if (DL.isUnknown()) continue;
      DebugLocTuple DLT = MF->getDebugLocTuple(DL);
      if (!DLT.Scope) continue;
      // There is no need to create another DIE for compile unit. For all
      // other scopes, create one DbgScope now. This will be translated 
      // into a scope DIE at the end.
      if (DIDescriptor(DLT.Scope).isCompileUnit()) continue;
      createDbgScope(DLT.Scope, DLT.InlinedAtLoc);
    }
  }


  // Build scope hierarchy using working set of scopes.
  for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
       I != E; ++I) {
    for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
         II != IE; ++II) {
      const MachineInstr *MInsn = II;
      DebugLoc DL = MInsn->getDebugLoc();
      if (DL.isUnknown())  continue;
      DebugLocTuple DLT = MF->getDebugLocTuple(DL);
      if (!DLT.Scope)  continue;
      // There is no need to create another DIE for compile unit. For all
      // other scopes, create one DbgScope now. This will be translated 
      // into a scope DIE at the end.
      if (DIDescriptor(DLT.Scope).isCompileUnit()) continue;
      DbgScope *Scope = getUpdatedDbgScope(DLT.Scope, MInsn, DLT.InlinedAtLoc);
      Scope->setLastInsn(MInsn);
    }
  }

  // If a scope's last instruction is not set then use its child scope's
  // last instruction as this scope's last instrunction.
  for (ValueMap<MDNode *, DbgScope *>::iterator DI = DbgScopeMap.begin(),
	 DE = DbgScopeMap.end(); DI != DE; ++DI) {
    if (DI->second->isAbstractScope())
      continue;
    assert (DI->second->getFirstInsn() && "Invalid first instruction!");
    DI->second->FixInstructionMarkers();
    assert (DI->second->getLastInsn() && "Invalid last instruction!");
  }

  // Each scope has first instruction and last instruction to mark beginning
  // and end of a scope respectively. Create an inverse map that list scopes
  // starts (and ends) with an instruction. One instruction may start (or end)
  // multiple scopes.
  for (ValueMap<MDNode *, DbgScope *>::iterator DI = DbgScopeMap.begin(),
	 DE = DbgScopeMap.end(); DI != DE; ++DI) {
    DbgScope *S = DI->second;
    if (S->isAbstractScope())
      continue;
    const MachineInstr *MI = S->getFirstInsn();
    assert (MI && "DbgScope does not have first instruction!");

    InsnToDbgScopeMapTy::iterator IDI = DbgScopeBeginMap.find(MI);
    if (IDI != DbgScopeBeginMap.end())
      IDI->second.push_back(S);
    else
      DbgScopeBeginMap[MI].push_back(S);

    MI = S->getLastInsn();
    assert (MI && "DbgScope does not have last instruction!");
    IDI = DbgScopeEndMap.find(MI);
    if (IDI != DbgScopeEndMap.end())
      IDI->second.push_back(S);
    else
      DbgScopeEndMap[MI].push_back(S);
/// BeginFunction - Gather pre-function debug information.  Assumes being
/// emitted immediately after the function entry point.
void DwarfDebug::BeginFunction(MachineFunction *MF) {
  this->MF = MF;
  if (!ShouldEmitDwarfDebug()) return;
  if (TimePassesIsEnabled)
    DebugTimer->startTimer();
#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
  if (!ExtractScopeInformation(MF))
    return;
  // Begin accumulating function debug information.
  MMI->BeginFunction(MF);
  // Assumes in correct section after the entry point.
  EmitLabel("func_begin", ++SubprogramCount);

  // Emit label for the implicitly defined dbg.stoppoint at the start of the
  // function.
  DebugLoc FDL = MF->getDefaultDebugLoc();
  if (!FDL.isUnknown()) {
    DebugLocTuple DLT = MF->getDebugLocTuple(FDL);
    unsigned LabelID = 0;
    DISubprogram SP = getDISubprogram(DLT.Scope);
      LabelID = RecordSourceLine(SP.getLineNumber(), 0, DLT.Scope);
      LabelID = RecordSourceLine(DLT.Line, DLT.Col, DLT.Scope);
  DebugLoc FDL = MF->getDefaultDebugLoc();
  if (!FDL.isUnknown()) {
    DebugLocTuple DLT = MF->getDebugLocTuple(FDL);
    unsigned LabelID = RecordSourceLine(DLT.Line, DLT.Col, DLT.Scope);
  if (TimePassesIsEnabled)
    DebugTimer->stopTimer();
/// EndFunction - Gather and emit post-function debug information.
///
void DwarfDebug::EndFunction(MachineFunction *MF) {
  if (!ShouldEmitDwarfDebug()) return;
  if (TimePassesIsEnabled)
    DebugTimer->startTimer();
#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
  if (DbgScopeMap.empty())
    return;
#endif
  // Define end label for subprogram.
  EmitLabel("func_end", SubprogramCount);
  // Get function line info.
  if (!Lines.empty()) {
    // Get section line info.
    unsigned ID = SectionMap.insert(Asm->getCurrentSection());
    if (SectionSourceLines.size() < ID) SectionSourceLines.resize(ID);
    std::vector<SrcLineInfo> &SectionLineInfos = SectionSourceLines[ID-1];
    // Append the function info to section info.
    SectionLineInfos.insert(SectionLineInfos.end(),
                            Lines.begin(), Lines.end());
  }
#ifndef ATTACH_DEBUG_INFO_TO_AN_INSN
  // Construct scopes for subprogram.
  if (CurrentFnDbgScope)
    ConstructCurrentFnDbgScope(CurrentFnDbgScope);
  else
    // FIXME: This is wrong. We are essentially getting past a problem with
    // debug information not being able to handle unreachable blocks that have
    // debug information in them. In particular, those unreachable blocks that
    // have "region end" info in them. That situation results in the "root
    // scope" not being created. If that's the case, then emit a "default"
    // scope, i.e., one that encompasses the whole function. This isn't
    // desirable. And a better way of handling this (and all of the debugging
    // information) needs to be explored.
    ConstructDefaultDbgScope(MF);
#else
  // Construct abstract scopes.
  for (SmallVector<DbgScope *, 4>::iterator AI = AbstractScopesList.begin(),
         AE = AbstractScopesList.end(); AI != AE; ++AI) 
    ConstructScopeDIE(*AI);
  ConstructScopeDIE(CurrentFnDbgScope);
#endif
  DebugFrames.push_back(FunctionDebugFrameInfo(SubprogramCount,
                                               MMI->getFrameMoves()));

  // Clear debug info
  if (CurrentFnDbgScope) {
    CurrentFnDbgScope = NULL;
    DbgScopeMap.clear();
    DbgScopeBeginMap.clear();
    DbgScopeEndMap.clear();
    ConcreteScopes.clear();
    AbstractScopesList.clear();
  if (TimePassesIsEnabled)
    DebugTimer->stopTimer();
/// RecordSourceLine - Records location information and associates it with a
/// label. Returns a unique label ID used to generate a label and provide
/// correspondence to the source line list.
unsigned DwarfDebug::RecordSourceLine(unsigned Line, unsigned Col, 
Devang Patel's avatar
Devang Patel committed
  if (!MMI)
    return 0;

  if (TimePassesIsEnabled)
    DebugTimer->startTimer();
  const char *Dir = NULL;
  const char *Fn = NULL;

  DIDescriptor Scope(S);
  if (Scope.isCompileUnit()) {
    DICompileUnit CU(S);
    Dir = CU.getDirectory();
    Fn = CU.getFilename();
  } else if (Scope.isSubprogram()) {
    DISubprogram SP(S);
    Dir = SP.getDirectory();
    Fn = SP.getFilename();
  } else if (Scope.isLexicalBlock()) {
    DILexicalBlock DB(S);
    Dir = DB.getDirectory();
    Fn = DB.getFilename();
  } else
    assert (0 && "Unexpected scope info");

  unsigned Src = GetOrCreateSourceID(Dir, Fn);
  unsigned ID = MMI->NextLabelID();
  Lines.push_back(SrcLineInfo(Line, Col, Src, ID));
  if (TimePassesIsEnabled)
    DebugTimer->stopTimer();
/// getOrCreateSourceID - Public version of GetOrCreateSourceID. This can be
/// timed. Look up the source id with the given directory and source file
/// names. If none currently exists, create a new id and insert it in the
/// SourceIds map. This can update DirectoryNames and SourceFileNames maps as
/// well.
unsigned DwarfDebug::getOrCreateSourceID(const std::string &DirName,
                                         const std::string &FileName) {
  if (TimePassesIsEnabled)
    DebugTimer->startTimer();
  unsigned SrcId = GetOrCreateSourceID(DirName.c_str(), FileName.c_str());
  if (TimePassesIsEnabled)
    DebugTimer->stopTimer();

  return SrcId;
/// RecordRegionStart - Indicate the start of a region.
Devang Patel's avatar
Devang Patel committed
unsigned DwarfDebug::RecordRegionStart(MDNode *N) {
  if (TimePassesIsEnabled)
    DebugTimer->startTimer();
Devang Patel's avatar
Devang Patel committed
  DbgScope *Scope = getOrCreateScope(N);
  unsigned ID = MMI->NextLabelID();
  if (!Scope->getStartLabelID()) Scope->setStartLabelID(ID);
  if (TimePassesIsEnabled)
    DebugTimer->stopTimer();
/// RecordRegionEnd - Indicate the end of a region.
Devang Patel's avatar
Devang Patel committed
unsigned DwarfDebug::RecordRegionEnd(MDNode *N) {
  if (TimePassesIsEnabled)
    DebugTimer->startTimer();
Devang Patel's avatar
Devang Patel committed
  DbgScope *Scope = getOrCreateScope(N);
  unsigned ID = MMI->NextLabelID();
  Scope->setEndLabelID(ID);
  if (TimePassesIsEnabled)
    DebugTimer->stopTimer();
/// RecordVariable - Indicate the declaration of a local variable.
Devang Patel's avatar
Devang Patel committed
void DwarfDebug::RecordVariable(MDNode *N, unsigned FrameIndex) {
  if (TimePassesIsEnabled)
    DebugTimer->startTimer();
Devang Patel's avatar
Devang Patel committed
  DIDescriptor Desc(N);
  DbgScope *Scope = NULL;
Devang Patel's avatar
Devang Patel committed
  if (Desc.getTag() == dwarf::DW_TAG_variable)
    Scope = getOrCreateScope(DIGlobalVariable(N).getContext().getNode());
  else {
    MDNode *Context = DIVariable(N).getContext().getNode();
    Scope = getOrCreateScope(Context);
  assert(Scope && "Unable to find the variable's scope");
  DbgVariable *DV = new DbgVariable(DIVariable(N), FrameIndex);
  Scope->AddVariable(DV);
  if (TimePassesIsEnabled)
    DebugTimer->stopTimer();
//===----------------------------------------------------------------------===//
// Emit Methods
//===----------------------------------------------------------------------===//

/// SizeAndOffsetDie - Compute the size and offset of a DIE.
///
unsigned DwarfDebug::SizeAndOffsetDie(DIE *Die, unsigned Offset, bool Last) {
  // Get the children.
  const std::vector<DIE *> &Children = Die->getChildren();
  // If not last sibling and has children then add sibling offset attribute.
  if (!Last && !Children.empty()) Die->AddSiblingOffset();

  // Record the abbreviation.
  AssignAbbrevNumber(Die->getAbbrev());

  // Get the abbreviation for this DIE.
  unsigned AbbrevNumber = Die->getAbbrevNumber();
  const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1];

  // Set DIE offset
  Die->setOffset(Offset);

  // Start the size with the size of abbreviation code.
  Offset += MCAsmInfo::getULEB128Size(AbbrevNumber);

  const SmallVector<DIEValue*, 32> &Values = Die->getValues();
  const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev->getData();
  // Size the DIE attribute values.
  for (unsigned i = 0, N = Values.size(); i < N; ++i)
    // Size attribute value.
    Offset += Values[i]->SizeOf(TD, AbbrevData[i].getForm());
  // Size the DIE children if any.
  if (!Children.empty()) {
    assert(Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes &&
           "Children flag not set");
    for (unsigned j = 0, M = Children.size(); j < M; ++j)
      Offset = SizeAndOffsetDie(Children[j], Offset, (j + 1) == M);
    // End of children marker.
    Offset += sizeof(int8_t);
  }
  Die->setSize(Offset - Die->getOffset());
  return Offset;
/// SizeAndOffsets - Compute the size and offset of all the DIEs.
///
void DwarfDebug::SizeAndOffsets() {
  // Compute size of compile unit header.
  static unsigned Offset =
    sizeof(int32_t) + // Length of Compilation Unit Info
    sizeof(int16_t) + // DWARF version number
    sizeof(int32_t) + // Offset Into Abbrev. Section
    sizeof(int8_t);   // Pointer Size (in bytes)
Devang Patel's avatar
Devang Patel committed
  SizeAndOffsetDie(ModuleCU->getDie(), Offset, true);
  CompileUnitOffsets[ModuleCU] = 0;
/// EmitInitial - Emit initial Dwarf declarations.  This is necessary for cc
/// tools to recognize the object file contains Dwarf information.
void DwarfDebug::EmitInitial() {
  // Check to see if we already emitted intial headers.
  if (didInitial) return;
  didInitial = true;
  const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
  // Dwarf sections base addresses.
  if (MAI->doesDwarfRequireFrameSection()) {
    Asm->OutStreamer.SwitchSection(TLOF.getDwarfFrameSection());
    EmitLabel("section_debug_frame", 0);
  }
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfInfoSection());
  EmitLabel("section_info", 0);
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfAbbrevSection());
  EmitLabel("section_abbrev", 0);
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfARangesSection());
  EmitLabel("section_aranges", 0);
  if (const MCSection *LineInfoDirective = TLOF.getDwarfMacroInfoSection()) {
    Asm->OutStreamer.SwitchSection(LineInfoDirective);
    EmitLabel("section_macinfo", 0);
  }
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfLineSection());
  EmitLabel("section_line", 0);
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfLocSection());
  EmitLabel("section_loc", 0);
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubNamesSection());
  EmitLabel("section_pubnames", 0);
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfStrSection());
  EmitLabel("section_str", 0);
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfRangesSection());
  EmitLabel("section_ranges", 0);
  Asm->OutStreamer.SwitchSection(TLOF.getTextSection());
  EmitLabel("text_begin", 0);
  Asm->OutStreamer.SwitchSection(TLOF.getDataSection());
  EmitLabel("data_begin", 0);
/// EmitDIE - Recusively Emits a debug information entry.
///
void DwarfDebug::EmitDIE(DIE *Die) {
  // Get the abbreviation for this DIE.
  unsigned AbbrevNumber = Die->getAbbrevNumber();
  const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1];
  // Emit the code (index) for the abbreviation.
  Asm->EmitULEB128Bytes(AbbrevNumber);
  if (Asm->isVerbose())
    Asm->EOL(std::string("Abbrev [" +
                         utostr(AbbrevNumber) +
                         "] 0x" + utohexstr(Die->getOffset()) +
                         ":0x" + utohexstr(Die->getSize()) + " " +
                         dwarf::TagString(Abbrev->getTag())));
  else
    Asm->EOL();
  SmallVector<DIEValue*, 32> &Values = Die->getValues();
  const SmallVector<DIEAbbrevData, 8> &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)");
    switch (Attr) {
    case dwarf::DW_AT_sibling:
      Asm->EmitInt32(Die->SiblingOffset());
      break;
    case dwarf::DW_AT_abstract_origin: {
      DIEEntry *E = cast<DIEEntry>(Values[i]);
      DIE *Origin = E->getEntry();
      unsigned Addr = Origin->getOffset();
      Asm->EmitInt32(Addr);
      break;
    }
    default:
      // Emit an attribute using the defined form.
      Values[i]->EmitValue(this, Form);
      break;
    }
    Asm->EOL(dwarf::AttributeString(Attr));
  }
  // 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)
      EmitDIE(Children[j]);
    Asm->EmitInt8(0); Asm->EOL("End Of Children Mark");
/// EmitDebugInfo / EmitDebugInfoPerCU - Emit the debug info section.
///
void DwarfDebug::EmitDebugInfoPerCU(CompileUnit *Unit) {
  DIE *Die = Unit->getDie();

  // Emit the compile units header.
  EmitLabel("info_begin", Unit->getID());

  // 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)
    sizeof(int32_t);  // FIXME - extra pad for gdb bug.

  Asm->EmitInt32(ContentSize);  Asm->EOL("Length of Compilation Unit Info");
  Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF version number");
  EmitSectionOffset("abbrev_begin", "section_abbrev", 0, 0, true, false);
  Asm->EOL("Offset Into Abbrev. Section");
  Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)");

  EmitDIE(Die);
  // FIXME - extra padding for gdb bug.
  Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
  Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
  Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
  Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
  EmitLabel("info_end", Unit->getID());

  Asm->EOL();
}
void DwarfDebug::EmitDebugInfo() {
  // Start debug info section.
  Asm->OutStreamer.SwitchSection(
                            Asm->getObjFileLowering().getDwarfInfoSection());
Devang Patel's avatar
Devang Patel committed
  EmitDebugInfoPerCU(ModuleCU);
/// EmitAbbreviations - Emit the abbreviation section.
void DwarfDebug::EmitAbbreviations() const {
  // Check to see if it is worth the effort.
  if (!Abbreviations.empty()) {
    // Start the debug abbrev section.
    Asm->OutStreamer.SwitchSection(
                            Asm->getObjFileLowering().getDwarfAbbrevSection());
    EmitLabel("abbrev_begin", 0);
    // For each abbrevation.
    for (unsigned i = 0, N = Abbreviations.size(); i < N; ++i) {
      // Get abbreviation data
      const DIEAbbrev *Abbrev = Abbreviations[i];
      // Emit the abbrevations code (base 1 index.)
      Asm->EmitULEB128Bytes(Abbrev->getNumber());
      Asm->EOL("Abbreviation Code");
      // Emit the abbreviations data.
      Abbrev->Emit(Asm);
    // Mark end of abbreviations.
    Asm->EmitULEB128Bytes(0); Asm->EOL("EOM(3)");
    EmitLabel("abbrev_end", 0);
    Asm->EOL();
  }
}
/// EmitEndOfLineMatrix - 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->EmitInt8(0); Asm->EOL("Extended Op");
  Asm->EmitInt8(TD->getPointerSize() + 1); Asm->EOL("Op size");
  Asm->EmitInt8(dwarf::DW_LNE_set_address); Asm->EOL("DW_LNE_set_address");
  EmitReference("section_end", SectionEnd); Asm->EOL("Section end label");
  // Mark end of matrix.
  Asm->EmitInt8(0); Asm->EOL("DW_LNE_end_sequence");
  Asm->EmitULEB128Bytes(1); Asm->EOL();
  Asm->EmitInt8(1); Asm->EOL();
}
/// EmitDebugLines - Emit source line information.
///
void DwarfDebug::EmitDebugLines() {
  // If the target is using .loc/.file, the assembler will be emitting the
  // .debug_line table automatically.
  // Minimum line delta, thus ranging from -10..(255-10).
  const int MinLineDelta = -(dwarf::DW_LNS_fixed_advance_pc + 1);
  // Maximum line delta, thus ranging from -10..(255-10).
  const int MaxLineDelta = 255 + MinLineDelta;
  // Start the dwarf line section.
  Asm->OutStreamer.SwitchSection(
                            Asm->getObjFileLowering().getDwarfLineSection());
  // Construct the section header.
  EmitDifference("line_end", 0, "line_begin", 0, true);
  Asm->EOL("Length of Source Line Info");
  EmitLabel("line_begin", 0);
  Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF version number");
  EmitDifference("line_prolog_end", 0, "line_prolog_begin", 0, true);
  Asm->EOL("Prolog Length");
  EmitLabel("line_prolog_begin", 0);
  Asm->EmitInt8(1); Asm->EOL("Minimum Instruction Length");
  Asm->EmitInt8(1); Asm->EOL("Default is_stmt_start flag");
  Asm->EmitInt8(MinLineDelta); Asm->EOL("Line Base Value (Special Opcodes)");
  Asm->EmitInt8(MaxLineDelta); Asm->EOL("Line Range Value (Special Opcodes)");
  Asm->EmitInt8(-MinLineDelta); Asm->EOL("Special Opcode Base");
  // Line number standard opcode encodings argument count
  Asm->EmitInt8(0); Asm->EOL("DW_LNS_copy arg count");
  Asm->EmitInt8(1); Asm->EOL("DW_LNS_advance_pc arg count");
  Asm->EmitInt8(1); Asm->EOL("DW_LNS_advance_line arg count");
  Asm->EmitInt8(1); Asm->EOL("DW_LNS_set_file arg count");
  Asm->EmitInt8(1); Asm->EOL("DW_LNS_set_column arg count");
  Asm->EmitInt8(0); Asm->EOL("DW_LNS_negate_stmt arg count");
  Asm->EmitInt8(0); Asm->EOL("DW_LNS_set_basic_block arg count");
  Asm->EmitInt8(0); Asm->EOL("DW_LNS_const_add_pc arg count");
  Asm->EmitInt8(1); Asm->EOL("DW_LNS_fixed_advance_pc arg count");
  // Emit directories.
  for (unsigned DI = 1, DE = getNumSourceDirectories()+1; DI != DE; ++DI) {
    Asm->EmitString(getSourceDirectoryName(DI));
    Asm->EOL("Directory");
  }
  Asm->EmitInt8(0); Asm->EOL("End of directories");

  // Emit files.
  for (unsigned SI = 1, SE = getNumSourceIds()+1; SI != SE; ++SI) {
    // Remember source id starts at 1.
    std::pair<unsigned, unsigned> Id = getSourceDirectoryAndFileIds(SI);
    Asm->EmitString(getSourceFileName(Id.second));
    Asm->EOL("Source");
    Asm->EmitULEB128Bytes(Id.first);
    Asm->EOL("Directory #");
    Asm->EmitULEB128Bytes(0);
    Asm->EOL("Mod date");
    Asm->EmitULEB128Bytes(0);
    Asm->EOL("File size");
  Asm->EmitInt8(0); Asm->EOL("End of files");
  EmitLabel("line_prolog_end", 0);
  // A sequence for each text section.
  unsigned SecSrcLinesSize = SectionSourceLines.size();
  for (unsigned j = 0; j < SecSrcLinesSize; ++j) {
    // Isolate current sections line info.
    const std::vector<SrcLineInfo> &LineInfos = SectionSourceLines[j];
      const MCSection *S = SectionMap[j + 1];
      O << '\t' << MAI->getCommentString() << " Section"
        << S->getName() << '\n';
    // Dwarf assumes we start with first line of first source file.
    unsigned Source = 1;
    unsigned Line = 1;
    // Construct rows of the address, source, line, column matrix.
    for (unsigned i = 0, N = LineInfos.size(); i < N; ++i) {
      const SrcLineInfo &LineInfo = LineInfos[i];
      unsigned LabelID = MMI->MappedLabel(LineInfo.getLabelID());
      if (!LabelID) continue;

      if (LineInfo.getLine() == 0) continue;

      if (!Asm->isVerbose())
        Asm->EOL();
      else {
        std::pair<unsigned, unsigned> SourceID =
          getSourceDirectoryAndFileIds(LineInfo.getSourceID());
        O << '\t' << MAI->getCommentString() << ' '
          << getSourceDirectoryName(SourceID.first) << ' '
          << getSourceFileName(SourceID.second)
          <<" :" << utostr_32(LineInfo.getLine()) << '\n';
      }
      // Define the line address.
      Asm->EmitInt8(0); Asm->EOL("Extended Op");
      Asm->EmitInt8(TD->getPointerSize() + 1); Asm->EOL("Op size");
      Asm->EmitInt8(dwarf::DW_LNE_set_address); Asm->EOL("DW_LNE_set_address");
      EmitReference("label",  LabelID); Asm->EOL("Location label");
      // If change of source, then switch to the new source.
      if (Source != LineInfo.getSourceID()) {
        Source = LineInfo.getSourceID();
        Asm->EmitInt8(dwarf::DW_LNS_set_file); Asm->EOL("DW_LNS_set_file");
        Asm->EmitULEB128Bytes(Source); Asm->EOL("New Source");
      }
      // If change of line.
      if (Line != LineInfo.getLine()) {
        // Determine offset.
        int Offset = LineInfo.getLine() - Line;
        int Delta = Offset - MinLineDelta;
        // Update line.
        Line = LineInfo.getLine();
        // If delta is small enough and in range...
        if (Delta >= 0 && Delta < (MaxLineDelta - 1)) {
          // ... then use fast opcode.
          Asm->EmitInt8(Delta - MinLineDelta); Asm->EOL("Line Delta");
        } else {
          // ... otherwise use long hand.
          Asm->EmitInt8(dwarf::DW_LNS_advance_line);
          Asm->EOL("DW_LNS_advance_line");
          Asm->EmitSLEB128Bytes(Offset); Asm->EOL("Line Offset");
          Asm->EmitInt8(dwarf::DW_LNS_copy); Asm->EOL("DW_LNS_copy");
        }
      } else {
        // Copy the previous row (different address or source)
        Asm->EmitInt8(dwarf::DW_LNS_copy); Asm->EOL("DW_LNS_copy");
      }
    }
    EmitEndOfLineMatrix(j + 1);
  }
  if (SecSrcLinesSize == 0)
    // Because we're emitting a debug_line section, we still need a line
    // table. The linker and friends expect it to exist. If there's nothing to
    // put into it, emit an empty table.
    EmitEndOfLineMatrix(1);
  EmitLabel("line_end", 0);
  Asm->EOL();
/// EmitCommonDebugFrame - Emit common frame info into a debug frame section.
///
void DwarfDebug::EmitCommonDebugFrame() {
  if (!MAI->doesDwarfRequireFrameSection())
  int stackGrowth =
    Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
      TargetFrameInfo::StackGrowsUp ?
    TD->getPointerSize() : -TD->getPointerSize();
  // Start the dwarf frame section.
  Asm->OutStreamer.SwitchSection(
                              Asm->getObjFileLowering().getDwarfFrameSection());
  EmitLabel("debug_frame_common", 0);
  EmitDifference("debug_frame_common_end", 0,
                 "debug_frame_common_begin", 0, true);
  Asm->EOL("Length of Common Information Entry");
  EmitLabel("debug_frame_common_begin", 0);
  Asm->EmitInt32((int)dwarf::DW_CIE_ID);
  Asm->EOL("CIE Identifier Tag");
  Asm->EmitInt8(dwarf::DW_CIE_VERSION);
  Asm->EOL("CIE Version");
  Asm->EmitString("");
  Asm->EOL("CIE Augmentation");
  Asm->EmitULEB128Bytes(1);
  Asm->EOL("CIE Code Alignment Factor");
  Asm->EmitSLEB128Bytes(stackGrowth);
  Asm->EOL("CIE Data Alignment Factor");
  Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), false));
  Asm->EOL("CIE RA Column");
  std::vector<MachineMove> Moves;
  RI->getInitialFrameState(Moves);
  EmitFrameMoves(NULL, 0, Moves, false);
  Asm->EmitAlignment(2, 0, 0, false);
  EmitLabel("debug_frame_common_end", 0);
/// EmitFunctionDebugFrame - Emit per function frame info into a debug frame
/// section.
void
DwarfDebug::EmitFunctionDebugFrame(const FunctionDebugFrameInfo&DebugFrameInfo){
  if (!MAI->doesDwarfRequireFrameSection())
  // Start the dwarf frame section.
  Asm->OutStreamer.SwitchSection(
                              Asm->getObjFileLowering().getDwarfFrameSection());
  EmitDifference("debug_frame_end", DebugFrameInfo.Number,
                 "debug_frame_begin", DebugFrameInfo.Number, true);
  Asm->EOL("Length of Frame Information Entry");
  EmitLabel("debug_frame_begin", DebugFrameInfo.Number);
  EmitSectionOffset("debug_frame_common", "section_debug_frame",
                    0, 0, true, false);
  Asm->EOL("FDE CIE offset");
  EmitReference("func_begin", DebugFrameInfo.Number);
  Asm->EOL("FDE initial location");
  EmitDifference("func_end", DebugFrameInfo.Number,
                 "func_begin", DebugFrameInfo.Number);
  Asm->EOL("FDE address range");
  EmitFrameMoves("func_begin", DebugFrameInfo.Number, DebugFrameInfo.Moves,
                 false);
  Asm->EmitAlignment(2, 0, 0, false);
  EmitLabel("debug_frame_end", DebugFrameInfo.Number);
void DwarfDebug::EmitDebugPubNamesPerCU(CompileUnit *Unit) {
  EmitDifference("pubnames_end", Unit->getID(),
                 "pubnames_begin", Unit->getID(), true);
  Asm->EOL("Length of Public Names Info");
  EmitLabel("pubnames_begin", Unit->getID());
  Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF Version");
  EmitSectionOffset("info_begin", "section_info",
                    Unit->getID(), 0, true, false);
  Asm->EOL("Offset of Compilation Unit Info");
  EmitDifference("info_end", Unit->getID(), "info_begin", Unit->getID(),
                 true);
  Asm->EOL("Compilation Unit Length");
  StringMap<DIE*> &Globals = Unit->getGlobals();
  for (StringMap<DIE*>::const_iterator
         GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) {
    const char *Name = GI->getKeyData();
    DIE * Entity = GI->second;

    Asm->EmitInt32(Entity->getOffset()); Asm->EOL("DIE offset");
    Asm->EmitString(Name, strlen(Name)); Asm->EOL("External Name");
  Asm->EmitInt32(0); Asm->EOL("End Mark");
  EmitLabel("pubnames_end", Unit->getID());
/// EmitDebugPubNames - Emit visible names into a debug pubnames section.
///
void DwarfDebug::EmitDebugPubNames() {
  // Start the dwarf pubnames section.
  Asm->OutStreamer.SwitchSection(
                          Asm->getObjFileLowering().getDwarfPubNamesSection());
Devang Patel's avatar
Devang Patel committed
  EmitDebugPubNamesPerCU(ModuleCU);