[prev in list] [next in list] [prev in thread] [next in thread] 

List:       haiku-commits
Subject:    [Haiku-commits] r31325 - haiku/trunk/src/apps/debugger/dwarf
From:       bonefish at BerliOS <bonefish () mail ! berlios ! de>
Date:       2009-06-30 12:48:46
Message-ID: 200906301248.n5UCmkF1007963 () sheep ! berlios ! de
[Download RAW message or body]

Author: bonefish
Date: 2009-06-30 14:48:46 +0200 (Tue, 30 Jun 2009)
New Revision: 31325
ViewCVS: http://svn.berlios.de/viewcvs/haiku?rev=31325&view=rev

Modified:
   haiku/trunk/src/apps/debugger/dwarf/CompilationUnit.cpp
   haiku/trunk/src/apps/debugger/dwarf/CompilationUnit.h
   haiku/trunk/src/apps/debugger/dwarf/DataReader.h
   haiku/trunk/src/apps/debugger/dwarf/DebugInfoEntries.h
   haiku/trunk/src/apps/debugger/dwarf/DebugInfoEntry.cpp
   haiku/trunk/src/apps/debugger/dwarf/DebugInfoEntry.h
   haiku/trunk/src/apps/debugger/dwarf/DwarfFile.cpp
   haiku/trunk/src/apps/debugger/dwarf/DwarfFile.h
   haiku/trunk/src/apps/debugger/dwarf/DwarfUtils.cpp
   haiku/trunk/src/apps/debugger/dwarf/DwarfUtils.h
Log:
* 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.


Modified: haiku/trunk/src/apps/debugger/dwarf/CompilationUnit.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/dwarf/CompilationUnit.cpp	2009-06-30 12:47:41 UTC (rev 31324)
+++ haiku/trunk/src/apps/debugger/dwarf/CompilationUnit.cpp	2009-06-30 12:48:46 UTC (rev 31325)
@@ -5,7 +5,23 @@
 
 #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,
 	dwarf_off_t abbreviationOffset)
@@ -15,7 +31,9 @@
 	fTotalSize(totalSize),
 	fAbbreviationOffset(abbreviationOffset),
 	fAbbreviationTable(NULL),
-	fUnitEntry(NULL)
+	fUnitEntry(NULL),
+	fDirectories(10, true),
+	fFiles(10, true)
 {
 }
 
@@ -88,3 +106,65 @@
 
 	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;
+}

Modified: haiku/trunk/src/apps/debugger/dwarf/CompilationUnit.h
===================================================================
--- haiku/trunk/src/apps/debugger/dwarf/CompilationUnit.h	2009-06-30 12:47:41 UTC (rev 31324)
+++ haiku/trunk/src/apps/debugger/dwarf/CompilationUnit.h	2009-06-30 12:48:46 UTC (rev 31325)
@@ -5,6 +5,8 @@
 #ifndef COMPILATION_UNIT_H
 #define COMPILATION_UNIT_H
 
+#include <String.h>
+
 #include <ObjectList.h>
 
 #include "Array.h"
@@ -50,7 +52,21 @@
 									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;
 			dwarf_off_t			fTotalSize;
@@ -59,6 +75,8 @@
 			DIECompileUnitBase*	fUnitEntry;
 			Array<DebugInfoEntry*> fEntries;
 			Array<dwarf_off_t>	fEntryOffsets;
+			DirectoryList		fDirectories;
+			FileList			fFiles;
 };
 
 

Modified: haiku/trunk/src/apps/debugger/dwarf/DataReader.h
===================================================================
--- haiku/trunk/src/apps/debugger/dwarf/DataReader.h	2009-06-30 12:47:41 UTC (rev 31324)
+++ haiku/trunk/src/apps/debugger/dwarf/DataReader.h	2009-06-30 12:48:46 UTC (rev 31325)
@@ -135,6 +135,15 @@
 		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)

Modified: haiku/trunk/src/apps/debugger/dwarf/DebugInfoEntries.h
===================================================================
--- haiku/trunk/src/apps/debugger/dwarf/DebugInfoEntries.h	2009-06-30 12:47:41 UTC (rev 31324)
+++ haiku/trunk/src/apps/debugger/dwarf/DebugInfoEntries.h	2009-06-30 12:48:46 UTC (rev 31325)
@@ -153,6 +153,9 @@
 			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,

Modified: haiku/trunk/src/apps/debugger/dwarf/DebugInfoEntry.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/dwarf/DebugInfoEntry.cpp	2009-06-30 12:47:41 UTC (rev 31324)
+++ haiku/trunk/src/apps/debugger/dwarf/DebugInfoEntry.cpp	2009-06-30 12:48:46 UTC (rev 31325)
@@ -94,6 +94,22 @@
 }
 
 
