status_t Team::GetStatementAtAddress(target_addr_t address, FunctionInstance*& _function, Statement*& _statement) { TRACE_CODE("Team::GetStatementAtAddress(%#" B_PRIx64 ")\n", address); // get the image at the address Image* image = ImageByAddress(address); if (image == NULL) { TRACE_CODE(" -> no image\n"); return B_ENTRY_NOT_FOUND; } ImageDebugInfo* imageDebugInfo = image->GetImageDebugInfo(); if (imageDebugInfo == NULL) { TRACE_CODE(" -> no image debug info\n"); return B_ENTRY_NOT_FOUND; } // get the function FunctionInstance* functionInstance = imageDebugInfo->FunctionAtAddress(address); if (functionInstance == NULL) { TRACE_CODE(" -> no function instance\n"); return B_ENTRY_NOT_FOUND; } // If the function instance has disassembled code attached, we can get the // statement directly. if (DisassembledCode* code = functionInstance->GetSourceCode()) { Statement* statement = code->StatementAtAddress(address); if (statement == NULL) return B_ENTRY_NOT_FOUND; statement->AcquireReference(); _statement = statement; _function = functionInstance; return B_OK; } // get the statement from the image debug info FunctionDebugInfo* functionDebugInfo = functionInstance->GetFunctionDebugInfo(); status_t error = functionDebugInfo->GetSpecificImageDebugInfo() ->GetStatement(functionDebugInfo, address, _statement); if (error != B_OK) { TRACE_CODE(" -> no statement from the specific image debug info\n"); return error; } _function = functionInstance; return B_OK; }
status_t DebugReportGenerator::_DumpFunctionDisassembly(BFile& _output, target_addr_t instructionPointer) { AutoLocker< ::Team> teamLocker(fTeam); BString data; FunctionInstance* instance = NULL; Statement* statement = NULL; status_t error = fTeam->GetStatementAtAddress(instructionPointer, instance, statement); if (error != B_OK) { data.SetToFormat("Unable to retrieve disassembly for IP %#" B_PRIx64 ": %s\n", instructionPointer, strerror(error)); WRITE_AND_CHECK(_output, data); return B_OK; } DisassembledCode* code = instance->GetSourceCode(); Function* function = instance->GetFunction(); if (code == NULL) { switch (function->SourceCodeState()) { case FUNCTION_SOURCE_NOT_LOADED: case FUNCTION_SOURCE_LOADED: // FUNCTION_SOURCE_LOADED is included since, if we entered // here, it implies that the high level source for the // function has been loaded, but the disassembly has not. function->AddListener(this); fSourceWaitingFunction = function; fListener->FunctionSourceCodeRequested(instance, true); // fall through case FUNCTION_SOURCE_LOADING: { teamLocker.Unlock(); do { error = acquire_sem(fTeamDataSem); } while (error == B_INTERRUPTED); if (error != B_OK) return error; teamLocker.Lock(); break; } default: return B_OK; } if (instance->SourceCodeState() == FUNCTION_SOURCE_UNAVAILABLE) return B_OK; error = fTeam->GetStatementAtAddress(instructionPointer, instance, statement); code = instance->GetSourceCode(); } SourceLocation location = statement->StartSourceLocation(); data = "\t\t\tDisassembly:\n"; WRITE_AND_CHECK(_output, data); for (int32 i = 0; i <= location.Line(); i++) { data = "\t\t\t\t"; data << code->LineAt(i); if (i == location.Line()) data << " <--"; data << "\n"; WRITE_AND_CHECK(_output, data); } data = "\n"; WRITE_AND_CHECK(_output, data); return B_OK; }