Debugger: Add support for suspending LoadImageDebugInfoJob.
DwarfFile: - Loading is now split into two steps, the first of which simply attempts to verify the presence of debug information. If the latter is referenced externally, but cannot be found on disk, the corresponding file reference is returned. TeamDebugInfo: - Add state parameter to LoadImageDebugInfo(). Use it to preserve where we are in the specific info loading loop if necessary. SpecificTeamDebugInfo: - Add parameter to CreateImageDebugInfo() to allow passing in a state object and adjust implementing subclasses accordingly. DwarfTeamDebugInfo: - Preserve and/or pass down DwarfFile's loading state as needed. DwarfManager: - When attempting to load a DwarfFile, detect the case where external debug information is referenced, but could not be located. If so, preserve the relevant details in the loading state, so the user can be notified and asked to find it accordingly. LoadImageDebugInfoJob: - Keep a state object for the progress of the current loading job. If a particular image fails due to needing user input, suspend ourselves until such input has been provided.
This commit is contained in:
@@ -33,7 +33,8 @@ DebuggerTeamDebugInfo::Init()
|
||||
|
||||
status_t
|
||||
DebuggerTeamDebugInfo::CreateImageDebugInfo(const ImageInfo& imageInfo,
|
||||
LocatableFile* imageFile, SpecificImageDebugInfo*& _imageDebugInfo)
|
||||
LocatableFile* imageFile, ImageDebugInfoLoadingState& _state,
|
||||
SpecificImageDebugInfo*& _imageDebugInfo)
|
||||
{
|
||||
DebuggerImageDebugInfo* debuggerInfo
|
||||
= new(std::nothrow) DebuggerImageDebugInfo(imageInfo,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Copyright 2014, Rene Gollent, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef DEBUGGER_TEAM_DEBUG_INFO_H
|
||||
@@ -24,6 +25,7 @@ public:
|
||||
|
||||
virtual status_t CreateImageDebugInfo(const ImageInfo& imageInfo,
|
||||
LocatableFile* imageFile,
|
||||
ImageDebugInfoLoadingState& _state,
|
||||
SpecificImageDebugInfo*& _imageDebugInfo);
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Copyright 2014, Rene Gollent, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -12,8 +13,10 @@
|
||||
#include "DebuggerInterface.h"
|
||||
#include "DwarfFile.h"
|
||||
#include "DwarfImageDebugInfo.h"
|
||||
#include "DwarfImageDebugInfoLoadingState.h"
|
||||
#include "DwarfManager.h"
|
||||
#include "GlobalTypeLookup.h"
|
||||
#include "ImageDebugInfoLoadingState.h"
|
||||
#include "LocatableFile.h"
|
||||
|
||||
|
||||
@@ -58,7 +61,8 @@ DwarfTeamDebugInfo::Init()
|
||||
|
||||
status_t
|
||||
DwarfTeamDebugInfo::CreateImageDebugInfo(const ImageInfo& imageInfo,
|
||||
LocatableFile* imageFile, SpecificImageDebugInfo*& _imageDebugInfo)
|
||||
LocatableFile* imageFile, ImageDebugInfoLoadingState& _state,
|
||||
SpecificImageDebugInfo*& _imageDebugInfo)
|
||||
{
|
||||
// We only like images whose file we can play with.
|
||||
BString filePath;
|
||||
@@ -66,11 +70,22 @@ DwarfTeamDebugInfo::CreateImageDebugInfo(const ImageInfo& imageInfo,
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
// try to load the DWARF file
|
||||
DwarfFile* file;
|
||||
status_t error = fManager->LoadFile(filePath, file);
|
||||
DwarfImageDebugInfoLoadingState* dwarfState;
|
||||
if (_state.HasSpecificDebugInfoLoadingState()) {
|
||||
dwarfState = dynamic_cast<DwarfImageDebugInfoLoadingState*>(
|
||||
_state.GetSpecificDebugInfoLoadingState());
|
||||
if (dwarfState == NULL)
|
||||
return B_BAD_VALUE;
|
||||
} else {
|
||||
dwarfState = new(std::nothrow) DwarfImageDebugInfoLoadingState();
|
||||
if (dwarfState == NULL)
|
||||
return B_NO_MEMORY;
|
||||
_state.SetSpecificDebugInfoLoadingState(dwarfState);
|
||||
}
|
||||
|
||||
status_t error = fManager->LoadFile(filePath, dwarfState->GetFileState());
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
BReference<DwarfFile> fileReference(file, true);
|
||||
|
||||
error = fManager->FinishLoading();
|
||||
if (error != B_OK)
|
||||
@@ -79,7 +94,7 @@ DwarfTeamDebugInfo::CreateImageDebugInfo(const ImageInfo& imageInfo,
|
||||
// create the image debug info
|
||||
DwarfImageDebugInfo* debugInfo = new(std::nothrow) DwarfImageDebugInfo(
|
||||
imageInfo, fDebuggerInterface, fArchitecture, fFileManager,
|
||||
fTypeLookup, fTypeCache, file);
|
||||
fTypeLookup, fTypeCache, dwarfState->GetFileState().dwarfFile);
|
||||
if (debugInfo == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Copyright 2014, Rene Gollent, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef DWARF_TEAM_DEBUG_INFO_H
|
||||
@@ -31,6 +32,7 @@ public:
|
||||
|
||||
virtual status_t CreateImageDebugInfo(const ImageInfo& imageInfo,
|
||||
LocatableFile* imageFile,
|
||||
ImageDebugInfoLoadingState& _state,
|
||||
SpecificImageDebugInfo*& _imageDebugInfo);
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Copyright 2014, Rene Gollent, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef SPECIFIC_TEAM_DEBUG_INFO_H
|
||||
@@ -8,17 +9,18 @@
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
class ImageDebugInfoLoadingState;
|
||||
class ImageInfo;
|
||||
class LocatableFile;
|
||||
class SpecificImageDebugInfo;
|
||||
|
||||
|
||||
class SpecificTeamDebugInfo {
|
||||
public:
|
||||
virtual ~SpecificTeamDebugInfo();
|
||||
|
||||
virtual status_t CreateImageDebugInfo(const ImageInfo& imageInfo,
|
||||
LocatableFile* imageFile,
|
||||
ImageDebugInfoLoadingState& _state,
|
||||
SpecificImageDebugInfo*& _imageDebugInfo)
|
||||
= 0;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Copyright 2012-2013, Rene Gollent, [email protected].
|
||||
* Copyright 2012-2014, Rene Gollent, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "Function.h"
|
||||
#include "FunctionID.h"
|
||||
#include "ImageDebugInfo.h"
|
||||
#include "ImageDebugInfoLoadingState.h"
|
||||
#include "LocatableFile.h"
|
||||
#include "SourceFile.h"
|
||||
#include "SourceLanguage.h"
|
||||
@@ -426,7 +427,8 @@ TeamDebugInfo::GetType(GlobalTypeCache* cache, const BString& name,
|
||||
|
||||
status_t
|
||||
TeamDebugInfo::LoadImageDebugInfo(const ImageInfo& imageInfo,
|
||||
LocatableFile* imageFile, ImageDebugInfo*& _imageDebugInfo)
|
||||
LocatableFile* imageFile, ImageDebugInfoLoadingState& _state,
|
||||
ImageDebugInfo*& _imageDebugInfo)
|
||||
{
|
||||
ImageDebugInfo* imageDebugInfo = new(std::nothrow) ImageDebugInfo(
|
||||
imageInfo);
|
||||
@@ -438,15 +440,23 @@ TeamDebugInfo::LoadImageDebugInfo(const ImageInfo& imageInfo,
|
||||
= fSpecificInfos.ItemAt(i); i++) {
|
||||
SpecificImageDebugInfo* specificImageInfo;
|
||||
status_t error = specificTeamInfo->CreateImageDebugInfo(imageInfo,
|
||||
imageFile, specificImageInfo);
|
||||
imageFile, _state, specificImageInfo);
|
||||
if (error == B_OK) {
|
||||
if (!imageDebugInfo->AddSpecificInfo(specificImageInfo)) {
|
||||
delete specificImageInfo;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
} else if (_state.UserInputRequired()) {
|
||||
_state.SetSpecificInfoIndex(i);
|
||||
return error;
|
||||
} else if (error == B_NO_MEMORY)
|
||||
return error;
|
||||
// fail only when out of memory
|
||||
|
||||
_state.ClearSpecificDebugInfoLoadingState();
|
||||
// if we made it this far, then we're done with current specific
|
||||
// info, and its corresponding state object, if any, is no longer
|
||||
// needed
|
||||
}
|
||||
|
||||
status_t error = imageDebugInfo->FinishInit(fDebuggerInterface);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Copyright 2014, Rene Gollent, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TEAM_DEBUG_INFO_H
|
||||
@@ -26,6 +27,7 @@ class Function;
|
||||
class FunctionID;
|
||||
class FunctionInstance;
|
||||
class ImageDebugInfo;
|
||||
class ImageDebugInfoLoadingState;
|
||||
class ImageInfo;
|
||||
class LocatableFile;
|
||||
class SourceCode;
|
||||
@@ -54,6 +56,7 @@ public:
|
||||
|
||||
status_t LoadImageDebugInfo(const ImageInfo& imageInfo,
|
||||
LocatableFile* imageFile,
|
||||
ImageDebugInfoLoadingState& state,
|
||||
ImageDebugInfo*& _imageDebugInfo);
|
||||
|
||||
status_t LoadSourceCode(LocatableFile* file,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009-2012, Ingo Weinhold, [email protected].
|
||||
* Copyright 2012-2013, Rene Gollent, [email protected].
|
||||
* Copyright 2012-2014, Rene Gollent, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -504,7 +504,7 @@ DwarfFile::~DwarfFile()
|
||||
|
||||
|
||||
status_t
|
||||
DwarfFile::Load(const char* fileName)
|
||||
DwarfFile::StartLoading(const char* fileName, BString& _requiredExternalFile)
|
||||
{
|
||||
fName = strdup(fileName);
|
||||
if (fName == NULL)
|
||||
@@ -523,9 +523,21 @@ DwarfFile::Load(const char* fileName)
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
error = _LocateDebugInfo();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
return _LocateDebugInfo(_requiredExternalFile);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DwarfFile::Load(const BString& externalInfoFilePath)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
if (fDebugInfoSection == NULL) {
|
||||
BString path;
|
||||
error = _LocateDebugInfo(path, externalInfoFilePath.IsEmpty()
|
||||
? NULL : externalInfoFilePath.String());
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
}
|
||||
|
||||
ElfFile* debugInfoFile = fAlternateElfFile != NULL
|
||||
? fAlternateElfFile : fElfFile;
|
||||
@@ -2686,7 +2698,8 @@ DwarfFile::_FindLocationExpression(CompilationUnit* unit, uint64 offset,
|
||||
|
||||
|
||||
status_t
|
||||
DwarfFile::_LocateDebugInfo()
|
||||
DwarfFile::_LocateDebugInfo(BString& _requiredExternalFileName,
|
||||
const char* locatedFilePath)
|
||||
{
|
||||
ElfFile* debugInfoFile = fElfFile;
|
||||
ElfSection* debugLinkSection = fElfFile->GetSection(".gnu_debuglink");
|
||||
@@ -2700,10 +2713,19 @@ DwarfFile::_LocateDebugInfo()
|
||||
// by a 32-bit CRC
|
||||
|
||||
BString debugPath;
|
||||
status_t result = _GetDebugInfoPath(
|
||||
(const char*)debugLinkSection->Data(), debugPath);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
if (locatedFilePath)
|
||||
debugPath = locatedFilePath;
|
||||
else {
|
||||
status_t result = _GetDebugInfoPath(
|
||||
(const char*)debugLinkSection->Data(),
|
||||
_requiredExternalFileName);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
debugPath = _requiredExternalFileName;
|
||||
}
|
||||
|
||||
if (fAlternateName != NULL)
|
||||
free(fAlternateName);
|
||||
|
||||
fAlternateName = strdup(debugPath.String());
|
||||
|
||||
@@ -2715,11 +2737,13 @@ DwarfFile::_LocateDebugInfo()
|
||||
int32 debugCRC = *(int32*)((char*)debugLinkSection->Data()
|
||||
+ debugLinkSection->Size() - sizeof(int32));
|
||||
*/
|
||||
fAlternateElfFile = new(std::nothrow) ElfFile;
|
||||
if (fAlternateElfFile == NULL)
|
||||
return B_NO_MEMORY;
|
||||
if (fAlternateElfFile == NULL) {
|
||||
fAlternateElfFile = new(std::nothrow) ElfFile;
|
||||
if (fAlternateElfFile == NULL)
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
result = fAlternateElfFile->Init(fAlternateName);
|
||||
status_t result = fAlternateElfFile->Init(fAlternateName);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
@@ -2780,6 +2804,11 @@ DwarfFile::_GetDebugInfoPath(const char* debugFileName,
|
||||
if (result == B_OK) {
|
||||
_infoPath = basePath.Path();
|
||||
return B_OK;
|
||||
} else {
|
||||
// if we failed to find a match, then it's up to the user to
|
||||
// locate it. As such, return the external info file name
|
||||
// for user interface purposes.
|
||||
_infoPath.SetTo(debugFileName);
|
||||
}
|
||||
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
@@ -35,7 +35,9 @@ public:
|
||||
DwarfFile();
|
||||
~DwarfFile();
|
||||
|
||||
status_t Load(const char* fileName);
|
||||
status_t StartLoading(const char* fileName,
|
||||
BString& _requiredExternalFile);
|
||||
status_t Load(const BString& externalFilePath);
|
||||
status_t FinishLoading();
|
||||
|
||||
const char* Name() const { return fName; }
|
||||
@@ -172,7 +174,10 @@ private:
|
||||
const void*& _expression,
|
||||
off_t& _length) const;
|
||||
|
||||
status_t _LocateDebugInfo();
|
||||
status_t _LocateDebugInfo(
|
||||
BString& _requiredExternalFileName,
|
||||
const char* locatedFilePath = NULL);
|
||||
|
||||
status_t _GetDebugInfoPath(const char* fileName,
|
||||
BString& _infoPath) const;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2014, Rene Gollent, rene@gollent.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -11,6 +12,7 @@
|
||||
#include <AutoLocker.h>
|
||||
|
||||
#include "DwarfFile.h"
|
||||
#include "DwarfFileLoadingState.h"
|
||||
|
||||
|
||||
DwarfManager::DwarfManager()
|
||||
@@ -33,26 +35,49 @@ DwarfManager::Init()
|
||||
|
||||
|
||||
status_t
|
||||
DwarfManager::LoadFile(const char* fileName, DwarfFile*& _file)
|
||||
DwarfManager::LoadFile(const char* fileName, DwarfFileLoadingState& _state)
|
||||
{
|
||||
AutoLocker<DwarfManager> locker(this);
|
||||
|
||||
DwarfFile* file = new(std::nothrow) DwarfFile;
|
||||
if (file == NULL)
|
||||
return B_NO_MEMORY;
|
||||
DwarfFile* file = _state.dwarfFile;
|
||||
BReference<DwarfFile> fileReference;
|
||||
if (file == NULL) {
|
||||
file = new(std::nothrow) DwarfFile;
|
||||
if (file == NULL)
|
||||
return B_NO_MEMORY;
|
||||
fileReference.SetTo(file, true);
|
||||
_state.dwarfFile = file;
|
||||
} else
|
||||
fileReference.SetTo(file);
|
||||
|
||||
BReference<DwarfFile> fileReference(file, true);
|
||||
status_t error = file->Load(fileName);
|
||||
status_t error;
|
||||
if (_state.externalInfoFileName.IsEmpty()) {
|
||||
error = file->StartLoading(fileName, _state.externalInfoFileName);
|
||||
if (error != B_OK) {
|
||||
// only preserve state in the failure case if an external
|
||||
// debug information reference was found, but the corresponding
|
||||
// file could not be located on disk.
|
||||
_state.state = _state.externalInfoFileName.IsEmpty()
|
||||
? DWARF_FILE_LOADING_STATE_FAILED
|
||||
: DWARF_FILE_LOADING_STATE_USER_INPUT_NEEDED;
|
||||
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
error = file->Load(_state.locatedExternalInfoPath);
|
||||
if (error != B_OK) {
|
||||
_state.state = DWARF_FILE_LOADING_STATE_FAILED;
|
||||
return error;
|
||||
}
|
||||
|
||||
fFiles.Add(file);
|
||||
fileReference.Detach();
|
||||
// we keep the initial reference for ourselves
|
||||
|
||||
file->AcquireReference();
|
||||
_file = file;
|
||||
fileReference.Detach();
|
||||
// keep a reference for ourselves in the list.
|
||||
|
||||
_state.state = DWARF_FILE_LOADING_STATE_SUCCEEDED;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2014, Rene Gollent, rene@gollent.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef DWARF_MANAGER_H
|
||||
@@ -11,6 +12,7 @@
|
||||
|
||||
|
||||
class DwarfFile;
|
||||
struct DwarfFileLoadingState;
|
||||
|
||||
|
||||
class DwarfManager {
|
||||
@@ -24,8 +26,10 @@ public:
|
||||
void Unlock() { fLock.Unlock(); }
|
||||
|
||||
status_t LoadFile(const char* fileName,
|
||||
DwarfFile*& _file);
|
||||
// returns a reference
|
||||
DwarfFileLoadingState& _loadingState);
|
||||
// _loadingState receives a reference
|
||||
// to the corresponding DwarfFile.
|
||||
|
||||
status_t FinishLoading();
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2011, Rene Gollent, rene@gollent.com.
|
||||
* Copyright 2011-2014, Rene Gollent, rene@gollent.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef JOBS_H
|
||||
#define JOBS_H
|
||||
|
||||
|
||||
#include "ImageDebugInfoLoadingState.h"
|
||||
#include "ImageDebugInfoProvider.h"
|
||||
#include "Types.h"
|
||||
#include "Worker.h"
|
||||
@@ -128,6 +129,8 @@ public:
|
||||
private:
|
||||
SimpleJobKey fKey;
|
||||
Image* fImage;
|
||||
ImageDebugInfoLoadingState
|
||||
fState;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
LoadImageDebugInfoJob::LoadImageDebugInfoJob(Image* image)
|
||||
:
|
||||
fKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO),
|
||||
fImage(image)
|
||||
fImage(image),
|
||||
fState()
|
||||
{
|
||||
fImage->AcquireReference();
|
||||
}
|
||||
@@ -47,10 +48,16 @@ LoadImageDebugInfoJob::Do()
|
||||
// create the debug info
|
||||
ImageDebugInfo* debugInfo;
|
||||
status_t error = fImage->GetTeam()->DebugInfo()->LoadImageDebugInfo(
|
||||
imageInfo, fImage->ImageFile(), debugInfo);
|
||||
imageInfo, fImage->ImageFile(), fState, debugInfo);
|
||||
|
||||
// set the result
|
||||
locker.Lock();
|
||||
|
||||
if (fState.UserInputRequired()) {
|
||||
// TODO: notify the user interface
|
||||
return WaitForUserInput();
|
||||
}
|
||||
|
||||
if (error == B_OK) {
|
||||
error = fImage->SetImageDebugInfo(debugInfo, IMAGE_DEBUG_INFO_LOADED);
|
||||
debugInfo->ReleaseReference();
|
||||
|
||||
Reference in New Issue
Block a user