* WIP regarding non comilation unit local types:

- Introduced GlobalTypeLookup interface and GlobalTypeLookupContext to look
    up types by name and cache them.
  - TeamDebugInfo implementes GlobalTypeLookup iterating through all
    ImageDebugInfos, which in turn iterate through all SpecificImageDebugInfos.
  - DwarfImageDebugInfo iterates through all compilation units, using
    a temporary DwarfStackFrameDebugInfo to create the type.
  - DwarfStackFrameDebugInfo no longer caches the types itself, but uses
    GlobalTypeLookupContext. It uses GlobalTypeLookup to look up types not
    defined in the compilation unit.
  - DwarfFile: Made expression evaluation more robust, so that it also works,
    when no subroutine entry, frame pointer, and instruction pointer are
    available (and not used by the expression).
  Basically works already, although the wrong compilation unit might be used
  when resolving values for global types. It's also horribly slow, when there
  are many types in the stack frame.
* DwarfStackFrameDebugInfo::ResolveArrayElementLocation(): The element location
  piece size was set incorrectly (multiplied by 8, although bytes were
  expected).



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33477 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-10-07 03:17:22 +00:00
parent d48ea308bf
commit 71f75cdcde
17 changed files with 564 additions and 131 deletions
+1
View File
@@ -65,6 +65,7 @@ Application Debugger :
Function.cpp
FunctionDebugInfo.cpp
FunctionInstance.cpp
GlobalTypeLookup.cpp
ImageDebugInfo.cpp
ImageDebugInfoProvider.cpp
NoOpStackFrameDebugInfo.cpp
@@ -78,6 +78,14 @@ DebuggerImageDebugInfo::GetFunctions(BObjectList<FunctionDebugInfo>& functions)
}
status_t
DebuggerImageDebugInfo::GetType(GlobalTypeLookupContext* context,
const BString& name, Type*& _type)
{
return B_UNSUPPORTED;
}
status_t
DebuggerImageDebugInfo::CreateFrame(Image* image,
FunctionInstance* functionInstance, CpuState* cpuState,
@@ -5,6 +5,7 @@
#ifndef DEBUGGER_IMAGE_DEBUG_INFO_H
#define DEBUGGER_IMAGE_DEBUG_INFO_H
#include "ImageInfo.h"
#include "SpecificImageDebugInfo.h"
@@ -26,6 +27,8 @@ public:
virtual status_t GetFunctions(
BObjectList<FunctionDebugInfo>& functions);
virtual status_t GetType(GlobalTypeLookupContext* context,
const BString& name, Type*& _type);
virtual status_t CreateFrame(Image* image,
FunctionInstance* functionInstance,
CpuState* cpuState,
@@ -33,6 +33,7 @@
#include "FileSourceCode.h"
#include "FunctionID.h"
#include "FunctionInstance.h"
#include "GlobalTypeLookup.h"
#include "LocatableFile.h"
#include "Register.h"
#include "RegisterMap.h"
@@ -47,32 +48,26 @@
#include "Variable.h"
// #pragma mark - UnwindTargetInterface
// #pragma mark - BasicTargetInterface
struct DwarfImageDebugInfo::UnwindTargetInterface : DwarfTargetInterface {
UnwindTargetInterface(const Register* registers, int32 registerCount,
RegisterMap* fromDwarfMap, RegisterMap* toDwarfMap, CpuState* cpuState,
Architecture* architecture, TeamMemory* teamMemory)
struct DwarfImageDebugInfo::BasicTargetInterface : DwarfTargetInterface {
BasicTargetInterface(const Register* registers, int32 registerCount,
RegisterMap* fromDwarfMap, Architecture* architecture,
TeamMemory* teamMemory)
:
fRegisters(registers),
fRegisterCount(registerCount),
fFromDwarfMap(fromDwarfMap),
fToDwarfMap(toDwarfMap),
fCpuState(cpuState),
fArchitecture(architecture),
fTeamMemory(teamMemory)
{
fFromDwarfMap->AcquireReference();
fToDwarfMap->AcquireReference();
fCpuState->AcquireReference();
}
~UnwindTargetInterface()
~BasicTargetInterface()
{
fFromDwarfMap->ReleaseReference();
fToDwarfMap->ReleaseReference();
fCpuState->ReleaseReference();
}
virtual uint32 CountRegisters() const
@@ -88,18 +83,12 @@ struct DwarfImageDebugInfo::UnwindTargetInterface : DwarfTargetInterface {
virtual bool GetRegisterValue(uint32 index, BVariant& _value) const
{
const Register* reg = _RegisterAt(index);
if (reg == NULL)
return false;
return fCpuState->GetRegisterValue(reg, _value);
return false;
}
virtual bool SetRegisterValue(uint32 index, const BVariant& value)
{
const Register* reg = _RegisterAt(index);
if (reg == NULL)
return false;
return fCpuState->SetRegisterValue(reg, value);
return false;
}
virtual bool IsCalleePreservedRegister(uint32 index) const
@@ -129,24 +118,67 @@ struct DwarfImageDebugInfo::UnwindTargetInterface : DwarfTargetInterface {
valueType, _value) == B_OK;
}
private:
protected:
const Register* _RegisterAt(uint32 dwarfIndex) const
{
int32 index = fFromDwarfMap->MapRegisterIndex(dwarfIndex);
return index >= 0 && index < fRegisterCount ? fRegisters + index : NULL;
}
private:
protected:
const Register* fRegisters;
int32 fRegisterCount;
RegisterMap* fFromDwarfMap;
RegisterMap* fToDwarfMap;
CpuState* fCpuState;
Architecture* fArchitecture;
TeamMemory* fTeamMemory;
};
// #pragma mark - UnwindTargetInterface
struct DwarfImageDebugInfo::UnwindTargetInterface : BasicTargetInterface {
UnwindTargetInterface(const Register* registers, int32 registerCount,
RegisterMap* fromDwarfMap, RegisterMap* toDwarfMap, CpuState* cpuState,
Architecture* architecture, TeamMemory* teamMemory)
:
BasicTargetInterface(registers, registerCount, fromDwarfMap,
architecture, teamMemory),
fToDwarfMap(toDwarfMap),
fCpuState(cpuState)
{
fToDwarfMap->AcquireReference();
fCpuState->AcquireReference();
}
~UnwindTargetInterface()
{
fToDwarfMap->ReleaseReference();
fCpuState->ReleaseReference();
}
virtual bool GetRegisterValue(uint32 index, BVariant& _value) const
{
const Register* reg = _RegisterAt(index);
if (reg == NULL)
return false;
return fCpuState->GetRegisterValue(reg, _value);
}
virtual bool SetRegisterValue(uint32 index, const BVariant& value)
{
const Register* reg = _RegisterAt(index);
if (reg == NULL)
return false;
return fCpuState->SetRegisterValue(reg, value);
}
private:
RegisterMap* fToDwarfMap;
CpuState* fCpuState;
};
// #pragma mark - EntryListWrapper
@@ -169,13 +201,14 @@ struct DwarfImageDebugInfo::EntryListWrapper {
DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo,
Architecture* architecture, TeamMemory* teamMemory,
FileManager* fileManager, DwarfFile* file)
FileManager* fileManager, GlobalTypeLookup* typeLookup, DwarfFile* file)
:
fLock("dwarf image debug info"),
fImageInfo(imageInfo),
fArchitecture(architecture),
fTeamMemory(teamMemory),
fFileManager(fileManager),
fTypeLookup(typeLookup),
fFile(file),
fTextSegment(NULL),
fRelocationDelta(0)
@@ -320,6 +353,72 @@ DwarfImageDebugInfo::GetFunctions(BObjectList<FunctionDebugInfo>& functions)
}
status_t
DwarfImageDebugInfo::GetType(GlobalTypeLookupContext* context,
const BString& name, Type*& _type)
{
int32 registerCount = fArchitecture->CountRegisters();
const Register* registers = fArchitecture->Registers();
// get the DWARF -> architecture register map
RegisterMap* fromDwarfMap;
status_t error = fArchitecture->GetDwarfRegisterMaps(NULL, &fromDwarfMap);
if (error != B_OK)
return error;
Reference<RegisterMap> fromDwarfMapReference(fromDwarfMap, true);
// create the target interface
BasicTargetInterface inputInterface(registers, registerCount, fromDwarfMap,
fArchitecture, fTeamMemory);
// iterate through all compilation units
for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i);
i++) {
DwarfStackFrameDebugInfo* stackFrameDebugInfo = NULL;
Reference<DwarfStackFrameDebugInfo> stackFrameDebugInfoReference;
// iterate through all types of the compilation unit
for (DebugInfoEntryList::ConstIterator it
= unit->UnitEntry()->Types().GetIterator();
DIEType* typeEntry = dynamic_cast<DIEType*>(it.Next());) {
if (typeEntry->IsDeclaration())
continue;
BString typeEntryName;
DwarfUtils::GetFullyQualifiedDIEName(typeEntry, typeEntryName);
if (typeEntryName != name)
continue;
// The name matches and the entry is not just a declaration --
// create the type. First create the StackFrameDebugInfo lazily.
if (stackFrameDebugInfo == NULL) {
stackFrameDebugInfo = new(std::nothrow)
DwarfStackFrameDebugInfo(fArchitecture, fFile, unit, NULL,
fTypeLookup, context, 0, 0, &inputInterface, fromDwarfMap);
if (stackFrameDebugInfo == NULL)
return B_NO_MEMORY;
stackFrameDebugInfoReference.SetTo(stackFrameDebugInfo, true);
error = stackFrameDebugInfo->Init();
if (error != B_OK)
return error;
}
// create the type
Type* type;
error = stackFrameDebugInfo->CreateType(typeEntry, type);
if (error != B_OK)
continue;
_type = type;
return B_OK;
}
}
return B_ENTRY_NOT_FOUND;
}
status_t
DwarfImageDebugInfo::CreateFrame(Image* image,
FunctionInstance* functionInstance, CpuState* cpuState,
@@ -393,12 +492,24 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
}
)
// create a type lookup context
GlobalTypeLookupContext* typeLookupContext
= new(std::nothrow) GlobalTypeLookupContext;
if (typeLookupContext == NULL)
return B_NO_MEMORY;
Reference<GlobalTypeLookupContext> typeLookupContextReference(
typeLookupContext, true);
error = typeLookupContext->Init();
if (error != B_OK)
return error;
// create the stack frame debug info
DIESubprogram* subprogramEntry = function->SubprogramEntry();
DwarfStackFrameDebugInfo* stackFrameDebugInfo
= new(std::nothrow) DwarfStackFrameDebugInfo(fArchitecture, fFile, unit,
subprogramEntry, instructionPointer, framePointer, inputInterface,
fromDwarfMap);
subprogramEntry, fTypeLookup, typeLookupContext, instructionPointer,
framePointer, inputInterface, fromDwarfMap);
if (stackFrameDebugInfo == NULL)
return B_NO_MEMORY;
Reference<DwarfStackFrameDebugInfo> stackFrameDebugInfoReference(
@@ -23,6 +23,7 @@ class ElfSegment;
class FileManager;
class FileSourceCode;
class FunctionID;
class GlobalTypeLookup;
class LocatableFile;
class SourceCode;
class TeamMemory;
@@ -33,7 +34,9 @@ public:
DwarfImageDebugInfo(const ImageInfo& imageInfo,
Architecture* architecture,
TeamMemory* teamMemory,
FileManager* fileManager, DwarfFile* file);
FileManager* fileManager,
GlobalTypeLookup* typeLookup,
DwarfFile* file);
virtual ~DwarfImageDebugInfo();
status_t Init();
@@ -43,6 +46,8 @@ public:
virtual status_t GetFunctions(
BObjectList<FunctionDebugInfo>& functions);
virtual status_t GetType(GlobalTypeLookupContext* context,
const BString& name, Type*& _type);
virtual status_t CreateFrame(Image* image,
FunctionInstance* functionInstance,
CpuState* cpuState,
@@ -66,6 +71,7 @@ public:
FileSourceCode* sourceCode);
private:
struct BasicTargetInterface;
struct UnwindTargetInterface;
struct EntryListWrapper;
@@ -90,6 +96,7 @@ private:
Architecture* fArchitecture;
TeamMemory* fTeamMemory;
FileManager* fFileManager;
GlobalTypeLookup* fTypeLookup;
DwarfFile* fFile;
ElfSegment* fTextSegment;
target_addr_t fRelocationDelta;
@@ -9,6 +9,7 @@
#include <algorithm>
#include <new>
#include <AutoLocker.h>
#include <Variant.h>
#include "ArrayIndexPath.h"
@@ -20,6 +21,7 @@
#include "DwarfUtils.h"
#include "FunctionID.h"
#include "FunctionParameterID.h"
#include "GlobalTypeLookup.h"
#include "LocalVariableID.h"
#include "Register.h"
#include "RegisterMap.h"
@@ -304,9 +306,6 @@ public:
private:
BString fName;
target_size_t fByteSize;
public:
DwarfType* fNext;
};
@@ -1127,80 +1126,41 @@ private:
};
// #pragma mark - DwarfTypeHashDefinition
struct DwarfStackFrameDebugInfo::DwarfTypeHashDefinition {
typedef const DIEType* KeyType;
typedef DwarfType ValueType;
size_t HashKey(const DIEType* key) const
{
return (addr_t)key;
}
size_t Hash(const DwarfType* value) const
{
return HashKey(value->GetDIEType());
}
bool Compare(const DIEType* key, const DwarfType* value) const
{
return key == value->GetDIEType();
}
DwarfType*& GetLink(DwarfType* value) const
{
return value->fNext;
}
};
// #pragma mark - DwarfStackFrameDebugInfo
DwarfStackFrameDebugInfo::DwarfStackFrameDebugInfo(Architecture* architecture,
DwarfFile* file, CompilationUnit* compilationUnit,
DIESubprogram* subprogramEntry, target_addr_t instructionPointer,
target_addr_t framePointer, DwarfTargetInterface* targetInterface,
RegisterMap* fromDwarfRegisterMap)
DIESubprogram* subprogramEntry, GlobalTypeLookup* typeLookup,
GlobalTypeLookupContext* typeLookupContext,
target_addr_t instructionPointer, target_addr_t framePointer,
DwarfTargetInterface* targetInterface, RegisterMap* fromDwarfRegisterMap)
:
StackFrameDebugInfo(architecture),
fFile(file),
fCompilationUnit(compilationUnit),
fSubprogramEntry(subprogramEntry),
fTypeLookup(typeLookup),
fTypeLookupContext(typeLookupContext),
fInstructionPointer(instructionPointer),
fFramePointer(framePointer),
fTargetInterface(targetInterface),
fFromDwarfRegisterMap(fromDwarfRegisterMap),
fTypes(NULL)
fFromDwarfRegisterMap(fromDwarfRegisterMap)
{
fTypeLookupContext->AcquireReference();
}
DwarfStackFrameDebugInfo::~DwarfStackFrameDebugInfo()
{
if (fTypes != NULL) {
DwarfType* type = fTypes->Clear(true);
while (type != NULL) {
DwarfType* next = type->fNext;
type->ReleaseReference();
type = next;
}
delete fTypes;
}
fTypeLookupContext->ReleaseReference();
}
status_t
DwarfStackFrameDebugInfo::Init()
{
fTypes = new(std::nothrow) TypeTable;
if (fTypes == NULL)
return B_NO_MEMORY;
return fTypes->Init();
return B_OK;
}
@@ -1468,7 +1428,7 @@ DwarfStackFrameDebugInfo::ResolveArrayElementLocation(StackFrame* stackFrame,
int64 byteOffset = elementOffset >= 0
? elementOffset / 8 : (elementOffset - 7) / 8;
piece.SetToMemory(piece.address + byteOffset);
piece.SetSize(type->BaseType()->ByteSize() * 8);
piece.SetSize(type->BaseType()->ByteSize());
// TODO: Support bit offsets correctly!
// TODO: Support bit fields (primitive types) correctly!
@@ -1647,39 +1607,73 @@ DwarfStackFrameDebugInfo::_ResolveDataMemberLocation(StackFrame* stackFrame,
status_t
DwarfStackFrameDebugInfo::_CreateType(DIEType* typeEntry, DwarfType*& _type)
{
// Try the type cache first. If we don't know the type yet, create it.
DwarfType* type = fTypes->Lookup(typeEntry);
// try the type cache first
BString name;
DwarfUtils::GetFullyQualifiedDIEName(typeEntry, name);
// TODO: The DIE may not have a name (e.g. pointer and reference types don't).
if (type == NULL) {
status_t error = _CreateTypeInternal(typeEntry, type);
if (error != B_OK)
return error;
// Insert the type into the hash table. Recheck, as the type may already
// have been inserted (e.g. in the compound type case).
if (fTypes->Lookup(typeEntry) == NULL)
fTypes->Insert(type);
// try to get the type's size
uint64 size;
if (_ResolveTypeByteSize(typeEntry, size) == B_OK)
type->SetByteSize(size);
AutoLocker<GlobalTypeLookupContext> contextLocker(fTypeLookupContext);
Type* globalType = name.Length() > 0
? fTypeLookupContext->CachedType(name) : NULL;
if (globalType != NULL) {
DwarfType* globalDwarfType = dynamic_cast<DwarfType*>(globalType);
if (globalDwarfType != NULL) {
globalDwarfType->AcquireReference();
_type = globalDwarfType;
return B_OK;
}
}
type->AcquireReference();
_type = type;
contextLocker.Unlock();
// If the type entry indicates a declaration only, we try to look the
// type up globally first.
if (typeEntry->IsDeclaration() && name.Length() > 0
&& fTypeLookup->GetType(fTypeLookupContext, name, globalType)
== B_OK) {
DwarfType* globalDwarfType
= dynamic_cast<DwarfType*>(globalType);
if (globalDwarfType != NULL) {
_type = globalDwarfType;
return B_OK;
}
globalType->ReleaseReference();
}
// No luck yet -- create the type.
DwarfType* type;
status_t error = _CreateTypeInternal(name, typeEntry, type);
if (error != B_OK)
return error;
Reference<DwarfType> typeReference(type, true);
// Insert the type into the cache. Re-check, as the type may already
// have been inserted (e.g. in the compound type case).
if (name.Length() > 0) {
contextLocker.Lock();
if (fTypeLookupContext->CachedType(name) == NULL) {
error = fTypeLookupContext->AddCachedType(name, type);
if (error != B_OK)
return error;
}
contextLocker.Unlock();
}
// try to get the type's size
uint64 size;
if (_ResolveTypeByteSize(typeEntry, size) == B_OK)
type->SetByteSize(size);
_type = typeReference.Detach();
return B_OK;
}
status_t
DwarfStackFrameDebugInfo::_CreateTypeInternal(DIEType* typeEntry,
DwarfType*& _type)
DwarfStackFrameDebugInfo::_CreateTypeInternal(const BString& name,
DIEType* typeEntry, DwarfType*& _type)
{
BString name;
DwarfUtils::GetFullyQualifiedDIEName(typeEntry, name);
// TODO: The DIE may not have a name (e.g. pointer and reference types don't).
switch (typeEntry->Tag()) {
case DW_TAG_class_type:
case DW_TAG_structure_type:
@@ -1775,10 +1769,17 @@ DwarfStackFrameDebugInfo::_CreateCompoundType(const BString& name,
return B_NO_MEMORY;
Reference<DwarfCompoundType> typeReference(type, true);
// Already add the type at this pointer to the hash table, since otherwise
// Already add the type at this pointer to the cache, since otherwise
// we could run into an infinite recursion when trying to create the types
// for the data members.
fTypes->Insert(type);
// TODO: Since access to the type lookup context is multi-threaded, the
// incomplete type could become visible to other threads. Hence we keep the
// context locked, but that essentially kills multi-threading for this context.
AutoLocker<GlobalTypeLookupContext> contextLocker(fTypeLookupContext);
status_t error = fTypeLookupContext->AddCachedType(name, type);
if (error != B_OK)
return error;
// contextLocker.Unlock();
// find the abstract origin or specification that defines the data members
DIECompoundType* memberOwnerEntry = DwarfUtils::GetDIEByPredicate(typeEntry,
@@ -1808,7 +1809,8 @@ DwarfStackFrameDebugInfo::_CreateCompoundType(const BString& name,
memberEntry, memberName, memberType);
Reference<DwarfDataMember> memberReference(member, true);
if (member == NULL || !type->AddDataMember(member)) {
fTypes->Remove(type);
contextLocker.Lock();
fTypeLookupContext->RemoveCachedType(name);
return B_NO_MEMORY;
}
}
@@ -1842,7 +1844,8 @@ DwarfStackFrameDebugInfo::_CreateCompoundType(const BString& name,
Reference<DwarfInheritance> inheritanceReference(inheritance,
true);
if (inheritance == NULL || !type->AddInheritance(inheritance)) {
fTypes->Remove(type);
contextLocker.Lock();
fTypeLookupContext->RemoveCachedType(name);
return B_NO_MEMORY;
}
}
@@ -8,8 +8,6 @@
#include <String.h>
#include <util/OpenHashTable.h>
#include "StackFrameDebugInfo.h"
#include "Type.h"
@@ -33,6 +31,8 @@ class DIEVariable;
class DwarfFile;
class DwarfTargetInterface;
class FunctionID;
class GlobalTypeLookup;
class GlobalTypeLookupContext;
class LocationDescription;
class MemberLocation;
class ObjectID;
@@ -46,6 +46,8 @@ public:
Architecture* architecture, DwarfFile* file,
CompilationUnit* compilationUnit,
DIESubprogram* subprogramEntry,
GlobalTypeLookup* typeLookup,
GlobalTypeLookupContext* typeLookupContext,
target_addr_t instructionPointer,
target_addr_t framePointer,
DwarfTargetInterface* targetInterface,
@@ -105,9 +107,6 @@ private:
struct DwarfUnspecifiedType;
struct DwarfFunctionType;
struct DwarfPointerToMemberType;
struct DwarfTypeHashDefinition;
typedef BOpenHashTable<DwarfTypeHashDefinition> TypeTable;
private:
status_t _ResolveDataMemberLocation(
@@ -121,8 +120,8 @@ private:
status_t _CreateType(DIEType* typeEntry,
DwarfType*& _type);
status_t _CreateTypeInternal(DIEType* typeEntry,
DwarfType*& _type);
status_t _CreateTypeInternal(const BString& name,
DIEType* typeEntry, DwarfType*& _type);
status_t _CreateCompoundType(const BString& name,
DIECompoundType* typeEntry,
@@ -180,11 +179,12 @@ private:
DwarfFile* fFile;
CompilationUnit* fCompilationUnit;
DIESubprogram* fSubprogramEntry;
GlobalTypeLookup* fTypeLookup;
GlobalTypeLookupContext* fTypeLookupContext;
target_addr_t fInstructionPointer;
target_addr_t fFramePointer;
DwarfTargetInterface* fTargetInterface;
RegisterMap* fFromDwarfRegisterMap;
TypeTable* fTypes;
};
@@ -15,12 +15,14 @@
DwarfTeamDebugInfo::DwarfTeamDebugInfo(Architecture* architecture,
TeamMemory* teamMemory, FileManager* fileManager)
TeamMemory* teamMemory, FileManager* fileManager,
GlobalTypeLookup* typeLookup)
:
fArchitecture(architecture),
fTeamMemory(teamMemory),
fFileManager(fileManager),
fManager(NULL)
fManager(NULL),
fTypeLookup(typeLookup)
{
}
@@ -64,17 +66,17 @@ DwarfTeamDebugInfo::CreateImageDebugInfo(const ImageInfo& imageInfo,
return error;
// create the image debug info
DwarfImageDebugInfo* debuggerInfo = new(std::nothrow) DwarfImageDebugInfo(
imageInfo, fArchitecture, fTeamMemory, fFileManager, file);
if (debuggerInfo == NULL)
DwarfImageDebugInfo* debugInfo = new(std::nothrow) DwarfImageDebugInfo(
imageInfo, fArchitecture, fTeamMemory, fFileManager, fTypeLookup, file);
if (debugInfo == NULL)
return B_NO_MEMORY;
error = debuggerInfo->Init();
error = debugInfo->Init();
if (error != B_OK) {
delete debuggerInfo;
delete debugInfo;
return error;
}
_imageDebugInfo = debuggerInfo;
_imageDebugInfo = debugInfo;
return B_OK;
}
@@ -12,6 +12,7 @@ class Architecture;
class DwarfManager;
class FileManager;
class ImageInfo;
class GlobalTypeLookup;
class TeamMemory;
@@ -19,7 +20,8 @@ class DwarfTeamDebugInfo : public SpecificTeamDebugInfo {
public:
DwarfTeamDebugInfo(Architecture* architecture,
TeamMemory* teamMemory,
FileManager* fileManager);
FileManager* fileManager,
GlobalTypeLookup* typeLookup);
virtual ~DwarfTeamDebugInfo();
status_t Init();
@@ -33,6 +35,7 @@ private:
TeamMemory* fTeamMemory;
FileManager* fFileManager;
DwarfManager* fManager;
GlobalTypeLookup* fTypeLookup;
};
@@ -0,0 +1,142 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "GlobalTypeLookup.h"
#include <new>
#include <String.h>
#include "StringUtils.h"
#include "Type.h"
struct GlobalTypeLookupContext::TypeEntry {
BString name;
Type* type;
TypeEntry* fNext;
TypeEntry(const BString& name, Type* type)
:
name(name),
type(type)
{
type->AcquireReference();
}
~TypeEntry()
{
type->ReleaseReference();
}
};
struct GlobalTypeLookupContext::TypeEntryHashDefinition {
typedef const BString KeyType;
typedef TypeEntry ValueType;
size_t HashKey(const BString& key) const
{
return StringUtils::HashValue(key);
}
size_t Hash(const TypeEntry* value) const
{
return HashKey(value->name);
}
bool Compare(const BString& key, const TypeEntry* value) const
{
return key == value->name;
}
TypeEntry*& GetLink(TypeEntry* value) const
{
return value->fNext;
}
};
// #pragma mark - GlobalTypeLookupContext
GlobalTypeLookupContext::GlobalTypeLookupContext()
:
fLock("global type lookup"),
fCachedTypes(NULL)
{
}
GlobalTypeLookupContext::~GlobalTypeLookupContext()
{
// release all cached type references
if (fCachedTypes != NULL) {
TypeEntry* entry = fCachedTypes->Clear(true);
while (entry != NULL) {
TypeEntry* nextEntry = entry->fNext;
delete entry;
entry = nextEntry;
}
}
}
status_t
GlobalTypeLookupContext::Init()
{
status_t error = fLock.InitCheck();
if (error != B_OK)
return error;
fCachedTypes = new(std::nothrow) TypeTable;
if (fCachedTypes == NULL)
return B_NO_MEMORY;
return fCachedTypes->Init();
}
Type*
GlobalTypeLookupContext::CachedType(const BString& name) const
{
TypeEntry* typeEntry = fCachedTypes->Lookup(name);
return typeEntry != NULL ? typeEntry->type : NULL;
}
status_t
GlobalTypeLookupContext::AddCachedType(const BString& name, Type* type)
{
TypeEntry* typeEntry = fCachedTypes->Lookup(name);
if (typeEntry != NULL)
return B_BAD_VALUE;
typeEntry = new(std::nothrow) TypeEntry(name, type);
if (typeEntry == NULL)
return B_NO_MEMORY;
fCachedTypes->Insert(typeEntry);
return B_OK;
}
void
GlobalTypeLookupContext::RemoveCachedType(const BString& name)
{
if (TypeEntry* typeEntry = fCachedTypes->Lookup(name)) {
fCachedTypes->Remove(typeEntry);
delete typeEntry;
}
}
// #pragma mark - GlobalTypeLookup
GlobalTypeLookup::~GlobalTypeLookup()
{
}
@@ -0,0 +1,70 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef GLOBAL_TYPE_LOOKUP_H
#define GLOBAL_TYPE_LOOKUP_H
#include <Locker.h>
#include <Referenceable.h>
#include <util/OpenHashTable.h>
class BString;
class Type;
class GlobalTypeLookupContext : public Referenceable {
public:
GlobalTypeLookupContext();
~GlobalTypeLookupContext();
status_t Init();
inline bool Lock();
inline void Unlock();
// context must be locked
Type* CachedType(const BString& name) const;
status_t AddCachedType(const BString& name, Type* type);
void RemoveCachedType(const BString& name);
private:
struct TypeEntry;
struct TypeEntryHashDefinition;
typedef BOpenHashTable<TypeEntryHashDefinition> TypeTable;
private:
BLocker fLock;
TypeTable* fCachedTypes;
};
class GlobalTypeLookup {
public:
~GlobalTypeLookup();
virtual status_t GetType(GlobalTypeLookupContext* context,
const BString& name, Type*& _type) = 0;
// returns a reference
};
bool
GlobalTypeLookupContext::Lock()
{
return fLock.Lock();
}
void
GlobalTypeLookupContext::Unlock()
{
fLock.Unlock();
}
#endif // GLOBAL_TYPE_LOOKUP_H
@@ -75,6 +75,21 @@ ImageDebugInfo::FinishInit()
}
status_t
ImageDebugInfo::GetType(GlobalTypeLookupContext* context, const BString& name,
Type*& _type)
{
for (int32 i = 0; SpecificImageDebugInfo* specificInfo
= fSpecificInfos.ItemAt(i); i++) {
status_t error = specificInfo->GetType(context, name, _type);
if (error == B_OK || error == B_NO_MEMORY)
return error;
}
return B_ENTRY_NOT_FOUND;
}
int32
ImageDebugInfo::CountFunctions() const
{
@@ -5,6 +5,7 @@
#ifndef IMAGE_DEBUG_INFO_H
#define IMAGE_DEBUG_INFO_H
#include <String.h>
#include <ObjectList.h>
@@ -19,8 +20,10 @@ class DebuggerInterface;
class FileSourceCode;
class FunctionDebugInfo;
class FunctionInstance;
class GlobalTypeLookupContext;
class LocatableFile;
class SpecificImageDebugInfo;
class Type;
class ImageDebugInfo : public Referenceable {
@@ -33,6 +36,10 @@ public:
bool AddSpecificInfo(SpecificImageDebugInfo* info);
status_t FinishInit();
status_t GetType(GlobalTypeLookupContext* context,
const BString& name, Type*& _type);
// returns a reference
int32 CountFunctions() const;
FunctionInstance* FunctionAt(int32 index) const;
FunctionInstance* FunctionAtAddress(target_addr_t address) const;
@@ -5,6 +5,7 @@
#ifndef SPECIFIC_IMAGE_DEBUG_INFO_H
#define SPECIFIC_IMAGE_DEBUG_INFO_H
#include <ObjectList.h>
#include <Referenceable.h>
@@ -12,12 +13,14 @@
class Architecture;
class BString;
class CpuState;
class DataMember;
class DebuggerInterface;
class FileSourceCode;
class FunctionDebugInfo;
class FunctionInstance;
class GlobalTypeLookupContext;
class Image;
class LocatableFile;
class SourceLanguage;
@@ -37,6 +40,10 @@ public:
= 0;
// returns references
virtual status_t GetType(GlobalTypeLookupContext* context,
const BString& name, Type*& _type) = 0;
// returns a reference
virtual status_t CreateFrame(Image* image,
FunctionInstance* functionInstance,
CpuState* cpuState,
+47 -1
View File
@@ -28,6 +28,7 @@
#include "SourceLanguage.h"
#include "SpecificImageDebugInfo.h"
#include "StringUtils.h"
#include "Type.h"
// #pragma mark - FunctionHashDefinition
@@ -319,7 +320,7 @@ TeamDebugInfo::Init()
// DWARF
DwarfTeamDebugInfo* dwarfInfo = new(std::nothrow) DwarfTeamDebugInfo(
fArchitecture, fDebuggerInterface, fFileManager);
fArchitecture, fDebuggerInterface, fFileManager, this);
if (dwarfInfo == NULL || !fSpecificInfos.AddItem(dwarfInfo)) {
delete dwarfInfo;
return B_NO_MEMORY;
@@ -346,6 +347,51 @@ TeamDebugInfo::Init()
}
status_t
TeamDebugInfo::GetType(GlobalTypeLookupContext* context, const BString& name,
Type*& _type)
{
// maybe the type is already cached
AutoLocker<GlobalTypeLookupContext> contextLocker(context);
Type* type = context->CachedType(name);
if (type != NULL) {
type->AcquireReference();
_type = type;
return B_OK;
}
contextLocker.Unlock();
// Clone the image list and get references to the images, so we can iterate
// through them without locking.
AutoLocker<BLocker> locker(fLock);
ImageList images;
for (int32 i = 0; ImageDebugInfo* imageDebugInfo = fImages.ItemAt(i); i++) {
if (images.AddItem(imageDebugInfo))
imageDebugInfo->AcquireReference();
}
locker.Unlock();
// get the type
status_t error = B_ENTRY_NOT_FOUND;
for (int32 i = 0; ImageDebugInfo* imageDebugInfo = images.ItemAt(i); i++) {
error = imageDebugInfo->GetType(context, name, type);
if (error == B_OK) {
_type = type;
break;
}
}
// release the references
for (int32 i = 0; ImageDebugInfo* imageDebugInfo = images.ItemAt(i); i++)
imageDebugInfo->ReleaseReference();
return error;
}
status_t
TeamDebugInfo::LoadImageDebugInfo(const ImageInfo& imageInfo,
LocatableFile* imageFile, ImageDebugInfo*& _imageDebugInfo)
+5 -1
View File
@@ -12,6 +12,7 @@
#include <Referenceable.h>
#include <util/OpenHashTable.h>
#include "GlobalTypeLookup.h"
#include "ImageInfo.h"
@@ -31,7 +32,7 @@ class SourceLocation;
class SpecificTeamDebugInfo;
class TeamDebugInfo : public Referenceable {
class TeamDebugInfo : public Referenceable, public GlobalTypeLookup {
public:
TeamDebugInfo(
DebuggerInterface* debuggerInterface,
@@ -41,6 +42,9 @@ public:
status_t Init();
virtual status_t GetType(GlobalTypeLookupContext* context,
const BString& name, Type*& _type);
status_t LoadImageDebugInfo(const ImageInfo& imageInfo,
LocatableFile* imageFile,
ImageDebugInfo*& _imageDebugInfo);
+7 -3
View File
@@ -61,6 +61,9 @@ public:
virtual bool GetFrameAddress(target_addr_t& _address)
{
if (fFramePointer == 0)
return false;
_address = fFramePointer;
return true;
}
@@ -79,6 +82,8 @@ public:
fFrameBaseEvaluated = true;
// get the subprogram's frame base location
if (fSubprogramEntry == NULL)
return false;
const LocationDescription* location = fSubprogramEntry->FrameBase();
if (!location->IsValid())
return false;
@@ -219,8 +224,7 @@ DwarfFile::Load(const char* fileName)
fDebugLineSection = fElfFile->GetSection(".debug_line");
fDebugFrameSection = fElfFile->GetSection(".debug_frame");
fDebugLocationSection = fElfFile->GetSection(".debug_loc");
// fDebugPublicTypesSection = fElfFile->GetSection(".debug_pubtypes");
fDebugPublicTypesSection = fElfFile->GetSection(".debug_pubnames");
fDebugPublicTypesSection = fElfFile->GetSection(".debug_pubtypes");
// iterate through the debug info section
DataReader dataReader(fDebugInfoSection->Data(),
@@ -1914,7 +1918,7 @@ DwarfFile::_GetLocationExpression(CompilationUnit* unit,
return B_OK;
}
if (location->IsLocationList()) {
if (location->IsLocationList() && instructionPointer != 0) {
return _FindLocationExpression(unit, location->listOffset,
instructionPointer, _expression, _length);
}