+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)
 {

Modified: haiku/trunk/src/apps/debugger/dwarf/DebugInfoEntry.h
===================================================================
--- haiku/trunk/src/apps/debugger/dwarf/DebugInfoEntry.h	2009-06-30 12:47:41 UTC (rev 31324)
+++ haiku/trunk/src/apps/debugger/dwarf/DebugInfoEntry.h	2009-06-30 12:48:46 UTC (rev 31325)
@@ -59,6 +59,9 @@
 	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,

Modified: haiku/trunk/src/apps/debugger/dwarf/DwarfFile.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/dwarf/DwarfFile.cpp	2009-06-30 12:47:41 UTC (rev 31324)
+++ haiku/trunk/src/apps/debugger/dwarf/DwarfFile.cpp	2009-06-30 12:48:46 UTC (rev 31325)
@@ -27,6 +27,7 @@
 	fDebugAbbrevSection(NULL),
 	fDebugStringSection(NULL),
 	fDebugRangesSection(NULL),
+	fDebugLineSection(NULL),
 	fCompilationUnits(20, true),
 	fCurrentCompilationUnit(NULL),
 	fFinished(false),
@@ -45,6 +46,7 @@
 		fElfFile->PutSection(fDebugAbbrevSection);
 		fElfFile->PutSection(fDebugStringSection);
 		fElfFile->PutSection(fDebugRangesSection);
+		fElfFile->PutSection(fDebugLineSection);
 		delete fElfFile;
 	}
 
@@ -72,8 +74,6 @@
 	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 @@
 		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 @@
 }
 
 
+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 @@
 		}
 	}
 
+	if (fDebugLineSection != NULL)
+		_ParseLineInfo(unit);
+
 	return B_OK;
 }
 
@@ -585,6 +614,93 @@
 
 
 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)
 {
 	// check, whether we've already loaded it

Modified: haiku/trunk/src/apps/debugger/dwarf/DwarfFile.h
===================================================================
--- haiku/trunk/src/apps/debugger/dwarf/DwarfFile.h	2009-06-30 12:47:41 UTC (rev 31324)
+++ haiku/trunk/src/apps/debugger/dwarf/DwarfFile.h	2009-06-30 12:48:46 UTC (rev 31325)
@@ -33,6 +33,8 @@
 
 			int32				CountCompilationUnits() const;
 			CompilationUnit*	CompilationUnitAt(int32 index) const;
+			CompilationUnit*	CompilationUnitForDIE(
+									const DebugInfoEntry* entry) const;
 
 private:
 			typedef DoublyLinkedList<AbbreviationTable> AbbreviationTableList;
@@ -49,6 +51,8 @@
 									DebugInfoEntry* entry,
 									AbbreviationEntry& abbreviationEntry);
 
+			status_t			_ParseLineInfo(CompilationUnit* unit);
+
 			status_t			_GetAbbreviationTable(off_t offset,
 									AbbreviationTable*& _table);
 
@@ -64,6 +68,7 @@
 			ElfSection*			fDebugAbbrevSection;
 			ElfSection*			fDebugStringSection;
 			ElfSection*			fDebugRangesSection;
+			ElfSection*			fDebugLineSection;
 			AbbreviationTableList fAbbreviationTables;
 			DebugInfoEntryFactory fDebugInfoFactory;
 			CompilationUnitList	fCompilationUnits;

Modified: haiku/trunk/src/apps/debugger/dwarf/DwarfUtils.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/dwarf/DwarfUtils.cpp	2009-06-30 12:47:41 UTC (rev 31324)
+++ haiku/trunk/src/apps/debugger/dwarf/DwarfUtils.cpp	2009-06-30 12:48:46 UTC (rev 31325)
@@ -7,7 +7,10 @@
 
 #include <String.h>
 
+#include "CompilationUnit.h"
+#include "DwarfFile.h"
 
+
 /*static*/ void
 DwarfUtils::GetDIEName(const DebugInfoEntry* entry, BString& _name)
 {
@@ -77,3 +80,55 @@
 	} 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;
+}

Modified: haiku/trunk/src/apps/debugger/dwarf/DwarfUtils.h
===================================================================
--- haiku/trunk/src/apps/debugger/dwarf/DwarfUtils.h	2009-06-30 12:47:41 UTC (rev 31324)
+++ haiku/trunk/src/apps/debugger/dwarf/DwarfUtils.h	2009-06-30 12:48:46 UTC (rev 31325)
@@ -10,6 +10,7 @@
 
 class BString;
 class DebugInfoEntry;
+class DwarfFile;
 
 
 class DwarfUtils {
@@ -21,6 +22,12 @@
 	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);
 };
 
 

_______________________________________________
Haiku-commits mailing list
Haiku-commits@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/haiku-commits
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic