//----------------------------------------------------------------------
// Parse
//
// Parses the .debug_info section and uses the .debug_abbrev section
// and various other sections in the SymbolFileDWARF class and calls the
// supplied callback function each time a compile unit header, or debug
// information entry is successfully parsed. This function can be used
// for different tasks such as parsing the file contents into a
// structured data, dumping, verifying and much more.
//----------------------------------------------------------------------
void DWARFDebugInfo::Parse(SymbolFileDWARF *dwarf2Data, Callback callback,
                           void *userData) {
  if (dwarf2Data) {
    lldb::offset_t offset = 0;
    uint32_t depth = 0;
    DWARFDebugInfoEntry die;

    DWARFCompileUnitSP cu;
    while ((cu = DWARFCompileUnit::Extract(dwarf2Data, &offset))) {
      const dw_offset_t next_cu_offset = cu->GetNextCompileUnitOffset();

      depth = 0;
      // Call the callback function with no DIE pointer for the compile unit
      // and get the offset that we are to continue to parse from
      offset = callback(dwarf2Data, cu.get(), NULL, offset, depth, userData);

      // Make sure we are within our compile unit
      if (offset < next_cu_offset) {
        // We are in our compile unit, parse starting at the offset
        // we were told to parse
        bool done = false;
        while (!done && die.Extract(dwarf2Data, cu.get(), &offset)) {
          // Call the callback function with DIE pointer that falls within the
          // compile unit
          offset =
              callback(dwarf2Data, cu.get(), &die, offset, depth, userData);

          if (die.IsNULL()) {
            if (depth)
              --depth;
            else
              done = true; // We are done with this compile unit!
          } else if (die.HasChildren())
            ++depth;
        }
      }

      // Make sure the offset returned is valid, and if not stop parsing.
      // Returning DW_INVALID_OFFSET from this callback is a good way to end
      // all parsing
      if (!dwarf2Data->get_debug_info_data().ValidOffset(offset))
        break;

      // Make sure we start on a proper
      offset = next_cu_offset;
    }
  }
}
Beispiel #2
0
static dw_offset_t FindCallbackString
(
    SymbolFileDWARF* dwarf2Data,
    DWARFCompileUnitSP& cu_sp,
    DWARFDebugInfoEntry* die,
    const dw_offset_t next_offset,
    const uint32_t curr_depth,
    void* userData
)
{
    FindCallbackStringInfo* info = (FindCallbackStringInfo*)userData;
    const DWARFCompileUnit* cu = cu_sp.get();

    if (die)
    {
        const char* die_name = die->GetName(dwarf2Data, cu);
        if (die_name)
        {
            if (info->regex)
            {
                if (info->regex->Execute(die_name))
                    info->die_offsets.push_back(die->GetOffset());
            }
            else
            {
                if ((info->ignore_case ? strcasecmp(die_name, info->name) : strcmp(die_name, info->name)) == 0)
                    info->die_offsets.push_back(die->GetOffset());
            }
        }
    }

    // Just return the current offset to parse the next CU or DIE entry
    return next_offset;
}
Beispiel #3
0
static dw_offset_t
DWARFDebugInfo_ParseCallback
(
    SymbolFileDWARF* dwarf2Data,
    DWARFCompileUnitSP& cu_sp,
    DWARFDebugInfoEntry* die,
    const dw_offset_t next_offset,
    const uint32_t curr_depth,
    void* userData
)
{
    DWARFDebugInfo* debug_info = (DWARFDebugInfo*)userData;
    DWARFCompileUnit* cu = cu_sp.get();
    if (die)
    {
        cu->AddDIE(*die);
    }
    else if (cu)
    {
        debug_info->AddCompileUnit(cu_sp);
    }

    // Just return the current offset to parse the next CU or DIE entry
    return next_offset;
}
Beispiel #4
0
//----------------------------------------------------------------------
// LookupAddress
//----------------------------------------------------------------------
bool
DWARFDebugInfo::LookupAddress
(
    const dw_addr_t address,
    const dw_offset_t hint_die_offset,
    DWARFCompileUnitSP& cu_sp,
    DWARFDebugInfoEntry** function_die,
    DWARFDebugInfoEntry** block_die
)
{

    if (hint_die_offset != DW_INVALID_OFFSET)
        cu_sp = GetCompileUnit(hint_die_offset);
    else
    {
        DWARFDebugAranges &cu_aranges = GetCompileUnitAranges ();
        const dw_offset_t cu_offset = cu_aranges.FindAddress (address);
        cu_sp = GetCompileUnit(cu_offset);
    }

    if (cu_sp.get())
    {
        if (cu_sp->LookupAddress(address, function_die, block_die))
            return true;
        cu_sp.reset();
    }
    else
    {
        // The hint_die_offset may have been a pointer to the actual item that
        // we are looking for
        DWARFDebugInfoEntry* die_ptr = GetDIEPtr(hint_die_offset, &cu_sp);
        if (die_ptr)
        {
            if (cu_sp.get())
            {
                if (function_die || block_die)
                    return die_ptr->LookupAddress(address, m_dwarf2Data, cu_sp.get(), function_die, block_die);

                // We only wanted the compile unit that contained this address
                return true;
            }
        }
    }
    return false;
}
bool DWARFDebugInfo::OffsetLessThanCompileUnitOffset(
    dw_offset_t offset, const DWARFCompileUnitSP &cu_sp) {
  return offset < cu_sp->GetOffset();
}
Beispiel #6
0
//----------------------------------------------------------------------
// DumpCallback
//
// A callback function for the static DWARFDebugInfo::Parse() function
// that gets called each time a compile unit header or debug information
// entry is successfully parsed.
//
// This function dump DWARF information and obey recurse depth and
// whether a single DIE is to be dumped (or all of the data).
//----------------------------------------------------------------------
static dw_offset_t DumpCallback
(
    SymbolFileDWARF* dwarf2Data,
    DWARFCompileUnitSP& cu_sp,
    DWARFDebugInfoEntry* die,
    const dw_offset_t next_offset,
    const uint32_t curr_depth,
    void* userData
)
{
    DumpInfo* dumpInfo = (DumpInfo*)userData;

    const DWARFCompileUnit* cu = cu_sp.get();

    Stream *s = dumpInfo->strm;
    bool show_parents = s->GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowAncestors);

    if (die)
    {
        // Are we dumping everything?
        if (dumpInfo->die_offset == DW_INVALID_OFFSET)
        {
            // Yes we are dumping everything. Obey our recurse level though
            if (curr_depth < dumpInfo->recurse_depth)
                die->Dump(dwarf2Data, cu, *s, 0);
        }
        else
        {
            // We are dumping a specific DIE entry by offset
            if (dumpInfo->die_offset == die->GetOffset())
            {
                // We found the DIE we were looking for, dump it!
                if (show_parents)
                {
                    s->SetIndentLevel(0);
                    const uint32_t num_ancestors = dumpInfo->ancestors.size();
                    if (num_ancestors > 0)
                    {
                        for (uint32_t i=0; i<num_ancestors-1; ++i)
                        {
                            dumpInfo->ancestors[i].Dump(dwarf2Data, cu, *s, 0);
                            s->IndentMore();
                        }
                    }
                }

                dumpInfo->found_depth = curr_depth;

                die->Dump(dwarf2Data, cu, *s, 0);

                // Note that we found the DIE we were looking for
                dumpInfo->found_die = true;

                // Since we are dumping a single DIE, if there are no children we are done!
                if (!die->HasChildren() || dumpInfo->recurse_depth == 0)
                    return DW_INVALID_OFFSET;   // Return an invalid address to end parsing
            }
            else if (dumpInfo->found_die)
            {
                // Are we done with all the children?
                if (curr_depth <= dumpInfo->found_depth)
                    return DW_INVALID_OFFSET;

                // We have already found our DIE and are printing it's children. Obey
                // our recurse depth and return an invalid offset if we get done
                // dumping all the the children
                if (dumpInfo->recurse_depth == UINT32_MAX || curr_depth <= dumpInfo->found_depth + dumpInfo->recurse_depth)
                    die->Dump(dwarf2Data, cu, *s, 0);
            }
            else if (dumpInfo->die_offset > die->GetOffset())
            {
                if (show_parents)
                    dumpInfo->ancestors.back() = *die;
            }
        }

        // Keep up with our indent level
        if (die->IsNULL())
        {
            if (show_parents)
                dumpInfo->ancestors.pop_back();

            if (curr_depth <= 1)
                return cu->GetNextCompileUnitOffset();
            else
                s->IndentLess();
        }
        else if (die->HasChildren())
        {
            if (show_parents)
            {
                DWARFDebugInfoEntry null_die;
                dumpInfo->ancestors.push_back(null_die);
            }
            s->IndentMore();
        }
    }
    else
    {
        if (cu == NULL)
            s->PutCString("NULL - cu");
        // We have a compile unit, reset our indent level to zero just in case
        s->SetIndentLevel(0);

        // See if we are dumping everything?
        if (dumpInfo->die_offset == DW_INVALID_OFFSET)
        {
            // We are dumping everything
            cu->Dump(s);
            return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this Compile Unit
        }
        else
        {
            if (show_parents)
            {
                dumpInfo->ancestors.clear();
                dumpInfo->ancestors.resize(1);
            }

            // We are dumping only a single DIE possibly with it's children and
            // we must find it's compile unit before we can dump it properly
            if (dumpInfo->die_offset < cu->GetFirstDIEOffset())
            {
                // Not found, maybe the DIE offset provided wasn't correct?
            //  *ostrm_ptr << "DIE at offset " << HEX32 << dumpInfo->die_offset << " was not found." << endl;
                return DW_INVALID_OFFSET;
            }
            else
            {
                // See if the DIE is in this compile unit?
                if (dumpInfo->die_offset < cu->GetNextCompileUnitOffset())
                {
                    // This DIE is in this compile unit!
                    if (s->GetVerbose())
                        cu->Dump(s); // Dump the compile unit for the DIE in verbose mode

                    return next_offset;
                //  // We found our compile unit that contains our DIE, just skip to dumping the requested DIE...
                //  return dumpInfo->die_offset;
                }
                else
                {
                    // Skip to the next compile unit as the DIE isn't in the current one!
                    return cu->GetNextCompileUnitOffset();
                }
            }
        }
    }

    // Just return the current offset to parse the next CU or DIE entry
    return next_offset;
}
Beispiel #7
0
static bool CompileUnitOffsetLessThan (const DWARFCompileUnitSP& a, const DWARFCompileUnitSP& b)
{
    return a->GetOffset() < b->GetOffset();
}