* Added parsing the .debug_line header for each compilation unit and attaching

the include directory and source file names to CompilationUnit.
* Added DwarfUtils::GetDeclarationLocation() which retrieves the respective
  source file name and line/column index for a given DIE.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31325 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-06-30 12:48:46 +00:00
parent c8e27e390c
commit 91c6759f30
10 changed files with 319 additions and 7 deletions
+81 -1
View File
@@ -5,6 +5,22 @@
#include "CompilationUnit.h"
#include <new>
struct CompilationUnit::File {
BString fileName;
const char* dirName;
File(const char* fileName, const char* dirName)
:
fileName(fileName),
dirName(dirName)
{
}
};
CompilationUnit::CompilationUnit(dwarf_off_t headerOffset,
dwarf_off_t contentOffset, dwarf_off_t totalSize,
@@ -15,7 +31,9 @@ CompilationUnit::CompilationUnit(dwarf_off_t headerOffset,
fTotalSize(totalSize),
fAbbreviationOffset(abbreviationOffset),
fAbbreviationTable(NULL),
fUnitEntry(NULL)
fUnitEntry(NULL),
fDirectories(10, true),
fFiles(10, true)
{
}
@@ -88,3 +106,65 @@ CompilationUnit::EntryForOffset(dwarf_off_t offset) const
return fEntryOffsets[lower] == offset ? fEntries[lower] : NULL;
}
bool
CompilationUnit::AddDirectory(const char* directory)
{
BString* directoryString = new(std::nothrow) BString(directory);
if (directoryString == NULL || directoryString->Length() == 0
|| !fDirectories.AddItem(directoryString)) {
delete directoryString;
return false;
}
return true;
}
int32
CompilationUnit::CountDirectories() const
{
return fDirectories.CountItems();
}
const char*
CompilationUnit::DirectoryAt(int32 index) const
{
BString* directory = fDirectories.ItemAt(index);
return directory != NULL ? directory->String() : NULL;
}
bool
CompilationUnit::AddFile(const char* fileName, int32 dirIndex)
{
File* file = new(std::nothrow) File(fileName, DirectoryAt(dirIndex));
if (file == NULL || file->fileName.Length() == 0 || !fFiles.AddItem(file)) {
delete file;
return false;
}
return true;
}
int32
CompilationUnit::CountFiles() const
{
return fFiles.CountItems();
}
const char*
CompilationUnit::FileAt(int32 index, const char** _directory) const
{
if (File* file = fFiles.ItemAt(index)) {
if (_directory != NULL)
*_directory = file->dirName;
return file->fileName.String();
}
return NULL;
}
+18
View File
@@ -5,6 +5,8 @@
#ifndef COMPILATION_UNIT_H
#define COMPILATION_UNIT_H
#include <String.h>
#include <ObjectList.h>
#include "Array.h"
@@ -50,6 +52,20 @@ public:
dwarf_off_t& offset) const;
DebugInfoEntry* EntryForOffset(dwarf_off_t offset) const;
bool AddDirectory(const char* directory);
int32 CountDirectories() const;
const char* DirectoryAt(int32 index) const;
bool AddFile(const char* fileName, int32 dirIndex);
int32 CountFiles() const;
const char* FileAt(int32 index,
const char** _directory = NULL) const;
private:
struct File;
typedef BObjectList<BString> DirectoryList;
typedef BObjectList<File> FileList;
private:
dwarf_off_t fHeaderOffset;
dwarf_off_t fContentOffset;
@@ -59,6 +75,8 @@ private:
DIECompileUnitBase* fUnitEntry;
Array<DebugInfoEntry*> fEntries;
Array<dwarf_off_t> fEntryOffsets;
DirectoryList fDirectories;
FileList fFiles;
};
+9
View File
@@ -135,6 +135,15 @@ public:
return NULL;
}
uint64 ReadInitialLength(bool& _dwarf64)
{
uint64 length = Read<uint32>(0);
_dwarf64 = (length == 0xffffffff);
if (_dwarf64)
length = Read<uint64>(0);
return length;
}
bool Skip(off_t bytes)
{
if (bytes < 0)
@@ -153,6 +153,9 @@ public:
dwarf_addr_t HighPC() const { return fHighPC; }
dwarf_addr_t AddressRangeBase() const;
dwarf_off_t StatementListOffset() const
{ return fStatementListOffset; }
virtual status_t AddChild(DebugInfoEntry* child);
virtual status_t AddAttribute_name(uint16 attributeName,
@@ -94,6 +94,22 @@ DebugInfoEntry::AbstractOrigin() const
}
bool
DebugInfoEntry::GetDeclarationLocation(uint32& _file, uint32& _line,
uint32& _column) const
{
DeclarationLocation* location = const_cast<DebugInfoEntry*>(this)
->GetDeclarationLocation();
if (location == NULL)
return false;
_file = location->file;
_line = location->line;
_column = location->column;
return true;
}
status_t
DebugInfoEntry::AddChild(DebugInfoEntry* child)
{
+3
View File
@@ -59,6 +59,9 @@ public:
virtual DebugInfoEntry* Specification() const;
virtual DebugInfoEntry* AbstractOrigin() const;
bool GetDeclarationLocation(uint32& _file,
uint32& _line, uint32& _column) const;
virtual status_t AddChild(DebugInfoEntry* child);
virtual status_t AddAttribute_decl_file(uint16 attributeName,
+122 -6
View File
@@ -27,6 +27,7 @@ DwarfFile::DwarfFile()
fDebugAbbrevSection(NULL),
fDebugStringSection(NULL),
fDebugRangesSection(NULL),
fDebugLineSection(NULL),
fCompilationUnits(20, true),
fCurrentCompilationUnit(NULL),
fFinished(false),
@@ -45,6 +46,7 @@ DwarfFile::~DwarfFile()
fElfFile->PutSection(fDebugAbbrevSection);
fElfFile->PutSection(fDebugStringSection);
fElfFile->PutSection(fDebugRangesSection);
fElfFile->PutSection(fDebugLineSection);
delete fElfFile;
}
@@ -72,8 +74,6 @@ DwarfFile::Load(const char* fileName)
fDebugInfoSection = fElfFile->GetSection(".debug_info");
fDebugAbbrevSection = fElfFile->GetSection(".debug_abbrev");
fDebugStringSection = fElfFile->GetSection(".debug_str");
fDebugRangesSection = fElfFile->GetSection(".debug_ranges");
// not mandatory
if (fDebugInfoSection == NULL || fDebugAbbrevSection == NULL
|| fDebugStringSection == NULL) {
fprintf(stderr, "DwarfManager::File::Load(\"%s\"): no "
@@ -82,15 +82,17 @@ DwarfFile::Load(const char* fileName)
return B_ERROR;
}
// not mandatory sections
fDebugRangesSection = fElfFile->GetSection(".debug_ranges");
fDebugLineSection = fElfFile->GetSection(".debug_line");
// iterate through the debug info section
DataReader dataReader(fDebugInfoSection->Data(),
fDebugInfoSection->Size());
while (dataReader.HasData()) {
dwarf_off_t unitHeaderOffset = dataReader.Offset();
uint64 unitLength = dataReader.Read<uint32>(0);
bool dwarf64 = (unitLength == 0xffffffff);
if (dwarf64)
unitLength = dataReader.Read<uint64>(0);
bool dwarf64;
uint64 unitLength = dataReader.ReadInitialLength(dwarf64);
dwarf_off_t unitLengthOffset = dataReader.Offset();
// the unitLength starts here
@@ -189,6 +191,30 @@ DwarfFile::CompilationUnitAt(int32 index) const
}
CompilationUnit*
DwarfFile::CompilationUnitForDIE(const DebugInfoEntry* entry) const
{
// find the root of the tree the entry lives in
while (entry != NULL && entry->Parent() != NULL)
entry = entry->Parent();
// that should be the compilation unit entry
const DIECompileUnitBase* unitEntry
= dynamic_cast<const DIECompileUnitBase*>(entry);
if (unitEntry == NULL)
return NULL;
// find the compilation unit
for (int32 i = 0; CompilationUnit* unit = fCompilationUnits.ItemAt(i);
i++) {
if (unit->UnitEntry() == unitEntry)
return unit;
}
return NULL;
}
status_t
DwarfFile::_ParseCompilationUnit(CompilationUnit* unit)
{
@@ -372,6 +398,9 @@ printf("entry %p at %lu\n", entry, offset);
}
}
if (fDebugLineSection != NULL)
_ParseLineInfo(unit);
return B_OK;
}
@@ -584,6 +613,93 @@ printf(" -> no attribute setter!\n");
}
status_t
DwarfFile::_ParseLineInfo(CompilationUnit* unit)
{
dwarf_off_t offset = unit->UnitEntry()->StatementListOffset();
printf("DwarfFile::_ParseLineInfo(%p), offset: %lu\n", unit, offset);
DataReader dataReader((uint8*)fDebugLineSection->Data() + offset,
fDebugLineSection->Size() - offset);
// unit length
bool dwarf64;
uint64 unitLength = dataReader.ReadInitialLength(dwarf64);
// version (uhalf)
uint16 version = dataReader.Read<uint16>(0);
// header_length (4/8)
uint64 headerLength = dwarf64
? dataReader.Read<uint64>(0) : (uint64)dataReader.Read<uint32>(0);
// minimum instruction length
uint8 minInstructionLength = dataReader.Read<uint8>(0);
// default is statement
bool defaultIsStatement = dataReader.Read<uint8>(0) != 0;
// line_base (sbyte)
int8 lineBase = (int8)dataReader.Read<uint8>(0);
// line_range (ubyte)
uint8 lineRange = dataReader.Read<uint8>(0);
// opcode_base (ubyte)
uint8 opcodeBase = dataReader.Read<uint8>(0);
// standard_opcode_lengths (ubyte[])
dataReader.Skip(opcodeBase - 1);
if (dataReader.HasOverflow())
return B_BAD_DATA;
if (version != 2 && version != 3)
return B_UNSUPPORTED;
printf(" unitLength: %llu\n", unitLength);
printf(" version: %u\n", version);
printf(" headerLength: %llu\n", headerLength);
printf(" minInstructionLength: %u\n", minInstructionLength);
printf(" defaultIsStatement: %d\n", defaultIsStatement);
printf(" lineBase: %d\n", lineBase);
printf(" lineRange: %u\n", lineRange);
printf(" opcodeBase: %u\n", opcodeBase);
// include directories
printf(" include directories:\n");
while (const char* directory = dataReader.ReadString()) {
if (*directory == '\0')
break;
printf(" \"%s\"\n", directory);
if (!unit->AddDirectory(directory))
return B_NO_MEMORY;
}
// file names
printf(" files:\n");
while (const char* file = dataReader.ReadString()) {
if (*file == '\0')
break;
uint64 dirIndex = dataReader.ReadUnsignedLEB128(0);
uint64 modificationTime = dataReader.ReadUnsignedLEB128(0);
uint64 fileLength = dataReader.ReadUnsignedLEB128(0);
if (dataReader.HasOverflow())
return B_BAD_DATA;
printf(" \"%s\", dir index: %llu, mtime: %llu, length: %llu\n", file,
dirIndex, modificationTime, fileLength);
if (!unit->AddFile(file, dirIndex - 1))
return B_NO_MEMORY;
}
return B_OK;
}
status_t
DwarfFile::_GetAbbreviationTable(off_t offset, AbbreviationTable*& _table)
{
+5
View File
@@ -33,6 +33,8 @@ public:
int32 CountCompilationUnits() const;
CompilationUnit* CompilationUnitAt(int32 index) const;
CompilationUnit* CompilationUnitForDIE(
const DebugInfoEntry* entry) const;
private:
typedef DoublyLinkedList<AbbreviationTable> AbbreviationTableList;
@@ -49,6 +51,8 @@ private:
DebugInfoEntry* entry,
AbbreviationEntry& abbreviationEntry);
status_t _ParseLineInfo(CompilationUnit* unit);
status_t _GetAbbreviationTable(off_t offset,
AbbreviationTable*& _table);
@@ -64,6 +68,7 @@ private:
ElfSection* fDebugAbbrevSection;
ElfSection* fDebugStringSection;
ElfSection* fDebugRangesSection;
ElfSection* fDebugLineSection;
AbbreviationTableList fAbbreviationTables;
DebugInfoEntryFactory fDebugInfoFactory;
CompilationUnitList fCompilationUnits;
+55
View File
@@ -7,6 +7,9 @@
#include <String.h>
#include "CompilationUnit.h"
#include "DwarfFile.h"
/*static*/ void
DwarfUtils::GetDIEName(const DebugInfoEntry* entry, BString& _name)
@@ -77,3 +80,55 @@ DwarfUtils::GetFullyQualifiedDIEName(const DebugInfoEntry* entry,
} else
_name = name;
}
/*static*/ bool
DwarfUtils::GetDeclarationLocation(DwarfFile* dwarfFile,
const DebugInfoEntry* entry, const char*& _directory, const char*& _file,
uint32& _line, uint32& _column)
{
uint32 file;
uint32 line;
uint32 column;
if (!entry->GetDeclarationLocation(file, line, column))
return false;
// if no info yet, try the abstract origin (if any)
if (file == 0) {
if (DebugInfoEntry* abstractOrigin = entry->AbstractOrigin()) {
if (abstractOrigin->GetDeclarationLocation(file, line, column)
&& file != 0) {
entry = abstractOrigin;
}
}
}
// if no info yet, try the specification (if any)
if (file == 0) {
if (DebugInfoEntry* specification = entry->Specification()) {
if (specification->GetDeclarationLocation(file, line, column)
&& file != 0) {
entry = specification;
}
}
}
if (file == 0)
return false;
// get the compilation unit
CompilationUnit* unit = dwarfFile->CompilationUnitForDIE(entry);
if (unit == NULL)
return false;
const char* directoryName;
const char* fileName = unit->FileAt(file - 1, &directoryName);
if (fileName == NULL)
return false;
_directory = directoryName;
_file = fileName;
_line = line;
_column = column;
return true;
}
+7
View File
@@ -10,6 +10,7 @@
class BString;
class DebugInfoEntry;
class DwarfFile;
class DwarfUtils {
@@ -21,6 +22,12 @@ public:
static void GetFullyQualifiedDIEName(
const DebugInfoEntry* entry,
BString& _name);
static bool GetDeclarationLocation(DwarfFile* dwarfFile,
const DebugInfoEntry* entry,
const char*& _directory,
const char*& _file,
uint32& _line, uint32& _column);
};