* Renaming and coding moving.
* Added locking to DwarfManager. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31279 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -10,7 +10,6 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) arch ] ;
|
|||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) arch x86 ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) arch x86 ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_info ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_info ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) dwarf ] ;
|
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) elf ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) elf ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) gui team_window ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) gui team_window ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) model ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) model ] ;
|
||||||
@@ -55,15 +54,6 @@ Application Debugger :
|
|||||||
DebugEvent.cpp
|
DebugEvent.cpp
|
||||||
DebuggerInterface.cpp
|
DebuggerInterface.cpp
|
||||||
|
|
||||||
# dwarf
|
|
||||||
attribute_classes.cpp
|
|
||||||
AttributeValue.cpp
|
|
||||||
DebugInfoEntries.cpp
|
|
||||||
DebugInfoEntry.cpp
|
|
||||||
DwarfManager.cpp
|
|
||||||
SourceLanguageInfo.cpp
|
|
||||||
tag_names.cpp
|
|
||||||
|
|
||||||
# elf
|
# elf
|
||||||
ElfFile.cpp
|
ElfFile.cpp
|
||||||
|
|
||||||
@@ -95,6 +85,7 @@ Application Debugger :
|
|||||||
:
|
:
|
||||||
<nogrist>Debugger_demangler.o
|
<nogrist>Debugger_demangler.o
|
||||||
<nogrist>Debugger_disasm_x86.o
|
<nogrist>Debugger_disasm_x86.o
|
||||||
|
<nogrist>Debugger_dwarf.o
|
||||||
<nogrist>DebugAnalyzer_gui_table.o
|
<nogrist>DebugAnalyzer_gui_table.o
|
||||||
|
|
||||||
libudis86.a
|
libudis86.a
|
||||||
@@ -110,4 +101,5 @@ Application Debugger :
|
|||||||
|
|
||||||
HaikuSubInclude arch x86 disasm ;
|
HaikuSubInclude arch x86 disasm ;
|
||||||
HaikuSubInclude demangler ;
|
HaikuSubInclude demangler ;
|
||||||
|
HaikuSubInclude dwarf ;
|
||||||
HaikuSubInclude gui running_teams_window ;
|
HaikuSubInclude gui running_teams_window ;
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "AbbreviationTable.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
|
||||||
|
AbbreviationTable::AbbreviationTable(off_t offset)
|
||||||
|
:
|
||||||
|
fOffset(offset),
|
||||||
|
fData(NULL),
|
||||||
|
fSize(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AbbreviationTable::~AbbreviationTable()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
AbbreviationTable::Init(const void* section, off_t sectionSize)
|
||||||
|
{
|
||||||
|
if (fOffset < 0 || fOffset >= sectionSize)
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
fData = (uint8*)section + fOffset;
|
||||||
|
fSize = sectionSize - fOffset;
|
||||||
|
// That's only the maximum size. Will be adjusted at the end.
|
||||||
|
|
||||||
|
status_t error = fEntryTable.Init();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
DataReader abbrevReader(fData, fSize);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
bool nullEntry;
|
||||||
|
status_t error = _ParseAbbreviationEntry(abbrevReader, nullEntry);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
if (nullEntry)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fSize -= abbrevReader.BytesRemaining();
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
AbbreviationTable::GetAbbreviationEntry(uint32 code, AbbreviationEntry& entry)
|
||||||
|
{
|
||||||
|
AbbreviationTableEntry* tableEntry = fEntryTable.Lookup(code);
|
||||||
|
if (tableEntry == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
entry.SetTo(code, fData + tableEntry->offset, tableEntry->size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
AbbreviationTable::_ParseAbbreviationEntry(DataReader& abbrevReader,
|
||||||
|
bool& _nullEntry)
|
||||||
|
{
|
||||||
|
uint32 code = abbrevReader.ReadUnsignedLEB128(0);
|
||||||
|
if (code == 0) {
|
||||||
|
if (abbrevReader.HasOverflow()) {
|
||||||
|
fprintf(stderr, "Invalid abbreviation table 1!\n");
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
_nullEntry = true;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t remaining = abbrevReader.BytesRemaining();
|
||||||
|
|
||||||
|
/* uint32 tag =*/ abbrevReader.ReadUnsignedLEB128(0);
|
||||||
|
/* uint8 hasChildren =*/ abbrevReader.Read<uint8>(DW_CHILDREN_no);
|
||||||
|
|
||||||
|
// printf("entry: %lu, tag: %lu, children: %d\n", code, tag,
|
||||||
|
// hasChildren);
|
||||||
|
|
||||||
|
// parse attribute specifications
|
||||||
|
while (true) {
|
||||||
|
uint32 attributeName = abbrevReader.ReadUnsignedLEB128(0);
|
||||||
|
uint32 attributeForm = abbrevReader.ReadUnsignedLEB128(0);
|
||||||
|
if (abbrevReader.HasOverflow()) {
|
||||||
|
fprintf(stderr, "Invalid abbreviation table 2!\n");
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributeName == 0 && attributeForm == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// printf(" attr: name: %lu, form: %lu\n", attributeName,
|
||||||
|
// attributeForm);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the entry
|
||||||
|
if (fEntryTable.Lookup(code) == NULL) {
|
||||||
|
AbbreviationTableEntry* entry = new(std::nothrow)
|
||||||
|
AbbreviationTableEntry(code, fSize - remaining,
|
||||||
|
remaining - abbrevReader.BytesRemaining());
|
||||||
|
if (entry == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
fEntryTable.Insert(entry);
|
||||||
|
} else
|
||||||
|
fprintf(stderr, "Duplicate abbreviation table entry %lu!\n", code);
|
||||||
|
|
||||||
|
_nullEntry = false;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef ABBREVIATION_TABLE_H
|
||||||
|
#define ABBREVIATION_TABLE_H
|
||||||
|
|
||||||
|
#include <util/DoublyLinkedList.h>
|
||||||
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
|
#include "DataReader.h"
|
||||||
|
#include "Dwarf.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct AbbreviationTableEntry : HashTableLink<AbbreviationTableEntry> {
|
||||||
|
uint32 code;
|
||||||
|
off_t offset;
|
||||||
|
off_t size;
|
||||||
|
|
||||||
|
AbbreviationTableEntry(uint32 code, off_t offset, off_t size)
|
||||||
|
:
|
||||||
|
code(code),
|
||||||
|
offset(offset),
|
||||||
|
size(size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct AbbreviationEntry {
|
||||||
|
AbbreviationEntry()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AbbreviationEntry(uint32 code, const void* data, off_t size)
|
||||||
|
{
|
||||||
|
SetTo(code, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTo(uint32 code, const void* data, off_t size)
|
||||||
|
{
|
||||||
|
fCode = code;
|
||||||
|
fAttributesReader.SetTo(data, size);
|
||||||
|
fTag = fAttributesReader.ReadUnsignedLEB128(0);
|
||||||
|
fHasChildren = fAttributesReader.Read<uint8>(0);
|
||||||
|
fData = fAttributesReader.Data();
|
||||||
|
fSize = fAttributesReader.BytesRemaining();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 Code() const { return fCode; }
|
||||||
|
uint32 Tag() const { return fTag; }
|
||||||
|
bool HasChildren() const { return fHasChildren == DW_CHILDREN_yes; }
|
||||||
|
|
||||||
|
bool GetNextAttribute(uint32& name, uint32& form)
|
||||||
|
{
|
||||||
|
name = fAttributesReader.ReadUnsignedLEB128(0);
|
||||||
|
form = fAttributesReader.ReadUnsignedLEB128(0);
|
||||||
|
return !fAttributesReader.HasOverflow() && (name != 0 || form != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32 fCode;
|
||||||
|
const void* fData;
|
||||||
|
off_t fSize;
|
||||||
|
uint32 fTag;
|
||||||
|
uint8 fHasChildren;
|
||||||
|
DataReader fAttributesReader;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct AbbreviationTableHashDefinition {
|
||||||
|
typedef uint32 KeyType;
|
||||||
|
typedef AbbreviationTableEntry ValueType;
|
||||||
|
|
||||||
|
size_t HashKey(uint32 key) const
|
||||||
|
{
|
||||||
|
return (size_t)key;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Hash(AbbreviationTableEntry* value) const
|
||||||
|
{
|
||||||
|
return HashKey(value->code);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Compare(uint32 key, AbbreviationTableEntry* value) const
|
||||||
|
{
|
||||||
|
return value->code == key;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashTableLink<AbbreviationTableEntry>* GetLink(
|
||||||
|
AbbreviationTableEntry* value) const
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class AbbreviationTable : public DoublyLinkedListLinkImpl<AbbreviationTable> {
|
||||||
|
public:
|
||||||
|
AbbreviationTable(off_t offset);
|
||||||
|
~AbbreviationTable();
|
||||||
|
|
||||||
|
status_t Init(const void* section, off_t sectionSize);
|
||||||
|
|
||||||
|
off_t Offset() const { return fOffset; }
|
||||||
|
|
||||||
|
bool GetAbbreviationEntry(uint32 code,
|
||||||
|
AbbreviationEntry& entry);
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef OpenHashTable<AbbreviationTableHashDefinition> EntryTable;
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _ParseAbbreviationEntry(
|
||||||
|
DataReader& abbrevReader, bool& _nullEntry);
|
||||||
|
|
||||||
|
private:
|
||||||
|
off_t fOffset;
|
||||||
|
const uint8* fData;
|
||||||
|
off_t fSize;
|
||||||
|
EntryTable fEntryTable;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // ABBREVIATION_TABLE_H
|
||||||
+2
-2
@@ -3,8 +3,8 @@
|
|||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "attribute_classes.h"
|
#include "AttributeClasses.h"
|
||||||
#include "dwarf.h"
|
#include "Dwarf.h"
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "attribute_classes.h"
|
#include "AttributeClasses.h"
|
||||||
|
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
#ifndef ATTRIBUTE_VALUE_H
|
#ifndef ATTRIBUTE_VALUE_H
|
||||||
#define ATTRIBUTE_VALUE_H
|
#define ATTRIBUTE_VALUE_H
|
||||||
|
|
||||||
#include "attribute_classes.h"
|
#include "AttributeClasses.h"
|
||||||
#include "types.h"
|
#include "DwarfTypes.h"
|
||||||
|
|
||||||
|
|
||||||
class DebugInfoEntry;
|
class DebugInfoEntry;
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CompilationUnit.h"
|
||||||
|
|
||||||
|
|
||||||
|
CompilationUnit::CompilationUnit(dwarf_off_t headerOffset,
|
||||||
|
dwarf_off_t contentOffset, dwarf_off_t totalSize,
|
||||||
|
dwarf_off_t abbreviationOffset)
|
||||||
|
:
|
||||||
|
fHeaderOffset(headerOffset),
|
||||||
|
fContentOffset(contentOffset),
|
||||||
|
fTotalSize(totalSize),
|
||||||
|
fAbbreviationOffset(abbreviationOffset),
|
||||||
|
fAbbreviationTable(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CompilationUnit::~CompilationUnit()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CompilationUnit::SetAbbreviationTable(AbbreviationTable* abbreviationTable)
|
||||||
|
{
|
||||||
|
fAbbreviationTable = abbreviationTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
CompilationUnit::AddDebugInfoEntry(DebugInfoEntry* entry, dwarf_off_t offset)
|
||||||
|
{
|
||||||
|
if (!fEntries.Add(entry))
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
if (!fEntryOffsets.Add(offset)) {
|
||||||
|
fEntries.Remove(fEntries.Count() - 1);
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
CompilationUnit::CountEntries() const
|
||||||
|
{
|
||||||
|
return fEntries.Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CompilationUnit::GetEntryAt(int index, DebugInfoEntry*& entry,
|
||||||
|
dwarf_off_t& offset) const
|
||||||
|
{
|
||||||
|
entry = fEntries[index];
|
||||||
|
offset = fEntryOffsets[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DebugInfoEntry*
|
||||||
|
CompilationUnit::EntryForOffset(dwarf_off_t offset) const
|
||||||
|
{
|
||||||
|
if (fEntries.IsEmpty())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// binary search
|
||||||
|
int lower = 0;
|
||||||
|
int upper = fEntries.Count() - 1;
|
||||||
|
while (lower < upper) {
|
||||||
|
int mid = (lower + upper + 1) / 2;
|
||||||
|
if (fEntryOffsets[mid] > offset)
|
||||||
|
upper = mid - 1;
|
||||||
|
else
|
||||||
|
lower = mid;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fEntryOffsets[lower] == offset ? fEntries[lower] : NULL;
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef COMPILATION_UNIT_H
|
||||||
|
#define COMPILATION_UNIT_H
|
||||||
|
|
||||||
|
#include <util/DoublyLinkedList.h>
|
||||||
|
|
||||||
|
#include "Array.h"
|
||||||
|
#include "DwarfTypes.h"
|
||||||
|
|
||||||
|
|
||||||
|
class AbbreviationTable;
|
||||||
|
class DebugInfoEntry;
|
||||||
|
|
||||||
|
|
||||||
|
class CompilationUnit : public DoublyLinkedListLinkImpl<CompilationUnit> {
|
||||||
|
public:
|
||||||
|
CompilationUnit(dwarf_off_t headerOffset,
|
||||||
|
dwarf_off_t contentOffset,
|
||||||
|
dwarf_off_t totalSize,
|
||||||
|
dwarf_off_t abbreviationOffset);
|
||||||
|
~CompilationUnit();
|
||||||
|
|
||||||
|
dwarf_off_t HeaderOffset() const { return fHeaderOffset; }
|
||||||
|
dwarf_off_t ContentOffset() const { return fContentOffset; }
|
||||||
|
dwarf_off_t RelativeContentOffset() const
|
||||||
|
{ return fContentOffset - fHeaderOffset; }
|
||||||
|
dwarf_off_t TotalSize() const { return fTotalSize; }
|
||||||
|
dwarf_off_t ContentSize() const
|
||||||
|
{ return fTotalSize
|
||||||
|
- RelativeContentOffset(); }
|
||||||
|
dwarf_off_t AbbreviationOffset() const
|
||||||
|
{ return fAbbreviationOffset; }
|
||||||
|
|
||||||
|
AbbreviationTable* GetAbbreviationTable() const
|
||||||
|
{ return fAbbreviationTable; }
|
||||||
|
void SetAbbreviationTable(
|
||||||
|
AbbreviationTable* abbreviationTable);
|
||||||
|
|
||||||
|
|
||||||
|
status_t AddDebugInfoEntry(DebugInfoEntry* entry,
|
||||||
|
dwarf_off_t offset);
|
||||||
|
int CountEntries() const;
|
||||||
|
void GetEntryAt(int index, DebugInfoEntry*& entry,
|
||||||
|
dwarf_off_t& offset) const;
|
||||||
|
DebugInfoEntry* EntryForOffset(dwarf_off_t offset) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
dwarf_off_t fHeaderOffset;
|
||||||
|
dwarf_off_t fContentOffset;
|
||||||
|
dwarf_off_t fTotalSize;
|
||||||
|
dwarf_off_t fAbbreviationOffset;
|
||||||
|
AbbreviationTable* fAbbreviationTable;
|
||||||
|
Array<DebugInfoEntry*> fEntries;
|
||||||
|
Array<dwarf_off_t> fEntryOffsets;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // COMPILATION_UNIT_H
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
#include "AttributeValue.h"
|
#include "AttributeValue.h"
|
||||||
#include "dwarf.h"
|
#include "Dwarf.h"
|
||||||
#include "SourceLanguageInfo.h"
|
#include "SourceLanguageInfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
#include "AttributeValue.h"
|
#include "AttributeValue.h"
|
||||||
#include "dwarf.h"
|
#include "Dwarf.h"
|
||||||
|
|
||||||
|
|
||||||
#define DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(name) \
|
#define DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(name) \
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include <util/DoublyLinkedList.h>
|
#include <util/DoublyLinkedList.h>
|
||||||
|
|
||||||
#include "types.h"
|
#include "DwarfTypes.h"
|
||||||
|
|
||||||
|
|
||||||
#define DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(name) \
|
#define DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(name) \
|
||||||
|
|||||||
@@ -0,0 +1,592 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "DwarfFile.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
|
#include "AttributeClasses.h"
|
||||||
|
#include "AttributeValue.h"
|
||||||
|
#include "AbbreviationTable.h"
|
||||||
|
#include "CompilationUnit.h"
|
||||||
|
#include "DataReader.h"
|
||||||
|
#include "ElfFile.h"
|
||||||
|
#include "TagNames.h"
|
||||||
|
|
||||||
|
|
||||||
|
DwarfFile::DwarfFile()
|
||||||
|
:
|
||||||
|
fName(NULL),
|
||||||
|
fElfFile(NULL),
|
||||||
|
fDebugInfoSection(NULL),
|
||||||
|
fDebugAbbrevSection(NULL),
|
||||||
|
fDebugStringSection(NULL),
|
||||||
|
fCurrentCompilationUnit(NULL),
|
||||||
|
fFinished(false),
|
||||||
|
fFinishError(B_OK)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DwarfFile::~DwarfFile()
|
||||||
|
{
|
||||||
|
while (CompilationUnit* unit = fCompilationUnits.RemoveHead())
|
||||||
|
delete unit;
|
||||||
|
|
||||||
|
while (AbbreviationTable* table = fAbbreviationTables.RemoveHead())
|
||||||
|
delete table;
|
||||||
|
|
||||||
|
if (fElfFile != NULL) {
|
||||||
|
fElfFile->PutSection(fDebugInfoSection);
|
||||||
|
fElfFile->PutSection(fDebugAbbrevSection);
|
||||||
|
fElfFile->PutSection(fDebugStringSection);
|
||||||
|
delete fElfFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(fName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::Load(const char* fileName)
|
||||||
|
{
|
||||||
|
fName = strdup(fileName);
|
||||||
|
if (fName == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
// load the ELF file
|
||||||
|
fElfFile = new(std::nothrow) ElfFile;
|
||||||
|
if (fElfFile == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
status_t error = fElfFile->Init(fileName);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// get the interesting sections
|
||||||
|
fDebugInfoSection = fElfFile->GetSection(".debug_info");
|
||||||
|
fDebugAbbrevSection = fElfFile->GetSection(".debug_abbrev");
|
||||||
|
fDebugStringSection = fElfFile->GetSection(".debug_str");
|
||||||
|
if (fDebugInfoSection == NULL || fDebugAbbrevSection == NULL
|
||||||
|
|| fDebugStringSection == NULL) {
|
||||||
|
fprintf(stderr, "DwarfManager::File::Load(\"%s\"): no "
|
||||||
|
".debug_info, .debug_abbrev, or .debug_str section.\n",
|
||||||
|
fileName);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
dwarf_off_t unitLengthOffset = dataReader.Offset();
|
||||||
|
// the unitLength starts here
|
||||||
|
|
||||||
|
if (unitLengthOffset + unitLength
|
||||||
|
> (uint64)fDebugInfoSection->Size()) {
|
||||||
|
printf("\"%s\": Invalid compilation unit length.\n", fileName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int version = dataReader.Read<uint16>(0);
|
||||||
|
off_t abbrevOffset = dwarf64
|
||||||
|
? dataReader.Read<uint64>(0)
|
||||||
|
: dataReader.Read<uint32>(0);
|
||||||
|
uint8 addressSize = dataReader.Read<uint8>(0);
|
||||||
|
|
||||||
|
if (dataReader.HasOverflow()) {
|
||||||
|
printf("\"%s\": Unexpected end of data in compilation unit "
|
||||||
|
"header.\n", fileName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("DWARF%d compilation unit: version %d, length: %lld, "
|
||||||
|
"abbrevOffset: %lld, address size: %d\n", dwarf64 ? 64 : 32,
|
||||||
|
version, unitLength, abbrevOffset, addressSize);
|
||||||
|
|
||||||
|
if (version != 2 && version != 3) {
|
||||||
|
printf("\"%s\": Unsupported compilation unit version: %d\n",
|
||||||
|
fileName, version);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addressSize != 4) {
|
||||||
|
printf("\"%s\": Unsupported address size: %d\n", fileName,
|
||||||
|
addressSize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dwarf_off_t unitContentOffset = dataReader.Offset();
|
||||||
|
|
||||||
|
// create a compilation unit object
|
||||||
|
CompilationUnit* unit = new(std::nothrow) CompilationUnit(
|
||||||
|
unitHeaderOffset, unitContentOffset,
|
||||||
|
unitLength + (unitLengthOffset - unitHeaderOffset),
|
||||||
|
abbrevOffset);
|
||||||
|
if (unit == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
fCompilationUnits.Add(unit);
|
||||||
|
|
||||||
|
// parse the debug info for the unit
|
||||||
|
fCurrentCompilationUnit = unit;
|
||||||
|
error = _ParseCompilationUnit(unit);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
dataReader.SeekAbsolute(unitLengthOffset + unitLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::FinishLoading()
|
||||||
|
{
|
||||||
|
if (fFinished)
|
||||||
|
return B_OK;
|
||||||
|
if (fFinishError != B_OK)
|
||||||
|
return fFinishError;
|
||||||
|
|
||||||
|
for (CompilationUnitList::Iterator it = fCompilationUnits.GetIterator();
|
||||||
|
CompilationUnit* unit = it.Next();) {
|
||||||
|
fCurrentCompilationUnit = unit;
|
||||||
|
status_t error = _FinishCompilationUnit(unit);
|
||||||
|
if (error != B_OK)
|
||||||
|
return fFinishError = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
fFinished = true;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::_ParseCompilationUnit(CompilationUnit* unit)
|
||||||
|
{
|
||||||
|
AbbreviationTable* abbreviationTable;
|
||||||
|
status_t error = _GetAbbreviationTable(unit->AbbreviationOffset(),
|
||||||
|
abbreviationTable);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
unit->SetAbbreviationTable(abbreviationTable);
|
||||||
|
|
||||||
|
DataReader dataReader(
|
||||||
|
(const uint8*)fDebugInfoSection->Data() + unit->ContentOffset(),
|
||||||
|
unit->ContentSize());
|
||||||
|
|
||||||
|
DebugInfoEntry* entry;
|
||||||
|
bool endOfEntryList;
|
||||||
|
error = _ParseDebugInfoEntry(dataReader, abbreviationTable, entry,
|
||||||
|
endOfEntryList);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
if (dynamic_cast<DIECompileUnitBase*>(entry) == NULL) {
|
||||||
|
fprintf(stderr, "No compilation unit entry in .debug_info "
|
||||||
|
"section.\n");
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("remaining bytes in unit: %lld\n", dataReader.BytesRemaining());
|
||||||
|
if (dataReader.HasData()) {
|
||||||
|
printf(" ");
|
||||||
|
while (dataReader.HasData()) {
|
||||||
|
printf("%02x", dataReader.Read<uint8>(0));
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::_ParseDebugInfoEntry(DataReader& dataReader,
|
||||||
|
AbbreviationTable* abbreviationTable, DebugInfoEntry*& _entry,
|
||||||
|
bool& _endOfEntryList, int level)
|
||||||
|
{
|
||||||
|
dwarf_off_t entryOffset = dataReader.Offset()
|
||||||
|
+ fCurrentCompilationUnit->RelativeContentOffset();
|
||||||
|
|
||||||
|
uint32 code = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
if (code == 0) {
|
||||||
|
if (dataReader.HasOverflow()) {
|
||||||
|
fprintf(stderr, "Unexpected end of .debug_info section.\n");
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
_entry = NULL;
|
||||||
|
_endOfEntryList = true;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the corresponding abbreviation entry
|
||||||
|
AbbreviationEntry abbreviationEntry;
|
||||||
|
if (!abbreviationTable->GetAbbreviationEntry(code, abbreviationEntry)) {
|
||||||
|
fprintf(stderr, "No abbreviation entry for code %lu\n", code);
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
printf("%*sentry at %lu: %lu, tag: %s (%lu), children: %d\n", level * 2, "",
|
||||||
|
entryOffset, abbreviationEntry.Code(), get_entry_tag_name(abbreviationEntry.Tag()),
|
||||||
|
abbreviationEntry.Tag(), abbreviationEntry.HasChildren());
|
||||||
|
|
||||||
|
DebugInfoEntry* entry;
|
||||||
|
status_t error = fDebugInfoFactory.CreateDebugInfoEntry(
|
||||||
|
abbreviationEntry.Tag(), entry);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
ObjectDeleter<DebugInfoEntry> entryDeleter(entry);
|
||||||
|
|
||||||
|
error = fCurrentCompilationUnit->AddDebugInfoEntry(entry, entryOffset);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// parse the attributes (supply NULL entry to avoid adding them yet)
|
||||||
|
error = _ParseEntryAttributes(dataReader, NULL, abbreviationEntry);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// parse children, if the entry has any
|
||||||
|
if (abbreviationEntry.HasChildren()) {
|
||||||
|
while (true) {
|
||||||
|
DebugInfoEntry* childEntry;
|
||||||
|
bool endOfEntryList;
|
||||||
|
status_t error = _ParseDebugInfoEntry(dataReader,
|
||||||
|
abbreviationTable, childEntry, endOfEntryList, level + 1);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// add the child to our entry
|
||||||
|
if (childEntry != NULL) {
|
||||||
|
if (entry != NULL) {
|
||||||
|
error = entry->AddChild(childEntry);
|
||||||
|
if (error == ENTRY_NOT_HANDLED) {
|
||||||
|
error = B_OK;
|
||||||
|
printf("%*s -> child unhandled\n", level * 2, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error != B_OK) {
|
||||||
|
delete childEntry;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
delete childEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endOfEntryList)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entryDeleter.Detach();
|
||||||
|
_entry = entry;
|
||||||
|
_endOfEntryList = false;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::_FinishCompilationUnit(CompilationUnit* unit)
|
||||||
|
{
|
||||||
|
printf("\nfinishing compilation unit %p\n", unit);
|
||||||
|
AbbreviationTable* abbreviationTable = unit->GetAbbreviationTable();
|
||||||
|
|
||||||
|
DataReader dataReader(
|
||||||
|
(const uint8*)fDebugInfoSection->Data() + unit->HeaderOffset(),
|
||||||
|
unit->TotalSize());
|
||||||
|
// DataReader dataReader(
|
||||||
|
// (const uint8*)fDebugInfoSection->Data() + unit->ContentOffset(),
|
||||||
|
// unit->ContentSize());
|
||||||
|
|
||||||
|
DebugInfoEntryInitInfo entryInitInfo;
|
||||||
|
|
||||||
|
int entryCount = unit->CountEntries();
|
||||||
|
for (int i = 0; i < entryCount; i++) {
|
||||||
|
// get the entry
|
||||||
|
DebugInfoEntry* entry;
|
||||||
|
dwarf_off_t offset;
|
||||||
|
unit->GetEntryAt(i, entry, offset);
|
||||||
|
printf("entry %p at %lu\n", entry, offset);
|
||||||
|
|
||||||
|
// seek the reader to the entry
|
||||||
|
dataReader.SeekAbsolute(offset);
|
||||||
|
|
||||||
|
// read the entry code
|
||||||
|
uint32 code = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
|
||||||
|
// get the respective abbreviation entry
|
||||||
|
AbbreviationEntry abbreviationEntry;
|
||||||
|
abbreviationTable->GetAbbreviationEntry(code, abbreviationEntry);
|
||||||
|
|
||||||
|
// initialization before setting the attributes
|
||||||
|
status_t error = entry->InitAfterHierarchy(entryInitInfo);
|
||||||
|
if (error != B_OK) {
|
||||||
|
fprintf(stderr, "Init after hierarchy failed!\n");
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse the attributes -- this time pass the entry, so that the
|
||||||
|
// attribute get set on it
|
||||||
|
error = _ParseEntryAttributes(dataReader, entry, abbreviationEntry);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// initialization after setting the attributes
|
||||||
|
error = entry->InitAfterAttributes(entryInitInfo);
|
||||||
|
if (error != B_OK) {
|
||||||
|
fprintf(stderr, "Init after attributes failed!\n");
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
||||||
|
DebugInfoEntry* entry, AbbreviationEntry& abbreviationEntry)
|
||||||
|
{
|
||||||
|
uint32 attributeName;
|
||||||
|
uint32 attributeForm;
|
||||||
|
while (abbreviationEntry.GetNextAttribute(attributeName,
|
||||||
|
attributeForm)) {
|
||||||
|
// resolve attribute form indirection
|
||||||
|
if (attributeForm == DW_FORM_indirect)
|
||||||
|
attributeForm = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
|
||||||
|
// prepare an AttributeValue
|
||||||
|
AttributeValue attributeValue;
|
||||||
|
attributeValue.attributeForm = attributeForm;
|
||||||
|
attributeValue.isSigned = false;
|
||||||
|
|
||||||
|
// Read the attribute value according to the attribute's form. For
|
||||||
|
// the forms that don't map to a single attribute class only or
|
||||||
|
// those that need additional processing, we read a temporary value
|
||||||
|
// first.
|
||||||
|
uint64 value = 0;
|
||||||
|
dwarf_size_t blockLength = 0;
|
||||||
|
bool localReference = true;
|
||||||
|
|
||||||
|
switch (attributeForm) {
|
||||||
|
case DW_FORM_addr:
|
||||||
|
value = dataReader.Read<dwarf_addr_t>(0);
|
||||||
|
break;
|
||||||
|
case DW_FORM_block2:
|
||||||
|
blockLength = dataReader.Read<uint16>(0);
|
||||||
|
break;
|
||||||
|
case DW_FORM_block4:
|
||||||
|
blockLength = dataReader.Read<uint32>(0);
|
||||||
|
break;
|
||||||
|
case DW_FORM_data2:
|
||||||
|
value = dataReader.Read<uint16>(0);
|
||||||
|
break;
|
||||||
|
case DW_FORM_data4:
|
||||||
|
value = dataReader.Read<uint32>(0);
|
||||||
|
break;
|
||||||
|
case DW_FORM_data8:
|
||||||
|
value = dataReader.Read<uint64>(0);
|
||||||
|
break;
|
||||||
|
case DW_FORM_string:
|
||||||
|
attributeValue.string = dataReader.ReadString();
|
||||||
|
break;
|
||||||
|
case DW_FORM_block:
|
||||||
|
blockLength = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
break;
|
||||||
|
case DW_FORM_block1:
|
||||||
|
blockLength = dataReader.Read<uint8>(0);
|
||||||
|
break;
|
||||||
|
case DW_FORM_data1:
|
||||||
|
value = dataReader.Read<uint8>(0);
|
||||||
|
break;
|
||||||
|
case DW_FORM_flag:
|
||||||
|
attributeValue.flag = dataReader.Read<uint8>(0) != 0;
|
||||||
|
break;
|
||||||
|
case DW_FORM_sdata:
|
||||||
|
value = dataReader.ReadSignedLEB128(0);
|
||||||
|
attributeValue.isSigned = true;
|
||||||
|
break;
|
||||||
|
case DW_FORM_strp:
|
||||||
|
{
|
||||||
|
dwarf_off_t offset = dataReader.Read<dwarf_off_t>(0);
|
||||||
|
if (offset >= fDebugStringSection->Size()) {
|
||||||
|
fprintf(stderr, "Invalid DW_FORM_strp offset: %lu\n",
|
||||||
|
offset);
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
attributeValue.string
|
||||||
|
= (const char*)fDebugStringSection->Data() + offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_FORM_udata:
|
||||||
|
value = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
break;
|
||||||
|
case DW_FORM_ref_addr:
|
||||||
|
value = dataReader.Read<dwarf_off_t>(0);
|
||||||
|
localReference = false;
|
||||||
|
break;
|
||||||
|
case DW_FORM_ref1:
|
||||||
|
value = dataReader.Read<uint8>(0);
|
||||||
|
break;
|
||||||
|
case DW_FORM_ref2:
|
||||||
|
value = dataReader.Read<uint16>(0);
|
||||||
|
break;
|
||||||
|
case DW_FORM_ref4:
|
||||||
|
value = dataReader.Read<uint32>(0);
|
||||||
|
break;
|
||||||
|
case DW_FORM_ref8:
|
||||||
|
value = dataReader.Read<uint64>(0);
|
||||||
|
break;
|
||||||
|
case DW_FORM_ref_udata:
|
||||||
|
value = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
break;
|
||||||
|
case DW_FORM_indirect:
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Unsupported attribute form: %lu\n",
|
||||||
|
attributeForm);
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the attribute class -- skip the attribute, if we can't handle
|
||||||
|
// it
|
||||||
|
uint8 attributeClass = get_attribute_class(attributeName,
|
||||||
|
attributeForm);
|
||||||
|
if (attributeClass == ATTRIBUTE_CLASS_UNKNOWN) {
|
||||||
|
printf("skipping attribute with unrecognized class: %s (%#lx) "
|
||||||
|
"%s (%#lx)\n", get_attribute_name_name(attributeName),
|
||||||
|
attributeName, get_attribute_form_name(attributeForm),
|
||||||
|
attributeForm);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
attributeValue.attributeClass = attributeClass;
|
||||||
|
|
||||||
|
// set the attribute value according to the attribute's class
|
||||||
|
switch (attributeClass) {
|
||||||
|
case ATTRIBUTE_CLASS_ADDRESS:
|
||||||
|
attributeValue.address = value;
|
||||||
|
break;
|
||||||
|
case ATTRIBUTE_CLASS_BLOCK:
|
||||||
|
attributeValue.block.data = dataReader.Data();
|
||||||
|
attributeValue.block.length = blockLength;
|
||||||
|
dataReader.Skip(blockLength);
|
||||||
|
break;
|
||||||
|
case ATTRIBUTE_CLASS_CONSTANT:
|
||||||
|
attributeValue.constant = value;
|
||||||
|
break;
|
||||||
|
case ATTRIBUTE_CLASS_LINEPTR:
|
||||||
|
case ATTRIBUTE_CLASS_LOCLISTPTR:
|
||||||
|
case ATTRIBUTE_CLASS_MACPTR:
|
||||||
|
case ATTRIBUTE_CLASS_RANGELISTPTR:
|
||||||
|
attributeValue.pointer = value;
|
||||||
|
break;
|
||||||
|
case ATTRIBUTE_CLASS_REFERENCE:
|
||||||
|
if (entry != NULL) {
|
||||||
|
attributeValue.reference = _ResolveReference(value,
|
||||||
|
localReference);
|
||||||
|
if (attributeValue.reference == NULL) {
|
||||||
|
fprintf(stderr, "Failed to resolve reference: "
|
||||||
|
"%s (%#lx) %s (%#lx): value: %llu\n",
|
||||||
|
get_attribute_name_name(attributeName),
|
||||||
|
attributeName,
|
||||||
|
get_attribute_form_name(attributeForm),
|
||||||
|
attributeForm, value);
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ATTRIBUTE_CLASS_FLAG:
|
||||||
|
case ATTRIBUTE_CLASS_STRING:
|
||||||
|
// already set
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataReader.HasOverflow()) {
|
||||||
|
fprintf(stderr, "Unexpected end of .debug_info section.\n");
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the attribute
|
||||||
|
if (entry != NULL) {
|
||||||
|
char buffer[1024];
|
||||||
|
printf(" attr %s %s (%d): %s\n", get_attribute_name_name(attributeName),
|
||||||
|
get_attribute_form_name(attributeForm), attributeClass, attributeValue.ToString(buffer, sizeof(buffer)));
|
||||||
|
|
||||||
|
DebugInfoEntrySetter attributeSetter
|
||||||
|
= get_attribute_name_setter(attributeName);
|
||||||
|
if (attributeSetter != NULL) {
|
||||||
|
status_t error = (entry->*attributeSetter)(attributeName,
|
||||||
|
attributeValue);
|
||||||
|
|
||||||
|
if (error == ATTRIBUTE_NOT_HANDLED) {
|
||||||
|
error = B_OK;
|
||||||
|
printf(" -> unhandled\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error != B_OK) {
|
||||||
|
fprintf(stderr, "Failed to set attribute: name: %s, "
|
||||||
|
"form: %s: %s\n",
|
||||||
|
get_attribute_name_name(attributeName),
|
||||||
|
get_attribute_form_name(attributeForm),
|
||||||
|
strerror(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf(" -> no attribute setter!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::_GetAbbreviationTable(off_t offset, AbbreviationTable*& _table)
|
||||||
|
{
|
||||||
|
// check, whether we've already loaded it
|
||||||
|
for (AbbreviationTableList::Iterator it
|
||||||
|
= fAbbreviationTables.GetIterator();
|
||||||
|
AbbreviationTable* table = it.Next();) {
|
||||||
|
if (offset == table->Offset()) {
|
||||||
|
_table = table;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a new table
|
||||||
|
AbbreviationTable* table = new(std::nothrow) AbbreviationTable(offset);
|
||||||
|
if (table == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
status_t error = table->Init(fDebugAbbrevSection->Data(),
|
||||||
|
fDebugAbbrevSection->Size());
|
||||||
|
if (error != B_OK) {
|
||||||
|
delete table;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
fAbbreviationTables.Add(table);
|
||||||
|
_table = table;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DebugInfoEntry*
|
||||||
|
DwarfFile::_ResolveReference(uint64 offset, bool localReference) const
|
||||||
|
{
|
||||||
|
if (localReference)
|
||||||
|
return fCurrentCompilationUnit->EntryForOffset(offset);
|
||||||
|
|
||||||
|
// TODO: Implement program-global references!
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef DWARF_FILE_H
|
||||||
|
#define DWARF_FILE_H
|
||||||
|
|
||||||
|
#include <util/DoublyLinkedList.h>
|
||||||
|
|
||||||
|
#include "DebugInfoEntries.h"
|
||||||
|
|
||||||
|
|
||||||
|
class AbbreviationEntry;
|
||||||
|
class AbbreviationTable;
|
||||||
|
class CompilationUnit;
|
||||||
|
class DataReader;
|
||||||
|
class ElfFile;
|
||||||
|
class ElfSection;
|
||||||
|
|
||||||
|
|
||||||
|
class DwarfFile : public DoublyLinkedListLinkImpl<DwarfFile> {
|
||||||
|
public:
|
||||||
|
DwarfFile();
|
||||||
|
~DwarfFile();
|
||||||
|
|
||||||
|
status_t Load(const char* fileName);
|
||||||
|
status_t FinishLoading();
|
||||||
|
|
||||||
|
const char* Name() const { return fName; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef DoublyLinkedList<AbbreviationTable> AbbreviationTableList;
|
||||||
|
typedef DoublyLinkedList<CompilationUnit> CompilationUnitList;
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _ParseCompilationUnit(CompilationUnit* unit);
|
||||||
|
status_t _ParseDebugInfoEntry(DataReader& dataReader,
|
||||||
|
AbbreviationTable* abbreviationTable,
|
||||||
|
DebugInfoEntry*& _entry,
|
||||||
|
bool& _endOfEntryList, int level = 0);
|
||||||
|
status_t _FinishCompilationUnit(CompilationUnit* unit);
|
||||||
|
status_t _ParseEntryAttributes(DataReader& dataReader,
|
||||||
|
DebugInfoEntry* entry,
|
||||||
|
AbbreviationEntry& abbreviationEntry);
|
||||||
|
|
||||||
|
status_t _GetAbbreviationTable(off_t offset,
|
||||||
|
AbbreviationTable*& _table);
|
||||||
|
|
||||||
|
DebugInfoEntry* _ResolveReference(uint64 offset,
|
||||||
|
bool localReference) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
char* fName;
|
||||||
|
ElfFile* fElfFile;
|
||||||
|
ElfSection* fDebugInfoSection;
|
||||||
|
ElfSection* fDebugAbbrevSection;
|
||||||
|
ElfSection* fDebugStringSection;
|
||||||
|
AbbreviationTableList fAbbreviationTables;
|
||||||
|
DebugInfoEntryFactory fDebugInfoFactory;
|
||||||
|
CompilationUnitList fCompilationUnits;
|
||||||
|
CompilationUnit* fCurrentCompilationUnit;
|
||||||
|
bool fFinished;
|
||||||
|
status_t fFinishError;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // DWARF_FILE_H
|
||||||
@@ -5,926 +5,17 @@
|
|||||||
|
|
||||||
#include "DwarfManager.h"
|
#include "DwarfManager.h"
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
#include <AutoDeleter.h>
|
#include <AutoDeleter.h>
|
||||||
#include <util/OpenHashTable.h>
|
#include <AutoLocker.h>
|
||||||
|
|
||||||
#include "Array.h"
|
#include "DwarfFile.h"
|
||||||
#include "attribute_classes.h"
|
|
||||||
#include "AttributeValue.h"
|
|
||||||
#include "DataReader.h"
|
|
||||||
#include "DebugInfoEntries.h"
|
|
||||||
#include "dwarf.h"
|
|
||||||
#include "ElfFile.h"
|
|
||||||
#include "tag_names.h"
|
|
||||||
|
|
||||||
|
|
||||||
struct AbbreviationTableEntry : HashTableLink<AbbreviationTableEntry> {
|
|
||||||
uint32 code;
|
|
||||||
off_t offset;
|
|
||||||
off_t size;
|
|
||||||
|
|
||||||
AbbreviationTableEntry(uint32 code, off_t offset, off_t size)
|
|
||||||
:
|
|
||||||
code(code),
|
|
||||||
offset(offset),
|
|
||||||
size(size)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct AbbreviationEntry {
|
|
||||||
AbbreviationEntry()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
AbbreviationEntry(uint32 code, const void* data, off_t size)
|
|
||||||
{
|
|
||||||
SetTo(code, data, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetTo(uint32 code, const void* data, off_t size)
|
|
||||||
{
|
|
||||||
fCode = code;
|
|
||||||
fAttributesReader.SetTo(data, size);
|
|
||||||
fTag = fAttributesReader.ReadUnsignedLEB128(0);
|
|
||||||
fHasChildren = fAttributesReader.Read<uint8>(0);
|
|
||||||
fData = fAttributesReader.Data();
|
|
||||||
fSize = fAttributesReader.BytesRemaining();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 Code() const { return fCode; }
|
|
||||||
uint32 Tag() const { return fTag; }
|
|
||||||
bool HasChildren() const { return fHasChildren == DW_CHILDREN_yes; }
|
|
||||||
|
|
||||||
bool GetNextAttribute(uint32& name, uint32& form)
|
|
||||||
{
|
|
||||||
name = fAttributesReader.ReadUnsignedLEB128(0);
|
|
||||||
form = fAttributesReader.ReadUnsignedLEB128(0);
|
|
||||||
return !fAttributesReader.HasOverflow() && (name != 0 || form != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint32 fCode;
|
|
||||||
const void* fData;
|
|
||||||
off_t fSize;
|
|
||||||
uint32 fTag;
|
|
||||||
uint8 fHasChildren;
|
|
||||||
DataReader fAttributesReader;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct AbbreviationTableHashDefinition {
|
|
||||||
typedef uint32 KeyType;
|
|
||||||
typedef AbbreviationTableEntry ValueType;
|
|
||||||
|
|
||||||
size_t HashKey(uint32 key) const
|
|
||||||
{
|
|
||||||
return (size_t)key;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Hash(AbbreviationTableEntry* value) const
|
|
||||||
{
|
|
||||||
return HashKey(value->code);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Compare(uint32 key, AbbreviationTableEntry* value) const
|
|
||||||
{
|
|
||||||
return value->code == key;
|
|
||||||
}
|
|
||||||
|
|
||||||
HashTableLink<AbbreviationTableEntry>* GetLink(
|
|
||||||
AbbreviationTableEntry* value) const
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef OpenHashTable<AbbreviationTableHashDefinition> AbbreviationEntryTable;
|
|
||||||
|
|
||||||
|
|
||||||
class AbbreviationTable : public DoublyLinkedListLinkImpl<AbbreviationTable> {
|
|
||||||
public:
|
|
||||||
AbbreviationTable(off_t offset)
|
|
||||||
:
|
|
||||||
fOffset(offset),
|
|
||||||
fData(NULL),
|
|
||||||
fSize(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~AbbreviationTable()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t Init(const void* section, off_t sectionSize)
|
|
||||||
{
|
|
||||||
if (fOffset < 0 || fOffset >= sectionSize)
|
|
||||||
return B_BAD_DATA;
|
|
||||||
|
|
||||||
fData = (uint8*)section + fOffset;
|
|
||||||
fSize = sectionSize - fOffset;
|
|
||||||
// That's only the maximum size. Will be adjusted at the end.
|
|
||||||
|
|
||||||
status_t error = fEntryTable.Init();
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
DataReader abbrevReader(fData, fSize);
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
bool nullEntry;
|
|
||||||
status_t error = _ParseAbbreviationEntry(abbrevReader, nullEntry);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
if (nullEntry)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
fSize -= abbrevReader.BytesRemaining();
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
off_t Offset() const
|
|
||||||
{
|
|
||||||
return fOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GetAbbreviationEntry(uint32 code, AbbreviationEntry& entry)
|
|
||||||
{
|
|
||||||
AbbreviationTableEntry* tableEntry = fEntryTable.Lookup(code);
|
|
||||||
if (tableEntry == NULL)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
entry.SetTo(code, fData + tableEntry->offset, tableEntry->size);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t _ParseAbbreviationEntry(DataReader& abbrevReader, bool& _nullEntry)
|
|
||||||
{
|
|
||||||
uint32 code = abbrevReader.ReadUnsignedLEB128(0);
|
|
||||||
if (code == 0) {
|
|
||||||
if (abbrevReader.HasOverflow()) {
|
|
||||||
fprintf(stderr, "Invalid abbreviation table 1!\n");
|
|
||||||
return B_BAD_DATA;
|
|
||||||
}
|
|
||||||
_nullEntry = true;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
off_t remaining = abbrevReader.BytesRemaining();
|
|
||||||
|
|
||||||
/* uint32 tag =*/ abbrevReader.ReadUnsignedLEB128(0);
|
|
||||||
/* uint8 hasChildren =*/ abbrevReader.Read<uint8>(DW_CHILDREN_no);
|
|
||||||
|
|
||||||
// printf("entry: %lu, tag: %lu, children: %d\n", code, tag,
|
|
||||||
// hasChildren);
|
|
||||||
|
|
||||||
// parse attribute specifications
|
|
||||||
while (true) {
|
|
||||||
uint32 attributeName = abbrevReader.ReadUnsignedLEB128(0);
|
|
||||||
uint32 attributeForm = abbrevReader.ReadUnsignedLEB128(0);
|
|
||||||
if (abbrevReader.HasOverflow()) {
|
|
||||||
fprintf(stderr, "Invalid abbreviation table 2!\n");
|
|
||||||
return B_BAD_DATA;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attributeName == 0 && attributeForm == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// printf(" attr: name: %lu, form: %lu\n", attributeName,
|
|
||||||
// attributeForm);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the entry
|
|
||||||
if (fEntryTable.Lookup(code) == NULL) {
|
|
||||||
AbbreviationTableEntry* entry = new(std::nothrow)
|
|
||||||
AbbreviationTableEntry(code, fSize - remaining,
|
|
||||||
remaining - abbrevReader.BytesRemaining());
|
|
||||||
if (entry == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
fEntryTable.Insert(entry);
|
|
||||||
} else
|
|
||||||
fprintf(stderr, "Duplicate abbreviation table entry %lu!\n", code);
|
|
||||||
|
|
||||||
_nullEntry = false;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
off_t fOffset;
|
|
||||||
const uint8* fData;
|
|
||||||
off_t fSize;
|
|
||||||
AbbreviationEntryTable fEntryTable;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - CompilationUnit
|
|
||||||
|
|
||||||
|
|
||||||
struct DwarfManager::CompilationUnit
|
|
||||||
: DoublyLinkedListLinkImpl<CompilationUnit> {
|
|
||||||
CompilationUnit(dwarf_off_t headerOffset, dwarf_off_t contentOffset,
|
|
||||||
dwarf_off_t totalSize, dwarf_off_t abbreviationOffset)
|
|
||||||
:
|
|
||||||
fHeaderOffset(headerOffset),
|
|
||||||
fContentOffset(contentOffset),
|
|
||||||
fTotalSize(totalSize),
|
|
||||||
fAbbreviationOffset(abbreviationOffset),
|
|
||||||
fAbbreviationTable(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~CompilationUnit()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
dwarf_off_t HeaderOffset() const
|
|
||||||
{
|
|
||||||
return fHeaderOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
dwarf_off_t ContentOffset() const
|
|
||||||
{
|
|
||||||
return fContentOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
dwarf_off_t RelativeContentOffset() const
|
|
||||||
{
|
|
||||||
return fContentOffset - fHeaderOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
dwarf_off_t TotalSize() const
|
|
||||||
{
|
|
||||||
return fTotalSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
dwarf_off_t ContentSize() const
|
|
||||||
{
|
|
||||||
return fTotalSize - RelativeContentOffset();
|
|
||||||
}
|
|
||||||
|
|
||||||
dwarf_off_t AbbreviationOffset() const
|
|
||||||
{
|
|
||||||
return fAbbreviationOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetAbbreviationTable(AbbreviationTable* abbreviationTable)
|
|
||||||
{
|
|
||||||
fAbbreviationTable = abbreviationTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
AbbreviationTable* GetAbbreviationTable() const
|
|
||||||
{
|
|
||||||
return fAbbreviationTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t AddDebugInfoEntry(DebugInfoEntry* entry, dwarf_off_t offset)
|
|
||||||
{
|
|
||||||
if (!fEntries.Add(entry))
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
if (!fEntryOffsets.Add(offset)) {
|
|
||||||
fEntries.Remove(fEntries.Count() - 1);
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CountEntries() const
|
|
||||||
{
|
|
||||||
return fEntries.Count();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetEntryAt(int index, DebugInfoEntry*& entry,
|
|
||||||
dwarf_off_t& offset) const
|
|
||||||
{
|
|
||||||
entry = fEntries[index];
|
|
||||||
offset = fEntryOffsets[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugInfoEntry* EntryForOffset(dwarf_off_t offset) const
|
|
||||||
{
|
|
||||||
if (fEntries.IsEmpty())
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
// binary search
|
|
||||||
int lower = 0;
|
|
||||||
int upper = fEntries.Count() - 1;
|
|
||||||
while (lower < upper) {
|
|
||||||
int mid = (lower + upper + 1) / 2;
|
|
||||||
if (fEntryOffsets[mid] > offset)
|
|
||||||
upper = mid - 1;
|
|
||||||
else
|
|
||||||
lower = mid;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fEntryOffsets[lower] == offset ? fEntries[lower] : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
dwarf_off_t fHeaderOffset;
|
|
||||||
dwarf_off_t fContentOffset;
|
|
||||||
dwarf_off_t fTotalSize;
|
|
||||||
dwarf_off_t fAbbreviationOffset;
|
|
||||||
AbbreviationTable* fAbbreviationTable;
|
|
||||||
Array<DebugInfoEntry*> fEntries;
|
|
||||||
Array<dwarf_off_t> fEntryOffsets;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - File
|
|
||||||
|
|
||||||
|
|
||||||
struct DwarfManager::File : DoublyLinkedListLinkImpl<File> {
|
|
||||||
File()
|
|
||||||
:
|
|
||||||
fName(NULL),
|
|
||||||
fElfFile(NULL),
|
|
||||||
fDebugInfoSection(NULL),
|
|
||||||
fDebugAbbrevSection(NULL),
|
|
||||||
fDebugStringSection(NULL),
|
|
||||||
fCurrentCompilationUnit(NULL),
|
|
||||||
fFinished(false),
|
|
||||||
fFinishError(B_OK)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~File()
|
|
||||||
{
|
|
||||||
while (CompilationUnit* unit = fCompilationUnits.RemoveHead())
|
|
||||||
delete unit;
|
|
||||||
|
|
||||||
while (AbbreviationTable* table = fAbbreviationTables.RemoveHead())
|
|
||||||
delete table;
|
|
||||||
|
|
||||||
if (fElfFile != NULL) {
|
|
||||||
fElfFile->PutSection(fDebugInfoSection);
|
|
||||||
fElfFile->PutSection(fDebugAbbrevSection);
|
|
||||||
fElfFile->PutSection(fDebugStringSection);
|
|
||||||
delete fElfFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(fName);
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t Load(const char* fileName)
|
|
||||||
{
|
|
||||||
fName = strdup(fileName);
|
|
||||||
if (fName == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
// load the ELF file
|
|
||||||
fElfFile = new(std::nothrow) ElfFile;
|
|
||||||
if (fElfFile == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
status_t error = fElfFile->Init(fileName);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
// get the interesting sections
|
|
||||||
fDebugInfoSection = fElfFile->GetSection(".debug_info");
|
|
||||||
fDebugAbbrevSection = fElfFile->GetSection(".debug_abbrev");
|
|
||||||
fDebugStringSection = fElfFile->GetSection(".debug_str");
|
|
||||||
if (fDebugInfoSection == NULL || fDebugAbbrevSection == NULL
|
|
||||||
|| fDebugStringSection == NULL) {
|
|
||||||
fprintf(stderr, "DwarfManager::File::Load(\"%s\"): no "
|
|
||||||
".debug_info, .debug_abbrev, or .debug_str section.\n",
|
|
||||||
fileName);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
dwarf_off_t unitLengthOffset = dataReader.Offset();
|
|
||||||
// the unitLength starts here
|
|
||||||
|
|
||||||
if (unitLengthOffset + unitLength
|
|
||||||
> (uint64)fDebugInfoSection->Size()) {
|
|
||||||
printf("\"%s\": Invalid compilation unit length.\n", fileName);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int version = dataReader.Read<uint16>(0);
|
|
||||||
off_t abbrevOffset = dwarf64
|
|
||||||
? dataReader.Read<uint64>(0)
|
|
||||||
: dataReader.Read<uint32>(0);
|
|
||||||
uint8 addressSize = dataReader.Read<uint8>(0);
|
|
||||||
|
|
||||||
if (dataReader.HasOverflow()) {
|
|
||||||
printf("\"%s\": Unexpected end of data in compilation unit "
|
|
||||||
"header.\n", fileName);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("DWARF%d compilation unit: version %d, length: %lld, "
|
|
||||||
"abbrevOffset: %lld, address size: %d\n", dwarf64 ? 64 : 32,
|
|
||||||
version, unitLength, abbrevOffset, addressSize);
|
|
||||||
|
|
||||||
if (version != 2 && version != 3) {
|
|
||||||
printf("\"%s\": Unsupported compilation unit version: %d\n",
|
|
||||||
fileName, version);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addressSize != 4) {
|
|
||||||
printf("\"%s\": Unsupported address size: %d\n", fileName,
|
|
||||||
addressSize);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
dwarf_off_t unitContentOffset = dataReader.Offset();
|
|
||||||
|
|
||||||
// create a compilation unit object
|
|
||||||
CompilationUnit* unit = new(std::nothrow) CompilationUnit(
|
|
||||||
unitHeaderOffset, unitContentOffset,
|
|
||||||
unitLength + (unitLengthOffset - unitHeaderOffset),
|
|
||||||
abbrevOffset);
|
|
||||||
if (unit == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
fCompilationUnits.Add(unit);
|
|
||||||
|
|
||||||
// parse the debug info for the unit
|
|
||||||
fCurrentCompilationUnit = unit;
|
|
||||||
error = _ParseCompilationUnit(unit);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
dataReader.SeekAbsolute(unitLengthOffset + unitLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t FinishLoading()
|
|
||||||
{
|
|
||||||
if (fFinished)
|
|
||||||
return B_OK;
|
|
||||||
if (fFinishError != B_OK)
|
|
||||||
return fFinishError;
|
|
||||||
|
|
||||||
for (CompilationUnitList::Iterator it = fCompilationUnits.GetIterator();
|
|
||||||
CompilationUnit* unit = it.Next();) {
|
|
||||||
fCurrentCompilationUnit = unit;
|
|
||||||
status_t error = _FinishCompilationUnit(unit);
|
|
||||||
if (error != B_OK)
|
|
||||||
return fFinishError = error;
|
|
||||||
}
|
|
||||||
|
|
||||||
fFinished = true;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* Name() const
|
|
||||||
{
|
|
||||||
return fName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef DoublyLinkedList<AbbreviationTable> AbbreviationTableList;
|
|
||||||
typedef DoublyLinkedList<CompilationUnit> CompilationUnitList;
|
|
||||||
|
|
||||||
private:
|
|
||||||
status_t _ParseCompilationUnit(CompilationUnit* unit)
|
|
||||||
{
|
|
||||||
AbbreviationTable* abbreviationTable;
|
|
||||||
status_t error = _GetAbbreviationTable(unit->AbbreviationOffset(),
|
|
||||||
abbreviationTable);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
unit->SetAbbreviationTable(abbreviationTable);
|
|
||||||
|
|
||||||
DataReader dataReader(
|
|
||||||
(const uint8*)fDebugInfoSection->Data() + unit->ContentOffset(),
|
|
||||||
unit->ContentSize());
|
|
||||||
|
|
||||||
DebugInfoEntry* entry;
|
|
||||||
bool endOfEntryList;
|
|
||||||
error = _ParseDebugInfoEntry(dataReader, abbreviationTable, entry,
|
|
||||||
endOfEntryList);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
if (dynamic_cast<DIECompileUnitBase*>(entry) == NULL) {
|
|
||||||
fprintf(stderr, "No compilation unit entry in .debug_info "
|
|
||||||
"section.\n");
|
|
||||||
return B_BAD_DATA;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("remaining bytes in unit: %lld\n", dataReader.BytesRemaining());
|
|
||||||
if (dataReader.HasData()) {
|
|
||||||
printf(" ");
|
|
||||||
while (dataReader.HasData()) {
|
|
||||||
printf("%02x", dataReader.Read<uint8>(0));
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t _ParseDebugInfoEntry(DataReader& dataReader,
|
|
||||||
AbbreviationTable* abbreviationTable, DebugInfoEntry*& _entry,
|
|
||||||
bool& _endOfEntryList, int level = 0)
|
|
||||||
{
|
|
||||||
dwarf_off_t entryOffset = dataReader.Offset()
|
|
||||||
+ fCurrentCompilationUnit->RelativeContentOffset();
|
|
||||||
|
|
||||||
uint32 code = dataReader.ReadUnsignedLEB128(0);
|
|
||||||
if (code == 0) {
|
|
||||||
if (dataReader.HasOverflow()) {
|
|
||||||
fprintf(stderr, "Unexpected end of .debug_info section.\n");
|
|
||||||
return B_BAD_DATA;
|
|
||||||
}
|
|
||||||
_entry = NULL;
|
|
||||||
_endOfEntryList = true;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the corresponding abbreviation entry
|
|
||||||
AbbreviationEntry abbreviationEntry;
|
|
||||||
if (!abbreviationTable->GetAbbreviationEntry(code, abbreviationEntry)) {
|
|
||||||
fprintf(stderr, "No abbreviation entry for code %lu\n", code);
|
|
||||||
return B_BAD_DATA;
|
|
||||||
}
|
|
||||||
printf("%*sentry at %lu: %lu, tag: %s (%lu), children: %d\n", level * 2, "",
|
|
||||||
entryOffset, abbreviationEntry.Code(), get_entry_tag_name(abbreviationEntry.Tag()),
|
|
||||||
abbreviationEntry.Tag(), abbreviationEntry.HasChildren());
|
|
||||||
|
|
||||||
DebugInfoEntry* entry;
|
|
||||||
status_t error = fDebugInfoFactory.CreateDebugInfoEntry(
|
|
||||||
abbreviationEntry.Tag(), entry);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
ObjectDeleter<DebugInfoEntry> entryDeleter(entry);
|
|
||||||
|
|
||||||
error = fCurrentCompilationUnit->AddDebugInfoEntry(entry, entryOffset);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
// parse the attributes (supply NULL entry to avoid adding them yet)
|
|
||||||
error = _ParseEntryAttributes(dataReader, NULL, abbreviationEntry);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
// parse children, if the entry has any
|
|
||||||
if (abbreviationEntry.HasChildren()) {
|
|
||||||
while (true) {
|
|
||||||
DebugInfoEntry* childEntry;
|
|
||||||
bool endOfEntryList;
|
|
||||||
status_t error = _ParseDebugInfoEntry(dataReader,
|
|
||||||
abbreviationTable, childEntry, endOfEntryList, level + 1);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
// add the child to our entry
|
|
||||||
if (childEntry != NULL) {
|
|
||||||
if (entry != NULL) {
|
|
||||||
error = entry->AddChild(childEntry);
|
|
||||||
if (error == ENTRY_NOT_HANDLED) {
|
|
||||||
error = B_OK;
|
|
||||||
printf("%*s -> child unhandled\n", level * 2, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error != B_OK) {
|
|
||||||
delete childEntry;
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
delete childEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (endOfEntryList)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
entryDeleter.Detach();
|
|
||||||
_entry = entry;
|
|
||||||
_endOfEntryList = false;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t _FinishCompilationUnit(CompilationUnit* unit)
|
|
||||||
{
|
|
||||||
printf("\nfinishing compilation unit %p\n", unit);
|
|
||||||
AbbreviationTable* abbreviationTable = unit->GetAbbreviationTable();
|
|
||||||
|
|
||||||
DataReader dataReader(
|
|
||||||
(const uint8*)fDebugInfoSection->Data() + unit->HeaderOffset(),
|
|
||||||
unit->TotalSize());
|
|
||||||
// DataReader dataReader(
|
|
||||||
// (const uint8*)fDebugInfoSection->Data() + unit->ContentOffset(),
|
|
||||||
// unit->ContentSize());
|
|
||||||
|
|
||||||
DebugInfoEntryInitInfo entryInitInfo;
|
|
||||||
|
|
||||||
int entryCount = unit->CountEntries();
|
|
||||||
for (int i = 0; i < entryCount; i++) {
|
|
||||||
// get the entry
|
|
||||||
DebugInfoEntry* entry;
|
|
||||||
dwarf_off_t offset;
|
|
||||||
unit->GetEntryAt(i, entry, offset);
|
|
||||||
printf("entry %p at %lu\n", entry, offset);
|
|
||||||
|
|
||||||
// seek the reader to the entry
|
|
||||||
dataReader.SeekAbsolute(offset);
|
|
||||||
|
|
||||||
// read the entry code
|
|
||||||
uint32 code = dataReader.ReadUnsignedLEB128(0);
|
|
||||||
|
|
||||||
// get the respective abbreviation entry
|
|
||||||
AbbreviationEntry abbreviationEntry;
|
|
||||||
abbreviationTable->GetAbbreviationEntry(code, abbreviationEntry);
|
|
||||||
|
|
||||||
// initialization before setting the attributes
|
|
||||||
status_t error = entry->InitAfterHierarchy(entryInitInfo);
|
|
||||||
if (error != B_OK) {
|
|
||||||
fprintf(stderr, "Init after hierarchy failed!\n");
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse the attributes -- this time pass the entry, so that the
|
|
||||||
// attribute get set on it
|
|
||||||
error = _ParseEntryAttributes(dataReader, entry, abbreviationEntry);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
// initialization after setting the attributes
|
|
||||||
error = entry->InitAfterAttributes(entryInitInfo);
|
|
||||||
if (error != B_OK) {
|
|
||||||
fprintf(stderr, "Init after attributes failed!\n");
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t _ParseEntryAttributes(DataReader& dataReader,
|
|
||||||
DebugInfoEntry* entry, AbbreviationEntry& abbreviationEntry)
|
|
||||||
{
|
|
||||||
uint32 attributeName;
|
|
||||||
uint32 attributeForm;
|
|
||||||
while (abbreviationEntry.GetNextAttribute(attributeName,
|
|
||||||
attributeForm)) {
|
|
||||||
// resolve attribute form indirection
|
|
||||||
if (attributeForm == DW_FORM_indirect)
|
|
||||||
attributeForm = dataReader.ReadUnsignedLEB128(0);
|
|
||||||
|
|
||||||
// prepare an AttributeValue
|
|
||||||
AttributeValue attributeValue;
|
|
||||||
attributeValue.attributeForm = attributeForm;
|
|
||||||
attributeValue.isSigned = false;
|
|
||||||
|
|
||||||
// Read the attribute value according to the attribute's form. For
|
|
||||||
// the forms that don't map to a single attribute class only or
|
|
||||||
// those that need additional processing, we read a temporary value
|
|
||||||
// first.
|
|
||||||
uint64 value = 0;
|
|
||||||
dwarf_size_t blockLength = 0;
|
|
||||||
bool localReference = true;
|
|
||||||
|
|
||||||
switch (attributeForm) {
|
|
||||||
case DW_FORM_addr:
|
|
||||||
value = dataReader.Read<dwarf_addr_t>(0);
|
|
||||||
break;
|
|
||||||
case DW_FORM_block2:
|
|
||||||
blockLength = dataReader.Read<uint16>(0);
|
|
||||||
break;
|
|
||||||
case DW_FORM_block4:
|
|
||||||
blockLength = dataReader.Read<uint32>(0);
|
|
||||||
break;
|
|
||||||
case DW_FORM_data2:
|
|
||||||
value = dataReader.Read<uint16>(0);
|
|
||||||
break;
|
|
||||||
case DW_FORM_data4:
|
|
||||||
value = dataReader.Read<uint32>(0);
|
|
||||||
break;
|
|
||||||
case DW_FORM_data8:
|
|
||||||
value = dataReader.Read<uint64>(0);
|
|
||||||
break;
|
|
||||||
case DW_FORM_string:
|
|
||||||
attributeValue.string = dataReader.ReadString();
|
|
||||||
break;
|
|
||||||
case DW_FORM_block:
|
|
||||||
blockLength = dataReader.ReadUnsignedLEB128(0);
|
|
||||||
break;
|
|
||||||
case DW_FORM_block1:
|
|
||||||
blockLength = dataReader.Read<uint8>(0);
|
|
||||||
break;
|
|
||||||
case DW_FORM_data1:
|
|
||||||
value = dataReader.Read<uint8>(0);
|
|
||||||
break;
|
|
||||||
case DW_FORM_flag:
|
|
||||||
attributeValue.flag = dataReader.Read<uint8>(0) != 0;
|
|
||||||
break;
|
|
||||||
case DW_FORM_sdata:
|
|
||||||
value = dataReader.ReadSignedLEB128(0);
|
|
||||||
attributeValue.isSigned = true;
|
|
||||||
break;
|
|
||||||
case DW_FORM_strp:
|
|
||||||
{
|
|
||||||
dwarf_off_t offset = dataReader.Read<dwarf_off_t>(0);
|
|
||||||
if (offset >= fDebugStringSection->Size()) {
|
|
||||||
fprintf(stderr, "Invalid DW_FORM_strp offset: %lu\n",
|
|
||||||
offset);
|
|
||||||
return B_BAD_DATA;
|
|
||||||
}
|
|
||||||
attributeValue.string
|
|
||||||
= (const char*)fDebugStringSection->Data() + offset;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DW_FORM_udata:
|
|
||||||
value = dataReader.ReadUnsignedLEB128(0);
|
|
||||||
break;
|
|
||||||
case DW_FORM_ref_addr:
|
|
||||||
value = dataReader.Read<dwarf_off_t>(0);
|
|
||||||
localReference = false;
|
|
||||||
break;
|
|
||||||
case DW_FORM_ref1:
|
|
||||||
value = dataReader.Read<uint8>(0);
|
|
||||||
break;
|
|
||||||
case DW_FORM_ref2:
|
|
||||||
value = dataReader.Read<uint16>(0);
|
|
||||||
break;
|
|
||||||
case DW_FORM_ref4:
|
|
||||||
value = dataReader.Read<uint32>(0);
|
|
||||||
break;
|
|
||||||
case DW_FORM_ref8:
|
|
||||||
value = dataReader.Read<uint64>(0);
|
|
||||||
break;
|
|
||||||
case DW_FORM_ref_udata:
|
|
||||||
value = dataReader.ReadUnsignedLEB128(0);
|
|
||||||
break;
|
|
||||||
case DW_FORM_indirect:
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "Unsupported attribute form: %lu\n",
|
|
||||||
attributeForm);
|
|
||||||
return B_BAD_DATA;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the attribute class -- skip the attribute, if we can't handle
|
|
||||||
// it
|
|
||||||
uint8 attributeClass = get_attribute_class(attributeName,
|
|
||||||
attributeForm);
|
|
||||||
if (attributeClass == ATTRIBUTE_CLASS_UNKNOWN) {
|
|
||||||
printf("skipping attribute with unrecognized class: %s (%#lx) "
|
|
||||||
"%s (%#lx)\n", get_attribute_name_name(attributeName),
|
|
||||||
attributeName, get_attribute_form_name(attributeForm),
|
|
||||||
attributeForm);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
attributeValue.attributeClass = attributeClass;
|
|
||||||
|
|
||||||
// set the attribute value according to the attribute's class
|
|
||||||
switch (attributeClass) {
|
|
||||||
case ATTRIBUTE_CLASS_ADDRESS:
|
|
||||||
attributeValue.address = value;
|
|
||||||
break;
|
|
||||||
case ATTRIBUTE_CLASS_BLOCK:
|
|
||||||
attributeValue.block.data = dataReader.Data();
|
|
||||||
attributeValue.block.length = blockLength;
|
|
||||||
dataReader.Skip(blockLength);
|
|
||||||
break;
|
|
||||||
case ATTRIBUTE_CLASS_CONSTANT:
|
|
||||||
attributeValue.constant = value;
|
|
||||||
break;
|
|
||||||
case ATTRIBUTE_CLASS_LINEPTR:
|
|
||||||
case ATTRIBUTE_CLASS_LOCLISTPTR:
|
|
||||||
case ATTRIBUTE_CLASS_MACPTR:
|
|
||||||
case ATTRIBUTE_CLASS_RANGELISTPTR:
|
|
||||||
attributeValue.pointer = value;
|
|
||||||
break;
|
|
||||||
case ATTRIBUTE_CLASS_REFERENCE:
|
|
||||||
if (entry != NULL) {
|
|
||||||
attributeValue.reference = _ResolveReference(value,
|
|
||||||
localReference);
|
|
||||||
if (attributeValue.reference == NULL) {
|
|
||||||
fprintf(stderr, "Failed to resolve reference: "
|
|
||||||
"%s (%#lx) %s (%#lx): value: %llu\n",
|
|
||||||
get_attribute_name_name(attributeName),
|
|
||||||
attributeName,
|
|
||||||
get_attribute_form_name(attributeForm),
|
|
||||||
attributeForm, value);
|
|
||||||
return B_ENTRY_NOT_FOUND;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ATTRIBUTE_CLASS_FLAG:
|
|
||||||
case ATTRIBUTE_CLASS_STRING:
|
|
||||||
// already set
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dataReader.HasOverflow()) {
|
|
||||||
fprintf(stderr, "Unexpected end of .debug_info section.\n");
|
|
||||||
return B_BAD_DATA;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the attribute
|
|
||||||
if (entry != NULL) {
|
|
||||||
char buffer[1024];
|
|
||||||
printf(" attr %s %s (%d): %s\n", get_attribute_name_name(attributeName),
|
|
||||||
get_attribute_form_name(attributeForm), attributeClass, attributeValue.ToString(buffer, sizeof(buffer)));
|
|
||||||
|
|
||||||
DebugInfoEntrySetter attributeSetter
|
|
||||||
= get_attribute_name_setter(attributeName);
|
|
||||||
if (attributeSetter != NULL) {
|
|
||||||
status_t error = (entry->*attributeSetter)(attributeName,
|
|
||||||
attributeValue);
|
|
||||||
|
|
||||||
if (error == ATTRIBUTE_NOT_HANDLED) {
|
|
||||||
error = B_OK;
|
|
||||||
printf(" -> unhandled\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error != B_OK) {
|
|
||||||
fprintf(stderr, "Failed to set attribute: name: %s, "
|
|
||||||
"form: %s: %s\n",
|
|
||||||
get_attribute_name_name(attributeName),
|
|
||||||
get_attribute_form_name(attributeForm),
|
|
||||||
strerror(error));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
printf(" -> no attribute setter!\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t _GetAbbreviationTable(off_t offset, AbbreviationTable*& _table)
|
|
||||||
{
|
|
||||||
// check, whether we've already loaded it
|
|
||||||
for (AbbreviationTableList::Iterator it
|
|
||||||
= fAbbreviationTables.GetIterator();
|
|
||||||
AbbreviationTable* table = it.Next();) {
|
|
||||||
if (offset == table->Offset()) {
|
|
||||||
_table = table;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a new table
|
|
||||||
AbbreviationTable* table = new(std::nothrow) AbbreviationTable(offset);
|
|
||||||
if (table == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
status_t error = table->Init(fDebugAbbrevSection->Data(),
|
|
||||||
fDebugAbbrevSection->Size());
|
|
||||||
if (error != B_OK) {
|
|
||||||
delete table;
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
fAbbreviationTables.Add(table);
|
|
||||||
_table = table;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugInfoEntry* _ResolveReference(uint64 offset, bool localReference) const
|
|
||||||
{
|
|
||||||
if (localReference)
|
|
||||||
return fCurrentCompilationUnit->EntryForOffset(offset);
|
|
||||||
|
|
||||||
// TODO: Implement program-global references!
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
char* fName;
|
|
||||||
ElfFile* fElfFile;
|
|
||||||
ElfSection* fDebugInfoSection;
|
|
||||||
ElfSection* fDebugAbbrevSection;
|
|
||||||
ElfSection* fDebugStringSection;
|
|
||||||
AbbreviationTableList fAbbreviationTables;
|
|
||||||
DebugInfoEntryFactory fDebugInfoFactory;
|
|
||||||
CompilationUnitList fCompilationUnits;
|
|
||||||
CompilationUnit* fCurrentCompilationUnit;
|
|
||||||
bool fFinished;
|
|
||||||
status_t fFinishError;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
DwarfManager::DwarfManager()
|
DwarfManager::DwarfManager()
|
||||||
|
:
|
||||||
|
fLock("dwarf manager")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -937,14 +28,16 @@ DwarfManager::~DwarfManager()
|
|||||||
status_t
|
status_t
|
||||||
DwarfManager::Init()
|
DwarfManager::Init()
|
||||||
{
|
{
|
||||||
return B_OK;
|
return fLock.InitCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfManager::LoadFile(const char* fileName)
|
DwarfManager::LoadFile(const char* fileName)
|
||||||
{
|
{
|
||||||
File* file = new(std::nothrow) File;
|
AutoLocker<DwarfManager> locker(this);
|
||||||
|
|
||||||
|
DwarfFile* file = new(std::nothrow) DwarfFile;
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -963,8 +56,10 @@ DwarfManager::LoadFile(const char* fileName)
|
|||||||
status_t
|
status_t
|
||||||
DwarfManager::FinishLoading()
|
DwarfManager::FinishLoading()
|
||||||
{
|
{
|
||||||
|
AutoLocker<DwarfManager> locker(this);
|
||||||
|
|
||||||
for (FileList::Iterator it = fFiles.GetIterator();
|
for (FileList::Iterator it = fFiles.GetIterator();
|
||||||
File* file = it.Next();) {
|
DwarfFile* file = it.Next();) {
|
||||||
status_t error = file->FinishLoading();
|
status_t error = file->FinishLoading();
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|||||||
@@ -5,13 +5,14 @@
|
|||||||
#ifndef DWARF_MANAGER_H
|
#ifndef DWARF_MANAGER_H
|
||||||
#define DWARF_MANAGER_H
|
#define DWARF_MANAGER_H
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <Locker.h>
|
||||||
|
|
||||||
#include <SupportDefs.h>
|
|
||||||
|
|
||||||
#include <util/DoublyLinkedList.h>
|
#include <util/DoublyLinkedList.h>
|
||||||
|
|
||||||
|
|
||||||
|
class DwarfFile;
|
||||||
|
|
||||||
|
|
||||||
class DwarfManager {
|
class DwarfManager {
|
||||||
public:
|
public:
|
||||||
DwarfManager();
|
DwarfManager();
|
||||||
@@ -19,15 +20,17 @@ public:
|
|||||||
|
|
||||||
status_t Init();
|
status_t Init();
|
||||||
|
|
||||||
|
bool Lock() { return fLock.Lock(); }
|
||||||
|
void Unlock() { fLock.Unlock(); }
|
||||||
|
|
||||||
status_t LoadFile(const char* fileName);
|
status_t LoadFile(const char* fileName);
|
||||||
status_t FinishLoading();
|
status_t FinishLoading();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct CompilationUnit;
|
typedef DoublyLinkedList<DwarfFile> FileList;
|
||||||
struct File;
|
|
||||||
typedef DoublyLinkedList<File> FileList;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
BLocker fLock;
|
||||||
FileList fFiles;
|
FileList fFiles;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef TYPES_H
|
#ifndef DWARF_TYPES_H
|
||||||
#define TYPES_H
|
#define DWARF_TYPES_H
|
||||||
|
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
@@ -19,4 +19,4 @@ typedef uint32 dwarf_size_t;
|
|||||||
#define DWARF_ADDRESS_MAX 0xffffffff
|
#define DWARF_ADDRESS_MAX 0xffffffff
|
||||||
|
|
||||||
|
|
||||||
#endif // TYPES_H
|
#endif // DWARF_TYPES_H
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
SubDir HAIKU_TOP src apps debugger dwarf ;
|
||||||
|
|
||||||
|
CCFLAGS += -Werror ;
|
||||||
|
C++FLAGS += -Werror ;
|
||||||
|
|
||||||
|
UsePrivateHeaders kernel shared ;
|
||||||
|
UsePrivateSystemHeaders ;
|
||||||
|
|
||||||
|
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ;
|
||||||
|
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) elf ] ;
|
||||||
|
|
||||||
|
|
||||||
|
MergeObject Debugger_dwarf.o
|
||||||
|
:
|
||||||
|
AbbreviationTable.cpp
|
||||||
|
AttributeClasses.cpp
|
||||||
|
AttributeValue.cpp
|
||||||
|
CompilationUnit.cpp
|
||||||
|
DebugInfoEntries.cpp
|
||||||
|
DebugInfoEntry.cpp
|
||||||
|
DwarfFile.cpp
|
||||||
|
DwarfManager.cpp
|
||||||
|
SourceLanguageInfo.cpp
|
||||||
|
TagNames.cpp
|
||||||
|
;
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include "SourceLanguageInfo.h"
|
#include "SourceLanguageInfo.h"
|
||||||
|
|
||||||
#include "dwarf.h"
|
#include "Dwarf.h"
|
||||||
|
|
||||||
|
|
||||||
UnknownSourceLanguageInfo::UnknownSourceLanguageInfo()
|
UnknownSourceLanguageInfo::UnknownSourceLanguageInfo()
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tag_names.h"
|
#include "TagNames.h"
|
||||||
|
|
||||||
#include "dwarf.h"
|
#include "Dwarf.h"
|
||||||
|
|
||||||
|
|
||||||
struct tag_name_info {
|
struct tag_name_info {
|
||||||
@@ -2,8 +2,8 @@
|
|||||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef TAG_NAMES_H
|
#ifndef DWARF_TAG_NAMES_H
|
||||||
#define TAG_NAMES_H
|
#define DWARF_TAG_NAMES_H
|
||||||
|
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
@@ -11,4 +11,4 @@
|
|||||||
const char* get_entry_tag_name(uint16 tag);
|
const char* get_entry_tag_name(uint16 tag);
|
||||||
|
|
||||||
|
|
||||||
#endif // TAG_NAMES_H
|
#endif // DWARF_TAG_NAMES_H
|
||||||
Reference in New Issue
Block a user