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 ArchitectureX8664::DisassembleCode(FunctionDebugInfo* function, const void* buffer, size_t bufferSize, DisassembledCode*& _sourceCode) { DisassembledCode* source = new(std::nothrow) DisassembledCode( fAssemblyLanguage); if (source == NULL) return B_NO_MEMORY; BReference<DisassembledCode> sourceReference(source, true); // init disassembler DisassemblerX8664 disassembler; status_t error = disassembler.Init(function->Address(), buffer, bufferSize); if (error != B_OK) return error; // add a function name line BString functionName(function->PrettyName()); if (!source->AddCommentLine((functionName << ':').String())) return B_NO_MEMORY; // disassemble the instructions BString line; target_addr_t instructionAddress; target_size_t instructionSize; bool breakpointAllowed; while (disassembler.GetNextInstruction(line, instructionAddress, instructionSize, breakpointAllowed) == B_OK) { // TODO: Respect breakpointAllowed! if (!source->AddInstructionLine(line, instructionAddress, instructionSize)) { return B_NO_MEMORY; } } _sourceCode = sourceReference.Detach(); 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; }