status_t LoadSourceCodeJob::Do() { // if requested, try loading the source code for the function Function* function = fFunctionInstance->GetFunction(); if (fLoadForFunction) { FileSourceCode* sourceCode; status_t error = fTeam->DebugInfo()->LoadSourceCode( function->SourceFile(), sourceCode); AutoLocker<Team> locker(fTeam); if (error == B_OK) { function->SetSourceCode(sourceCode, FUNCTION_SOURCE_LOADED); sourceCode->ReleaseReference(); return B_OK; } function->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE); } // Only try to load the function instance code, if it's not overridden yet. AutoLocker<Team> locker(fTeam); if (fFunctionInstance->SourceCodeState() != FUNCTION_SOURCE_LOADING) return B_OK; locker.Unlock(); // disassemble the function DisassembledCode* sourceCode = NULL; status_t error = fTeam->DebugInfo()->DisassembleFunction(fFunctionInstance, sourceCode); // set the result locker.Lock(); if (error == B_OK) { if (fFunctionInstance->SourceCodeState() == FUNCTION_SOURCE_LOADING) { // various parts of the debugger expect functions to have only // one of source or disassembly available. As such, if the current // function had source code previously active, unset it when // explicitly asked for disassembly. This needs to be done first // since Function will clear the disassembled code states of all // its child instances. if (function->SourceCodeState() == FUNCTION_SOURCE_LOADED) { FileSourceCode* sourceCode = function->GetSourceCode(); function->SetSourceCode(sourceCode, FUNCTION_SOURCE_NOT_LOADED); } fFunctionInstance->SetSourceCode(sourceCode, FUNCTION_SOURCE_LOADED); sourceCode->ReleaseReference(); } } else fFunctionInstance->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE); return error; }
status_t LoadSourceCodeJob::Do() { // if requested, try loading the source code for the function Function* function = fFunctionInstance->GetFunction(); if (fLoadForFunction) { FileSourceCode* sourceCode; status_t error = fTeam->DebugInfo()->LoadSourceCode( function->SourceFile(), sourceCode); AutoLocker<Team> locker(fTeam); if (error == B_OK) { function->SetSourceCode(sourceCode, FUNCTION_SOURCE_LOADED); sourceCode->ReleaseReference(); return B_OK; } function->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE); } // Only try to load the function instance code, if it's not overridden yet. AutoLocker<Team> locker(fTeam); if (fFunctionInstance->SourceCodeState() != FUNCTION_SOURCE_LOADING) return B_OK; locker.Unlock(); // disassemble the function DisassembledCode* sourceCode = NULL; status_t error = fTeam->DebugInfo()->DisassembleFunction(fFunctionInstance, sourceCode); // set the result locker.Lock(); if (error == B_OK) { if (fFunctionInstance->SourceCodeState() == FUNCTION_SOURCE_LOADING) { fFunctionInstance->SetSourceCode(sourceCode, FUNCTION_SOURCE_LOADED); sourceCode->ReleaseReference(); } } else fFunctionInstance->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE); return error; }
status_t TeamDebugInfo::AddImageDebugInfo(ImageDebugInfo* imageDebugInfo) { AutoLocker<BLocker> locker(fLock); // We have both locks now, so that for read-only access either lock // suffices. if (!fImages.AddItem(imageDebugInfo)) return B_NO_MEMORY; // Match all of the image debug info's functions instances with functions. BObjectList<SourceFileEntry> sourceFileEntries; for (int32 i = 0; FunctionInstance* instance = imageDebugInfo->FunctionAt(i); i++) { // lookup the function or create it, if it doesn't exist yet Function* function = fFunctions->Lookup(instance); if (function != NULL) { // TODO: Also update possible user breakpoints in this function! function->AddInstance(instance); instance->SetFunction(function); // The new image debug info might have additional information about // the source file of the function, so remember the source file // entry. if (LocatableFile* sourceFile = function->SourceFile()) { SourceFileEntry* entry = fSourceFiles->Lookup(sourceFile); if (entry != NULL && entry->GetSourceCode() != NULL) sourceFileEntries.AddItem(entry); } } else { function = new(std::nothrow) Function; if (function == NULL) { RemoveImageDebugInfo(imageDebugInfo); return B_NO_MEMORY; } function->AddInstance(instance); instance->SetFunction(function); status_t error = _AddFunction(function); // Insert after adding the instance. Otherwise the function // wouldn't be hashable/comparable. if (error != B_OK) { function->RemoveInstance(instance); instance->SetFunction(NULL); RemoveImageDebugInfo(imageDebugInfo); return error; } } } // update the source files the image debug info knows about for (int32 i = 0; SourceFileEntry* entry = sourceFileEntries.ItemAt(i); i++) { FileSourceCode* sourceCode = entry->GetSourceCode(); sourceCode->Lock(); if (imageDebugInfo->AddSourceCodeInfo(entry->SourceFile(), sourceCode) == B_OK) { // TODO: Notify interesting parties! Iterate through all functions // for this source file? } sourceCode->Unlock(); } return B_OK; }
status_t TeamDebugInfo::LoadSourceCode(LocatableFile* file, FileSourceCode*& _sourceCode) { AutoLocker<BLocker> locker(fLock); // If we don't know the source file, there's nothing we can do. SourceFileEntry* entry = fSourceFiles->Lookup(file); if (entry == NULL) return B_ENTRY_NOT_FOUND; // the source might already be loaded FileSourceCode* sourceCode = entry->GetSourceCode(); if (sourceCode != NULL) { sourceCode->AcquireReference(); _sourceCode = sourceCode; return B_OK; } // get the source language from some function's image debug info Function* function = entry->FunctionAt(0); if (function == NULL) return B_ENTRY_NOT_FOUND; FunctionDebugInfo* functionDebugInfo = function->FirstInstance()->GetFunctionDebugInfo(); SourceLanguage* language; status_t error = functionDebugInfo->GetSpecificImageDebugInfo() ->GetSourceLanguage(functionDebugInfo, language); if (error != B_OK) return error; BReference<SourceLanguage> languageReference(language, true); // no source code yet // locker.Unlock(); // TODO: It would be nice to unlock here, but we need to iterate through // the images below. We could clone the list, acquire references, and // unlock. Then we have to compare the list with the then current list when // we're done loading. // load the source file SourceFile* sourceFile; error = fFileManager->LoadSourceFile(file, sourceFile); if (error != B_OK) return error; // create the source code sourceCode = new(std::nothrow) FileSourceCode(file, sourceFile, language); sourceFile->ReleaseReference(); if (sourceCode == NULL) return B_NO_MEMORY; BReference<FileSourceCode> sourceCodeReference(sourceCode, true); error = sourceCode->Init(); if (error != B_OK) return error; // Iterate through all images that know the source file and ask them to add // information. bool anyInfo = false; for (int32 i = 0; ImageDebugInfo* imageDebugInfo = fImages.ItemAt(i); i++) anyInfo |= imageDebugInfo->AddSourceCodeInfo(file, sourceCode) == B_OK; if (!anyInfo) return B_ENTRY_NOT_FOUND; entry->SetSourceCode(sourceCode); _sourceCode = sourceCodeReference.Detach(); return B_OK; }