diff --git a/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.cpp b/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.cpp index 3c46e5f5df..66195db739 100644 --- a/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.cpp @@ -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, diff --git a/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.h b/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.h index d3895c0c1e..37367540d1 100644 --- a/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.h +++ b/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.h @@ -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 DEBUGGER_TEAM_DEBUG_INFO_H @@ -24,6 +25,7 @@ public: virtual status_t CreateImageDebugInfo(const ImageInfo& imageInfo, LocatableFile* imageFile, + ImageDebugInfoLoadingState& _state, SpecificImageDebugInfo*& _imageDebugInfo); private: diff --git a/src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp index 331f0a3b4b..da04aca4d3 100644 --- a/src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp @@ -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. */ @@ -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( + _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 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; diff --git a/src/apps/debugger/debug_info/DwarfTeamDebugInfo.h b/src/apps/debugger/debug_info/DwarfTeamDebugInfo.h index 90c243417a..fa2891b925 100644 --- a/src/apps/debugger/debug_info/DwarfTeamDebugInfo.h +++ b/src/apps/debugger/debug_info/DwarfTeamDebugInfo.h @@ -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_TEAM_DEBUG_INFO_H @@ -31,6 +32,7 @@ public: virtual status_t CreateImageDebugInfo(const ImageInfo& imageInfo, LocatableFile* imageFile, + ImageDebugInfoLoadingState& _state, SpecificImageDebugInfo*& _imageDebugInfo); private: diff --git a/src/apps/debugger/debug_info/SpecificTeamDebugInfo.h b/src/apps/debugger/debug_info/SpecificTeamDebugInfo.h index 1d3a47d103..f9ac7c6a72 100644 --- a/src/apps/debugger/debug_info/SpecificTeamDebugInfo.h +++ b/src/apps/debugger/debug_info/SpecificTeamDebugInfo.h @@ -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 SPECIFIC_TEAM_DEBUG_INFO_H @@ -8,17 +9,18 @@ #include +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; }; diff --git a/src/apps/debugger/debug_info/TeamDebugInfo.cpp b/src/apps/debugger/debug_info/TeamDebugInfo.cpp index 700caa4d76..00b174e0fa 100644 --- a/src/apps/debugger/debug_info/TeamDebugInfo.cpp +++ b/src/apps/debugger/debug_info/TeamDebugInfo.cpp @@ -1,6 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2012-2013, Rene Gollent, rene@gollent.com. + * Copyright 2012-2014, Rene Gollent, rene@gollent.com. * 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); diff --git a/src/apps/debugger/debug_info/TeamDebugInfo.h b/src/apps/debugger/debug_info/TeamDebugInfo.h index 06b7fe0399..884a1a36c7 100644 --- a/src/apps/debugger/debug_info/TeamDebugInfo.h +++ b/src/apps/debugger/debug_info/TeamDebugInfo.h @@ -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 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, diff --git a/src/apps/debugger/dwarf/DwarfFile.cpp b/src/apps/debugger/dwarf/DwarfFile.cpp index ad2fd47876..fa38af5af1 100644 --- a/src/apps/debugger/dwarf/DwarfFile.cpp +++ b/src/apps/debugger/dwarf/DwarfFile.cpp @@ -1,6 +1,6 @@ /* * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2012-2013, Rene Gollent, rene@gollent.com. + * Copyright 2012-2014, Rene Gollent, rene@gollent.com. * 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; diff --git a/src/apps/debugger/dwarf/DwarfFile.h b/src/apps/debugger/dwarf/DwarfFile.h index 17dee900c8..b778383c80 100644 --- a/src/apps/debugger/dwarf/DwarfFile.h +++ b/src/apps/debugger/dwarf/DwarfFile.h @@ -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; diff --git a/src/apps/debugger/dwarf/DwarfManager.cpp b/src/apps/debugger/dwarf/DwarfManager.cpp index b6fb6bfadb..4f033da0c3 100644 --- a/src/apps/debugger/dwarf/DwarfManager.cpp +++ b/src/apps/debugger/dwarf/DwarfManager.cpp @@ -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 #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 locker(this); - DwarfFile* file = new(std::nothrow) DwarfFile; - if (file == NULL) - return B_NO_MEMORY; + DwarfFile* file = _state.dwarfFile; + BReference 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 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; } diff --git a/src/apps/debugger/dwarf/DwarfManager.h b/src/apps/debugger/dwarf/DwarfManager.h index 8da0755a49..375402fc22 100644 --- a/src/apps/debugger/dwarf/DwarfManager.h +++ b/src/apps/debugger/dwarf/DwarfManager.h @@ -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: diff --git a/src/apps/debugger/jobs/Jobs.h b/src/apps/debugger/jobs/Jobs.h index 1cf7a06925..f024bc38a3 100644 --- a/src/apps/debugger/jobs/Jobs.h +++ b/src/apps/debugger/jobs/Jobs.h @@ -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; }; diff --git a/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp b/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp index dc1706c29f..418873f5eb 100644 --- a/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp +++ b/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp @@ -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();