void TeamDebugger::_HandleInspectAddress(target_addr_t address, TeamMemoryBlock::Listener* listener) { TRACE_CONTROL("TeamDebugger::_HandleInspectAddress(%" B_PRIx64 ", %p)\n", address, listener); TeamMemoryBlock* memoryBlock = fMemoryBlockManager ->GetMemoryBlock(address); if (memoryBlock == NULL) { _NotifyUser("Inspect Address", "Failed to allocate memory block"); return; } if (!memoryBlock->HasListener(listener)) memoryBlock->AddListener(listener); if (!memoryBlock->IsValid()) { AutoLocker< ::Team> teamLocker(fTeam); TeamMemory* memory = fTeam->GetTeamMemory(); // schedule the job status_t result; if ((result = fWorker->ScheduleJob( new(std::nothrow) RetrieveMemoryBlockJob(fTeam, memory, memoryBlock), this)) != B_OK) { memoryBlock->ReleaseReference(); _NotifyUser("Inspect Address", "Failed to retrieve memory data: %s", strerror(result)); } } else memoryBlock->NotifyDataRetrieved(); }
void InspectorWindow::MessageReceived(BMessage* message) { switch (message->what) { case MSG_THREAD_STATE_CHANGED: { ::Thread* thread; if (message->FindPointer("thread", reinterpret_cast<void**>(&thread)) != B_OK) { break; } BReference< ::Thread> threadReference(thread, true); if (thread->State() == THREAD_STATE_STOPPED) { if (fCurrentBlock != NULL) { _SetCurrentBlock(NULL); _SetToAddress(fCurrentAddress); } } break; } case MSG_INSPECT_ADDRESS: { target_addr_t address = 0; if (message->FindUInt64("address", &address) != B_OK) { if (fAddressInput->TextView()->TextLength() == 0) break; fExpressionInfo->SetTo(fAddressInput->Text()); fListener->ExpressionEvaluationRequested(fLanguage, fExpressionInfo); } else _SetToAddress(address); break; } case MSG_EXPRESSION_EVALUATED: { BString errorMessage; BReference<ExpressionResult> reference; ExpressionResult* value = NULL; if (message->FindPointer("value", reinterpret_cast<void**>(&value)) == B_OK) { reference.SetTo(value, true); if (value->Kind() == EXPRESSION_RESULT_KIND_PRIMITIVE) { Value* primitive = value->PrimitiveValue(); BVariant variantValue; primitive->ToVariant(variantValue); if (variantValue.Type() == B_STRING_TYPE) { errorMessage.SetTo(variantValue.ToString()); } else { _SetToAddress(variantValue.ToUInt64()); break; } } } else { status_t result = message->FindInt32("result"); errorMessage.SetToFormat("Failed to evaluate expression: %s", strerror(result)); } BAlert* alert = new(std::nothrow) BAlert("Inspect Address", errorMessage.String(), "Close"); if (alert != NULL) alert->Go(); break; } case MSG_NAVIGATE_PREVIOUS_BLOCK: case MSG_NAVIGATE_NEXT_BLOCK: { if (fCurrentBlock != NULL) { target_addr_t address = fCurrentBlock->BaseAddress(); if (message->what == MSG_NAVIGATE_PREVIOUS_BLOCK) address -= fCurrentBlock->Size(); else address += fCurrentBlock->Size(); BMessage setMessage(MSG_INSPECT_ADDRESS); setMessage.AddUInt64("address", address); PostMessage(&setMessage); } break; } case MSG_MEMORY_BLOCK_RETRIEVED: { TeamMemoryBlock* block = NULL; status_t result; if (message->FindPointer("block", reinterpret_cast<void **>(&block)) != B_OK || message->FindInt32("result", &result) != B_OK) { break; } if (result == B_OK) { _SetCurrentBlock(block); fPreviousBlockButton->SetEnabled(true); fNextBlockButton->SetEnabled(true); } else { BString errorMessage; errorMessage.SetToFormat("Unable to read address 0x%" B_PRIx64 ": %s", block->BaseAddress(), strerror(result)); BAlert* alert = new(std::nothrow) BAlert("Inspect address", errorMessage.String(), "Close"); if (alert == NULL) break; alert->Go(NULL); block->ReleaseReference(); } break; } case MSG_EDIT_CURRENT_BLOCK: { _SetEditMode(true); break; } case MSG_MEMORY_DATA_CHANGED: { if (fCurrentBlock == NULL) break; target_addr_t address; if (message->FindUInt64("address", &address) == B_OK && address >= fCurrentBlock->BaseAddress() && address < fCurrentBlock->BaseAddress() + fCurrentBlock->Size()) { fCurrentBlock->Invalidate(); _SetEditMode(false); fListener->InspectRequested(address, this); } break; } case MSG_COMMIT_MODIFIED_BLOCK: { // TODO: this could conceivably be extended to detect the // individual modified regions and only write those back. // That would require potentially submitting multiple separate // write requests, and thus require tracking all the writes being // waited upon for completion. fListener->MemoryWriteRequested(fCurrentBlock->BaseAddress(), fMemoryView->GetEditedData(), fCurrentBlock->Size()); break; } case MSG_REVERT_MODIFIED_BLOCK: { _SetEditMode(false); break; } default: { BWindow::MessageReceived(message); break; } } }
void InspectorWindow::MessageReceived(BMessage* message) { switch (message->what) { case MSG_INSPECT_ADDRESS: { target_addr_t address = 0; bool addressValid = false; if (message->FindUInt64("address", &address) != B_OK) { ExpressionParser parser; parser.SetSupportHexInput(true); const char* addressExpression = fAddressInput->Text(); BString errorMessage; try { address = parser.EvaluateToInt64(addressExpression); } catch(ParseException parseError) { errorMessage.SetToFormat("Failed to parse address: %s", parseError.message.String()); } catch(...) { errorMessage.SetToFormat( "Unknown error while parsing address"); } if (errorMessage.Length() > 0) { BAlert* alert = new(std::nothrow) BAlert("Inspect Address", errorMessage.String(), "Close"); if (alert != NULL) alert->Go(); } else addressValid = true; } else { addressValid = true; } if (addressValid) { fCurrentAddress = address; if (fCurrentBlock == NULL || !fCurrentBlock->Contains(address)) { fListener->InspectRequested(address, this); } else fMemoryView->SetTargetAddress(fCurrentBlock, address); } break; } case MSG_NAVIGATE_PREVIOUS_BLOCK: case MSG_NAVIGATE_NEXT_BLOCK: { if (fCurrentBlock != NULL) { target_addr_t address = fCurrentBlock->BaseAddress(); if (message->what == MSG_NAVIGATE_PREVIOUS_BLOCK) address -= fCurrentBlock->Size(); else address += fCurrentBlock->Size(); BMessage setMessage(MSG_INSPECT_ADDRESS); setMessage.AddUInt64("address", address); PostMessage(&setMessage); } break; } case MSG_MEMORY_BLOCK_RETRIEVED: { TeamMemoryBlock* block = NULL; status_t result; if (message->FindPointer("block", reinterpret_cast<void **>(&block)) != B_OK || message->FindInt32("result", &result) != B_OK) { break; } { AutoLocker< ::Team> teamLocker(fTeam); block->RemoveListener(this); } if (result == B_OK) { if (fCurrentBlock != NULL) fCurrentBlock->ReleaseReference(); fCurrentBlock = block; fMemoryView->SetTargetAddress(block, fCurrentAddress); fPreviousBlockButton->SetEnabled(true); fNextBlockButton->SetEnabled(true); } else { BString errorMessage; errorMessage.SetToFormat("Unable to read address 0x%" B_PRIx64 ": %s", block->BaseAddress(), strerror(result)); BAlert* alert = new(std::nothrow) BAlert("Inspect address", errorMessage.String(), "Close"); if (alert == NULL) break; alert->Go(NULL); block->ReleaseReference(); } break; } default: { BWindow::MessageReceived(message); break; } } }
void CliDumpMemoryCommand::Execute(int argc, const char* const* argv, CliContext& context) { if (argc < 2) { PrintUsage(argv[0]); return; } target_addr_t address; ExpressionParser parser; parser.SetSupportHexInput(true); try { address = parser.EvaluateToInt64(argv[1]); } catch(...) { printf("Error parsing address/expression.\n"); return; } int32 itemSize = 0; int32 displayWidth = 0; // build the format string if (strcmp(argv[0], "db") == 0) { itemSize = 1; displayWidth = 16; } else if (strcmp(argv[0], "ds") == 0) { itemSize = 2; displayWidth = 8; } else if (strcmp(argv[0], "dw") == 0) { itemSize = 4; displayWidth = 4; } else if (strcmp(argv[0], "dl") == 0) { itemSize = 8; displayWidth = 2; } else if (strcmp(argv[0], "string") == 0) { itemSize = 1; displayWidth = -1; } else { printf("dump called in an invalid way!\n"); return; } int32 num = 0; if (argc == 3) { char *remainder; num = strtol(argv[2], &remainder, 0); if (*remainder != '\0') { printf("Error: invalid parameter \"%s\"\n", argv[2]); } } if (num <= 0) num = displayWidth; TeamMemoryBlock* block = context.CurrentBlock(); if (block == NULL || !block->Contains(address)) { context.GetUserInterfaceListener()->InspectRequested(address, &context); context.WaitForEvents(CliContext::EVENT_TEAM_MEMORY_BLOCK_RETRIEVED); if (context.IsTerminating()) return; block = context.CurrentBlock(); } if (!strcmp(argv[0], "string")) { printf("%p \"", (char*)address); target_addr_t offset = address; char c; while (block->Contains(offset)) { c = *(block->Data() + offset - block->BaseAddress()); if (c == '\0') break; if (c == '\n') printf("\\n"); else if (c == '\t') printf("\\t"); else { if (!isprint(c)) c = '.'; printf("%c", c); } ++offset; } printf("\"\n"); } else { BString output; UiUtils::DumpMemory(output, 0, block, address, itemSize, displayWidth, num); printf("%s\n", output.String()); } }