* 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:
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user