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:
Rene Gollent
2014-06-15 10:59:14 -04:00
parent a262768084
commit 7cab832956
13 changed files with 149 additions and 41 deletions
@@ -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;
};
+13 -3
View File
@@ -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,
+43 -14
View 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;
+7 -2
View File
@@ -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;
+35 -10
View File
@@ -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;
}
+6 -2
View File
@@ -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:
+4 -1
View File
@@ -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();