1 #include "QtDebugger.h"
2 #include "ui_QtDebugger.h"
3
4 #include <QApplication>
5 #include <QInputDialog>
6 #include <QMessageBox>
7
8 #include <iostream>
9 #include "AppConfig.h"
10 #include "MIPSAssembler.h"
11 #include "Ps2Const.h"
12 #include "ee/PS2OS.h"
13 #include "MipsFunctionPatternDb.h"
14 #include "StdStream.h"
15 #include "StdStreamUtils.h"
16 #include "xml/Parser.h"
17 #include "xml/Utils.h"
18 #include "string_cast.h"
19 #include "string_format.h"
20 #include "PathUtils.h"
21
22 #define PREF_DEBUGGER_MEMORYVIEW_BYTEWIDTH "debugger.memoryview.bytewidth"
23
24 #define FIND_MAX_ADDRESS 0x02000000
25
QtDebugger(CPS2VM & virtualMachine)26 QtDebugger::QtDebugger(CPS2VM& virtualMachine)
27 : ui(new Ui::QtDebugger)
28 , m_virtualMachine(virtualMachine)
29 {
30 ui->setupUi(this);
31
32 // Setup QT Stuff
33 RegisterPreferences();
34
35 //ELF View Initialization
36 m_pELFView = new CELFView(ui->mdiArea);
37
38 //Functions View Initialization
39 m_pFunctionsView = new CFunctionsView(ui->mdiArea);
40 m_pFunctionsView->hide();
41 m_OnFunctionDblClickConnection = m_pFunctionsView->OnFunctionDblClick.Connect(std::bind(&QtDebugger::OnFunctionsViewFunctionDblClick, this, std::placeholders::_1));
42 m_OnFunctionsStateChangeConnection = m_pFunctionsView->OnFunctionsStateChange.Connect(std::bind(&QtDebugger::OnFunctionsViewFunctionsStateChange, this));
43
44 //Threads View Initialization
45 auto threadsView = new CThreadsViewWnd(ui->mdiArea);
46 m_threadsView = new QMdiSubWindow(ui->mdiArea);
47 m_threadsView->setWidget(threadsView);
48 m_threadsView->setWindowTitle("Threads");
49
50 m_threadsView->hide();
51 m_OnGotoAddressConnection = threadsView->OnGotoAddress.Connect(std::bind(&QtDebugger::OnThreadsViewAddressDblClick, this, std::placeholders::_1));
52
53 //Address List View Initialization
54 m_addressListView = new CAddressListViewWnd(ui->mdiArea);
55 m_addressListView->hide();
56 m_AddressSelectedConnection = m_addressListView->AddressSelected.Connect([&](uint32 address) { OnFindCallersAddressDblClick(address); });
57
58 //Debug Views Initialization
59 m_nCurrentView = -1;
60
61 m_pView[DEBUGVIEW_EE] = new CDebugView(this, ui->mdiArea, m_virtualMachine, &m_virtualMachine.m_ee->m_EE,
62 std::bind(&CPS2VM::StepEe, &m_virtualMachine), m_virtualMachine.m_ee->m_os, "EmotionEngine", PS2::EE_RAM_SIZE + PS2::EE_BIOS_SIZE);
63 m_pView[DEBUGVIEW_VU0] = new CDebugView(this, ui->mdiArea, m_virtualMachine, &m_virtualMachine.m_ee->m_VU0,
64 std::bind(&CPS2VM::StepVu0, &m_virtualMachine), nullptr, "Vector Unit 0", PS2::VUMEM0SIZE, CQtDisAsmTableModel::DISASM_VU);
65 m_pView[DEBUGVIEW_VU1] = new CDebugView(this, ui->mdiArea, m_virtualMachine, &m_virtualMachine.m_ee->m_VU1,
66 std::bind(&CPS2VM::StepVu1, &m_virtualMachine), nullptr, "Vector Unit 1", PS2::VUMEM1SIZE, CQtDisAsmTableModel::DISASM_VU);
67 m_pView[DEBUGVIEW_IOP] = new CDebugView(this, ui->mdiArea, m_virtualMachine, &m_virtualMachine.m_iop->m_cpu,
68 std::bind(&CPS2VM::StepIop, &m_virtualMachine), m_virtualMachine.m_iop->m_bios.get(), "IO Processor", PS2::IOP_RAM_SIZE);
69
70 m_OnExecutableChangeConnection = m_virtualMachine.m_ee->m_os->OnExecutableChange.Connect(std::bind(&QtDebugger::OnExecutableChange, this));
71 m_OnExecutableUnloadingConnection = m_virtualMachine.m_ee->m_os->OnExecutableUnloading.Connect(std::bind(&QtDebugger::OnExecutableUnloading, this));
72
73 m_OnMachineStateChangeConnection = m_virtualMachine.OnMachineStateChange.Connect(std::bind(&QtDebugger::OnMachineStateChange, this));
74 m_OnRunningStateChangeConnection = m_virtualMachine.OnRunningStateChange.Connect(std::bind(&QtDebugger::OnRunningStateChange, this));
75
76 ActivateView(DEBUGVIEW_EE);
77 LoadSettings();
78
79 if(GetDisassemblyWindow()->isVisible())
80 {
81 GetDisassemblyWindow()->setFocus(Qt::ActiveWindowFocusReason);
82 }
83
84 connect(this, &QtDebugger::OnMachineStateChange, this, &QtDebugger::OnMachineStateChangeMsg);
85 connect(this, &QtDebugger::OnRunningStateChange, this, &QtDebugger::OnRunningStateChangeMsg);
86 connect(this, &QtDebugger::OnExecutableChange, this, &QtDebugger::OnExecutableChangeMsg);
87 connect(this, &QtDebugger::OnExecutableUnloading, this, &QtDebugger::OnExecutableUnloadingMsg);
88 }
89
~QtDebugger()90 QtDebugger::~QtDebugger()
91 {
92 delete ui;
93
94 OnExecutableUnloading();
95
96 for(unsigned int i = 0; i < DEBUGVIEW_MAX; i++)
97 {
98 delete m_pView[i];
99 }
100
101 delete m_pELFView;
102 delete m_pFunctionsView;
103 }
104
closeEvent(QCloseEvent * event)105 void QtDebugger::closeEvent(QCloseEvent* event)
106 {
107 if(isVisible())
108 SaveSettings();
109
110 event->accept();
111 }
112
RegisterPreferences()113 void QtDebugger::RegisterPreferences()
114 {
115 CAppConfig& config(CAppConfig::GetInstance());
116
117 config.RegisterPreferenceInteger("debugger.disasm.posx", 0);
118 config.RegisterPreferenceInteger("debugger.disasm.posy", 0);
119 config.RegisterPreferenceInteger("debugger.disasm.sizex", 0);
120 config.RegisterPreferenceInteger("debugger.disasm.sizey", 0);
121 config.RegisterPreferenceBoolean("debugger.disasm.visible", true);
122
123 config.RegisterPreferenceInteger("debugger.regview.posx", 0);
124 config.RegisterPreferenceInteger("debugger.regview.posy", 0);
125 config.RegisterPreferenceInteger("debugger.regview.sizex", 0);
126 config.RegisterPreferenceInteger("debugger.regview.sizey", 0);
127 config.RegisterPreferenceBoolean("debugger.regview.visible", true);
128
129 config.RegisterPreferenceInteger("debugger.memoryview.posx", 0);
130 config.RegisterPreferenceInteger("debugger.memoryview.posy", 0);
131 config.RegisterPreferenceInteger("debugger.memoryview.sizex", 0);
132 config.RegisterPreferenceInteger("debugger.memoryview.sizey", 0);
133 config.RegisterPreferenceBoolean("debugger.memoryview.visible", true);
134 config.RegisterPreferenceInteger(PREF_DEBUGGER_MEMORYVIEW_BYTEWIDTH, 0);
135
136 config.RegisterPreferenceInteger("debugger.callstack.posx", 0);
137 config.RegisterPreferenceInteger("debugger.callstack.posy", 0);
138 config.RegisterPreferenceInteger("debugger.callstack.sizex", 0);
139 config.RegisterPreferenceInteger("debugger.callstack.sizey", 0);
140 config.RegisterPreferenceBoolean("debugger.callstack.visible", true);
141 }
142
UpdateTitle()143 void QtDebugger::UpdateTitle()
144 {
145 std::string sTitle("Play! - Debugger");
146
147 if(GetCurrentView() != NULL)
148 {
149 sTitle += (" - [ ");
150 sTitle += GetCurrentView()->GetName();
151 sTitle += (" ]");
152 }
153
154 setWindowTitle(sTitle.c_str());
155 }
156
LoadSettings()157 void QtDebugger::LoadSettings()
158 {
159 LoadViewLayout();
160 LoadBytesPerLine();
161 }
162
SaveSettings()163 void QtDebugger::SaveSettings()
164 {
165 SaveViewLayout();
166 SaveBytesPerLine();
167 }
168
SerializeWindowGeometry(QWidget * pWindow,const char * sPosX,const char * sPosY,const char * sSizeX,const char * sSizeY,const char * sVisible)169 void QtDebugger::SerializeWindowGeometry(QWidget* pWindow, const char* sPosX, const char* sPosY, const char* sSizeX, const char* sSizeY, const char* sVisible)
170 {
171 CAppConfig& config(CAppConfig::GetInstance());
172
173 auto geometry = pWindow->geometry();
174
175 config.SetPreferenceInteger(sPosX, geometry.x());
176 config.SetPreferenceInteger(sPosY, geometry.y());
177
178 config.SetPreferenceInteger(sSizeX, geometry.width());
179 config.SetPreferenceInteger(sSizeY, geometry.height());
180
181 config.SetPreferenceBoolean(sVisible, pWindow->isVisible());
182 }
183
UnserializeWindowGeometry(QWidget * pWindow,const char * sPosX,const char * sPosY,const char * sSizeX,const char * sSizeY,const char * sVisible)184 void QtDebugger::UnserializeWindowGeometry(QWidget* pWindow, const char* sPosX, const char* sPosY, const char* sSizeX, const char* sSizeY, const char* sVisible)
185 {
186 CAppConfig& config(CAppConfig::GetInstance());
187
188 pWindow->setGeometry(config.GetPreferenceInteger(sPosX), config.GetPreferenceInteger(sPosY),
189 config.GetPreferenceInteger(sSizeX), config.GetPreferenceInteger(sSizeY));
190
191 if(!config.GetPreferenceBoolean(sVisible))
192 {
193 pWindow->hide();
194 }
195 else
196 {
197 pWindow->show();
198 }
199 }
200
Resume()201 void QtDebugger::Resume()
202 {
203 m_virtualMachine.Resume();
204 }
205
StepCPU()206 void QtDebugger::StepCPU()
207 {
208 if(m_virtualMachine.GetStatus() == CVirtualMachine::RUNNING)
209 {
210 QApplication::beep();
211 return;
212 }
213
214 if(!GetDisassemblyWindow()->hasFocus())
215 {
216 GetDisassemblyWindow()->setFocus(Qt::ActiveWindowFocusReason);
217 }
218
219 GetCurrentView()->Step();
220 }
221
FindWordValue(uint32 mask)222 void QtDebugger::FindWordValue(uint32 mask)
223 {
224 uint32 targetValue = 0;
225 {
226 bool ok;
227 QString res = QInputDialog::getText(this, tr("Find Value in Memory"),
228 tr("Enter value to find:"), QLineEdit::Normal,
229 tr("00000000"), &ok);
230 if(!ok || res.isEmpty())
231 return;
232
233 if(sscanf(res.toStdString().c_str(), "%x", &targetValue) <= 0)
234 {
235 QMessageBox msgBox;
236 msgBox.setText("Invalid hex value.");
237 msgBox.exec();
238 return;
239 }
240 }
241 auto context = GetCurrentView()->GetContext();
242 auto title = string_format("Search results for 0x%08X", targetValue);
243 auto refs = FindWordValueRefs(context, targetValue & mask, mask);
244
245 m_addressListView->SetTitle(std::move(title));
246 m_addressListView->SetAddressList(std::move(refs));
247 m_addressListView->show();
248 m_addressListView->setFocus(Qt::ActiveWindowFocusReason);
249 }
250
AssembleJAL()251 void QtDebugger::AssembleJAL()
252 {
253 uint32 nValueTarget = 0, nValueAssemble = 0;
254 auto getAddress =
255 [this](const char* prompt, uint32& address) {
256 bool ok;
257 QString res = QInputDialog::getText(this, tr("Assemble JAL"),
258 tr(prompt), QLineEdit::Normal,
259 tr("00000000"), &ok);
260 if(!ok || res.isEmpty())
261 return false;
262 uint32 addrValueTemp = 0;
263 if(sscanf(res.toStdString().c_str(), "%x", &address) <= 0)
264 {
265 QMessageBox msgBox;
266 msgBox.setText("Invalid value.");
267 msgBox.exec();
268 return false;
269 }
270 return true;
271 };
272 if(!getAddress("Enter jump target:", nValueTarget)) return;
273 if(!getAddress("Enter address to assemble JAL to:", nValueAssemble)) return;
274
275 *(uint32*)&m_virtualMachine.m_ee->m_ram[nValueAssemble] = 0x0C000000 | (nValueTarget / 4);
276 }
277
ReanalyzeEe()278 void QtDebugger::ReanalyzeEe()
279 {
280 if(m_virtualMachine.m_ee->m_os->GetELF() == nullptr) return;
281
282 auto executableRange = m_virtualMachine.m_ee->m_os->GetExecutableRange();
283 uint32 minAddr = executableRange.first;
284 uint32 maxAddr = executableRange.second & ~0x03;
285
286 auto getAddress =
287 [this](const char* prompt, uint32& address) {
288 bool ok;
289 QString res = QInputDialog::getText(this, tr("Analyze EE"),
290 tr(prompt), QLineEdit::Normal,
291 tr(string_format("0x%08X", address).c_str()), &ok);
292 if(!ok || res.isEmpty())
293 return false;
294 uint32 addrValueTemp = 0;
295 if(sscanf(res.toStdString().c_str(), "%x", &addrValueTemp) <= 0)
296 {
297 QMessageBox msgBox;
298 msgBox.setText("Invalid value.");
299 msgBox.exec();
300 return false;
301 }
302 if(addrValueTemp != 0)
303 {
304 address = addrValueTemp & ~0x3;
305 }
306 return true;
307 };
308
309 if(!getAddress("Start Address:", minAddr)) return;
310 if(!getAddress("End Address:", maxAddr)) return;
311
312 if(minAddr > maxAddr)
313 {
314 QMessageBox msgBox;
315 msgBox.setText("Start address is larger than end address.");
316 msgBox.exec();
317 return;
318 }
319
320 minAddr = std::min<uint32>(minAddr, PS2::EE_RAM_SIZE);
321 maxAddr = std::min<uint32>(maxAddr, PS2::EE_RAM_SIZE);
322
323 m_virtualMachine.m_ee->m_EE.m_analysis->Clear();
324 m_virtualMachine.m_ee->m_EE.m_analysis->Analyse(minAddr, maxAddr);
325 }
326
FindEeFunctions()327 void QtDebugger::FindEeFunctions()
328 {
329 if(m_virtualMachine.m_ee->m_os->GetELF() == nullptr) return;
330
331 auto executableRange = m_virtualMachine.m_ee->m_os->GetExecutableRange();
332 uint32 minAddr = executableRange.first;
333 uint32 maxAddr = executableRange.second & ~0x03;
334
335 auto functionsPath = Framework::PathUtils::GetAppResourcesPath() / "ee_functions.xml";
336 auto functionsStream = Framework::CreateInputStdStream(functionsPath.native());
337 auto functionsDocument = std::unique_ptr<Framework::Xml::CNode>(Framework::Xml::CParser::ParseDocument(functionsStream));
338 auto functionsNode = functionsDocument->Select("Functions");
339
340 //Check function patterns
341 {
342 CMipsFunctionPatternDb patternDb(functionsNode);
343
344 for(auto patternIterator(std::begin(patternDb.GetPatterns()));
345 patternIterator != std::end(patternDb.GetPatterns()); ++patternIterator)
346 {
347 auto pattern = *patternIterator;
348 for(uint32 address = minAddr; address <= maxAddr; address += 4)
349 {
350 uint32* text = reinterpret_cast<uint32*>(m_virtualMachine.m_ee->m_ram + address);
351 uint32 textSize = (maxAddr - address);
352 if(pattern.Matches(text, textSize))
353 {
354 m_virtualMachine.m_ee->m_EE.m_Functions.InsertTag(address, pattern.name.c_str());
355 break;
356 }
357 }
358 }
359 }
360
361 //Check function comments
362 {
363 std::map<std::string, std::string> stringFuncs;
364 auto commentNodes = functionsNode->SelectNodes("FunctionComments/FunctionComment");
365 for(const auto& commentNode : commentNodes)
366 {
367 auto comment = Framework::Xml::GetAttributeStringValue(commentNode, "Comment");
368 auto functionName = Framework::Xml::GetAttributeStringValue(commentNode, "Function");
369 stringFuncs.insert(std::make_pair(comment, functionName));
370 }
371
372 //Identify functions that reference special string literals
373 {
374 auto& eeFunctions = m_virtualMachine.m_ee->m_EE.m_Functions;
375 const auto& eeComments = m_virtualMachine.m_ee->m_EE.m_Comments;
376 const auto& eeAnalysis = m_virtualMachine.m_ee->m_EE.m_analysis;
377 for(auto tagIterator = eeComments.GetTagsBegin();
378 tagIterator != eeComments.GetTagsEnd(); tagIterator++)
379 {
380 const auto& tag = *tagIterator;
381 auto subroutine = eeAnalysis->FindSubroutine(tag.first);
382 if(subroutine == nullptr) continue;
383 auto stringFunc = stringFuncs.find(tag.second);
384 if(stringFunc == std::end(stringFuncs)) continue;
385 eeFunctions.InsertTag(subroutine->start, stringFunc->second.c_str());
386 }
387 }
388 }
389
390 m_virtualMachine.m_ee->m_EE.m_Functions.OnTagListChange();
391 }
392
Layout1024()393 void QtDebugger::Layout1024()
394 {
395 static_cast<QWidget*>(GetDisassemblyWindow()->parent())->setGeometry(0, 0, 700, 435);
396 static_cast<QWidget*>(GetDisassemblyWindow()->parent())->show();
397 GetDisassemblyWindow()->show();
398
399 static_cast<QWidget*>(GetRegisterViewWindow()->parent())->setGeometry(700, 0, 324, 572);
400 static_cast<QWidget*>(GetRegisterViewWindow()->parent())->show();
401 GetRegisterViewWindow()->show();
402
403 static_cast<QWidget*>(GetMemoryViewWindow()->parent())->setGeometry(0, 435, 700, 265);
404 static_cast<QWidget*>(GetMemoryViewWindow()->parent())->show();
405 GetMemoryViewWindow()->show();
406
407 static_cast<QWidget*>(GetCallStackWindow()->parent())->setGeometry(700, 572, 324, 128);
408 static_cast<QWidget*>(GetCallStackWindow()->parent())->show();
409 GetCallStackWindow()->show();
410 }
411
Layout1280()412 void QtDebugger::Layout1280()
413 {
414 static_cast<QWidget*>(GetDisassemblyWindow()->parent())->setGeometry(0, 0, 900, 540);
415 static_cast<QWidget*>(GetDisassemblyWindow()->parent())->show();
416 GetDisassemblyWindow()->show();
417
418 static_cast<QWidget*>(GetRegisterViewWindow()->parent())->setGeometry(900, 0, 380, 784);
419 static_cast<QWidget*>(GetRegisterViewWindow()->parent())->show();
420 GetRegisterViewWindow()->show();
421
422 static_cast<QWidget*>(GetMemoryViewWindow()->parent())->setGeometry(0, 540, 900, 416);
423 static_cast<QWidget*>(GetMemoryViewWindow()->parent())->show();
424 GetMemoryViewWindow()->show();
425
426 static_cast<QWidget*>(GetCallStackWindow()->parent())->setGeometry(900, 784, 380, 172);
427 static_cast<QWidget*>(GetCallStackWindow()->parent())->show();
428 GetCallStackWindow()->show();
429 }
430
Layout1600()431 void QtDebugger::Layout1600()
432 {
433 static_cast<QWidget*>(GetDisassemblyWindow()->parent())->setGeometry(0, 0, 1094, 725);
434 static_cast<QWidget*>(GetDisassemblyWindow()->parent())->show();
435 GetDisassemblyWindow()->show();
436
437 static_cast<QWidget*>(GetRegisterViewWindow()->parent())->setGeometry(1094, 0, 506, 725);
438 static_cast<QWidget*>(GetRegisterViewWindow()->parent())->show();
439 GetRegisterViewWindow()->show();
440
441 static_cast<QWidget*>(GetMemoryViewWindow()->parent())->setGeometry(0, 725, 1094, 407);
442 static_cast<QWidget*>(GetMemoryViewWindow()->parent())->show();
443 GetMemoryViewWindow()->show();
444
445 static_cast<QWidget*>(GetCallStackWindow()->parent())->setGeometry(1094, 725, 506, 407);
446 static_cast<QWidget*>(GetCallStackWindow()->parent())->show();
447 GetCallStackWindow()->show();
448 }
449
ActivateView(unsigned int nView)450 void QtDebugger::ActivateView(unsigned int nView)
451 {
452 if(m_nCurrentView == nView) return;
453
454 if(m_nCurrentView != -1)
455 {
456 SaveBytesPerLine();
457 SaveViewLayout();
458 GetCurrentView()->Hide();
459 }
460
461 m_findCallersRequestConnection.reset();
462
463 m_nCurrentView = nView;
464 LoadViewLayout();
465 LoadBytesPerLine();
466 UpdateTitle();
467
468 {
469 auto biosDebugInfoProvider = GetCurrentView()->GetBiosDebugInfoProvider();
470 m_pFunctionsView->SetContext(GetCurrentView()->GetContext(), biosDebugInfoProvider);
471 static_cast<CThreadsViewWnd*>(m_threadsView->widget())->SetContext(GetCurrentView()->GetContext(), biosDebugInfoProvider);
472 }
473
474 if(GetDisassemblyWindow()->isVisible())
475 {
476 GetDisassemblyWindow()->setFocus(Qt::ActiveWindowFocusReason);
477 }
478
479 m_findCallersRequestConnection = GetCurrentView()->GetDisassemblyWindow()->FindCallersRequested.Connect(
480 [&](uint32 address) { OnFindCallersRequested(address); });
481 }
482
SaveViewLayout()483 void QtDebugger::SaveViewLayout()
484 {
485 SerializeWindowGeometry(static_cast<QWidget*>(GetDisassemblyWindow()->parent()),
486 "debugger.disasm.posx",
487 "debugger.disasm.posy",
488 "debugger.disasm.sizex",
489 "debugger.disasm.sizey",
490 "debugger.disasm.visible");
491
492 SerializeWindowGeometry(static_cast<QWidget*>(GetRegisterViewWindow()->parent()),
493 "debugger.regview.posx",
494 "debugger.regview.posy",
495 "debugger.regview.sizex",
496 "debugger.regview.sizey",
497 "debugger.regview.visible");
498
499 SerializeWindowGeometry(static_cast<QWidget*>(GetMemoryViewWindow()->parent()),
500 "debugger.memoryview.posx",
501 "debugger.memoryview.posy",
502 "debugger.memoryview.sizex",
503 "debugger.memoryview.sizey",
504 "debugger.memoryview.visible");
505
506 SerializeWindowGeometry(static_cast<QWidget*>(GetCallStackWindow()->parent()),
507 "debugger.callstack.posx",
508 "debugger.callstack.posy",
509 "debugger.callstack.sizex",
510 "debugger.callstack.sizey",
511 "debugger.callstack.visible");
512 }
513
LoadViewLayout()514 void QtDebugger::LoadViewLayout()
515 {
516 UnserializeWindowGeometry(static_cast<QWidget*>(GetDisassemblyWindow()->parent()),
517 "debugger.disasm.posx",
518 "debugger.disasm.posy",
519 "debugger.disasm.sizex",
520 "debugger.disasm.sizey",
521 "debugger.disasm.visible");
522
523 UnserializeWindowGeometry(static_cast<QWidget*>(GetRegisterViewWindow()->parent()),
524 "debugger.regview.posx",
525 "debugger.regview.posy",
526 "debugger.regview.sizex",
527 "debugger.regview.sizey",
528 "debugger.regview.visible");
529
530 UnserializeWindowGeometry(static_cast<QWidget*>(GetMemoryViewWindow()->parent()),
531 "debugger.memoryview.posx",
532 "debugger.memoryview.posy",
533 "debugger.memoryview.sizex",
534 "debugger.memoryview.sizey",
535 "debugger.memoryview.visible");
536
537 UnserializeWindowGeometry(static_cast<QWidget*>(GetCallStackWindow()->parent()),
538 "debugger.callstack.posx",
539 "debugger.callstack.posy",
540 "debugger.callstack.sizex",
541 "debugger.callstack.sizey",
542 "debugger.callstack.visible");
543 }
544
SaveBytesPerLine()545 void QtDebugger::SaveBytesPerLine()
546 {
547 auto memoryView = GetMemoryViewWindow();
548 auto bytesPerLine = GetMemoryViewWindow()->GetBytesPerLine();
549 CAppConfig::GetInstance().SetPreferenceInteger(PREF_DEBUGGER_MEMORYVIEW_BYTEWIDTH, bytesPerLine);
550 }
551
LoadBytesPerLine()552 void QtDebugger::LoadBytesPerLine()
553 {
554 auto bytesPerLine = CAppConfig::GetInstance().GetPreferenceInteger(PREF_DEBUGGER_MEMORYVIEW_BYTEWIDTH);
555 auto memoryView = GetMemoryViewWindow();
556 memoryView->SetBytesPerLine(bytesPerLine);
557 }
558
GetCurrentView()559 CDebugView* QtDebugger::GetCurrentView()
560 {
561 if(m_nCurrentView == -1) return NULL;
562 return m_pView[m_nCurrentView];
563 }
564
GetContext()565 CMIPS* QtDebugger::GetContext()
566 {
567 return nullptr;
568 return GetCurrentView()->GetContext();
569 }
570
GetDisassemblyWindow()571 CDisAsmWnd* QtDebugger::GetDisassemblyWindow()
572 {
573 return GetCurrentView()->GetDisassemblyWindow();
574 }
575
GetMemoryViewWindow()576 CMemoryViewMIPSWnd* QtDebugger::GetMemoryViewWindow()
577 {
578 return GetCurrentView()->GetMemoryViewWindow();
579 }
580
GetRegisterViewWindow()581 CRegViewWnd* QtDebugger::GetRegisterViewWindow()
582 {
583 return GetCurrentView()->GetRegisterViewWindow();
584 }
585
GetCallStackWindow()586 CCallStackWnd* QtDebugger::GetCallStackWindow()
587 {
588 return GetCurrentView()->GetCallStackWindow();
589 }
590
FindCallers(CMIPS * context,uint32 address)591 std::vector<uint32> QtDebugger::FindCallers(CMIPS* context, uint32 address)
592 {
593 std::vector<uint32> callers;
594 for(uint32 i = 0; i < FIND_MAX_ADDRESS; i += 4)
595 {
596 uint32 opcode = context->m_pMemoryMap->GetInstruction(i);
597 uint32 ea = context->m_pArch->GetInstructionEffectiveAddress(context, i, opcode);
598 if(ea == address)
599 {
600 callers.push_back(i);
601 }
602 }
603 return callers;
604 }
605
FindWordValueRefs(CMIPS * context,uint32 targetValue,uint32 valueMask)606 std::vector<uint32> QtDebugger::FindWordValueRefs(CMIPS* context, uint32 targetValue, uint32 valueMask)
607 {
608 std::vector<uint32> refs;
609 for(uint32 i = 0; i < FIND_MAX_ADDRESS; i += 4)
610 {
611 uint32 valueAtAddress = context->m_pMemoryMap->GetWord(i);
612 if((valueAtAddress & valueMask) == targetValue)
613 {
614 refs.push_back(i);
615 }
616 }
617 return refs;
618 }
619
OnFunctionsViewFunctionDblClick(uint32 address)620 void QtDebugger::OnFunctionsViewFunctionDblClick(uint32 address)
621 {
622 GetDisassemblyWindow()->SetAddress(address);
623 }
624
OnFunctionsViewFunctionsStateChange()625 void QtDebugger::OnFunctionsViewFunctionsStateChange()
626 {
627 GetDisassemblyWindow()->HandleMachineStateChange();
628 GetCallStackWindow()->HandleMachineStateChange();
629 }
630
OnThreadsViewAddressDblClick(uint32 address)631 void QtDebugger::OnThreadsViewAddressDblClick(uint32 address)
632 {
633 auto disAsm = GetDisassemblyWindow();
634 disAsm->SetCenterAtAddress(address);
635 disAsm->SetSelectedAddress(address);
636 }
637
OnFindCallersRequested(uint32 address)638 void QtDebugger::OnFindCallersRequested(uint32 address)
639 {
640 auto context = GetCurrentView()->GetContext();
641 auto callers = FindCallers(context, address);
642 auto title =
643 [&]() {
644 auto functionName = context->m_Functions.Find(address);
645 if(functionName)
646 {
647 return string_format("Find Callers For '%s' (0x%08X)",
648 functionName, address);
649 }
650 else
651 {
652 return string_format("Find Callers For 0x%08X", address);
653 }
654 }();
655
656 m_addressListView->SetAddressList(std::move(callers));
657 m_addressListView->SetTitle(std::move(title));
658 m_addressListView->show();
659 m_addressListView->setFocus(Qt::ActiveWindowFocusReason);
660 }
661
OnFindCallersAddressDblClick(uint32 address)662 void QtDebugger::OnFindCallersAddressDblClick(uint32 address)
663 {
664 auto disAsm = GetDisassemblyWindow();
665 disAsm->SetCenterAtAddress(address);
666 disAsm->SetSelectedAddress(address);
667 }
668
OnExecutableChangeMsg()669 void QtDebugger::OnExecutableChangeMsg()
670 {
671 m_pELFView->SetELF(m_virtualMachine.m_ee->m_os->GetELF());
672
673 LoadDebugTags();
674
675 GetDisassemblyWindow()->HandleMachineStateChange();
676 GetCallStackWindow()->HandleMachineStateChange();
677 m_pFunctionsView->Refresh();
678 }
679
OnExecutableUnloadingMsg()680 void QtDebugger::OnExecutableUnloadingMsg()
681 {
682 SaveDebugTags();
683 m_pELFView->SetELF(NULL);
684 }
685
OnMachineStateChangeMsg()686 void QtDebugger::OnMachineStateChangeMsg()
687 {
688 for(auto& view : m_pView)
689 {
690 view->HandleMachineStateChange();
691 }
692 static_cast<CThreadsViewWnd*>(m_threadsView->widget())->HandleMachineStateChange();
693 }
694
OnRunningStateChangeMsg()695 void QtDebugger::OnRunningStateChangeMsg()
696 {
697 auto newState = m_virtualMachine.GetStatus();
698 for(auto& view : m_pView)
699 {
700 view->HandleRunningStateChange(newState);
701 }
702 static_cast<CThreadsViewWnd*>(m_threadsView->widget())->HandleRunningStateChange(newState);
703 }
704
LoadDebugTags()705 void QtDebugger::LoadDebugTags()
706 {
707 #ifdef DEBUGGER_INCLUDED
708 m_virtualMachine.LoadDebugTags(m_virtualMachine.m_ee->m_os->GetExecutableName());
709 #endif
710 }
711
SaveDebugTags()712 void QtDebugger::SaveDebugTags()
713 {
714 #ifdef DEBUGGER_INCLUDED
715 if(m_virtualMachine.m_ee != nullptr)
716 {
717 if(m_virtualMachine.m_ee->m_os->GetELF() != nullptr)
718 {
719 m_virtualMachine.SaveDebugTags(m_virtualMachine.m_ee->m_os->GetExecutableName());
720 }
721 }
722 #endif
723 }
724
on_actionResume_triggered()725 void QtDebugger::on_actionResume_triggered()
726 {
727 Resume();
728 }
729
on_actionStep_CPU_triggered()730 void QtDebugger::on_actionStep_CPU_triggered()
731 {
732 StepCPU();
733 }
734
on_actionDump_INTC_Handlers_triggered()735 void QtDebugger::on_actionDump_INTC_Handlers_triggered()
736 {
737 m_virtualMachine.DumpEEIntcHandlers();
738 }
739
on_actionDump_DMAC_Handlers_triggered()740 void QtDebugger::on_actionDump_DMAC_Handlers_triggered()
741 {
742 m_virtualMachine.DumpEEDmacHandlers();
743 }
744
on_actionAssemble_JAL_triggered()745 void QtDebugger::on_actionAssemble_JAL_triggered()
746 {
747 AssembleJAL();
748 }
749
on_actionReanalyse_ee_triggered()750 void QtDebugger::on_actionReanalyse_ee_triggered()
751 {
752 ReanalyzeEe();
753 }
754
on_actionFind_Functions_triggered()755 void QtDebugger::on_actionFind_Functions_triggered()
756 {
757 FindEeFunctions();
758 }
759
on_actionCascade_triggered()760 void QtDebugger::on_actionCascade_triggered()
761 {
762 ui->mdiArea->cascadeSubWindows();
763 }
764
on_actionTile_triggered()765 void QtDebugger::on_actionTile_triggered()
766 {
767 ui->mdiArea->tileSubWindows();
768 }
769
on_actionLayout_1024x768_triggered()770 void QtDebugger::on_actionLayout_1024x768_triggered()
771 {
772 Layout1024();
773 }
774
on_actionLayout_1280x1024_triggered()775 void QtDebugger::on_actionLayout_1280x1024_triggered()
776 {
777 Layout1280();
778 }
779
on_actionLayout_1600x1200_triggered()780 void QtDebugger::on_actionLayout_1600x1200_triggered()
781 {
782 Layout1600();
783 }
784
on_actionfind_word_value_triggered()785 void QtDebugger::on_actionfind_word_value_triggered()
786 {
787 FindWordValue(~0);
788 }
789
on_actionFind_Word_Half_Value_triggered()790 void QtDebugger::on_actionFind_Word_Half_Value_triggered()
791 {
792 FindWordValue(0xFFFF);
793 }
794
on_actionCall_Stack_triggered()795 void QtDebugger::on_actionCall_Stack_triggered()
796 {
797 GetCallStackWindow()->show();
798 static_cast<QWidget*>(GetCallStackWindow()->parent())->show();
799 static_cast<QWidget*>(GetCallStackWindow()->parent())->setFocus(Qt::ActiveWindowFocusReason);
800 }
801
on_actionFunctions_triggered()802 void QtDebugger::on_actionFunctions_triggered()
803 {
804 m_pFunctionsView->show();
805 m_pFunctionsView->setFocus(Qt::ActiveWindowFocusReason);
806 }
807
on_actionThreads_triggered()808 void QtDebugger::on_actionThreads_triggered()
809 {
810 static_cast<CThreadsViewWnd*>(m_threadsView->widget())->show();
811 m_threadsView->show();
812 m_threadsView->setFocus(Qt::ActiveWindowFocusReason);
813 }
814
on_actionView_Disassmebly_triggered()815 void QtDebugger::on_actionView_Disassmebly_triggered()
816 {
817 GetDisassemblyWindow()->show();
818 static_cast<QWidget*>(GetDisassemblyWindow()->parent())->show();
819 static_cast<QWidget*>(GetDisassemblyWindow()->parent())->setFocus(Qt::ActiveWindowFocusReason);
820 }
821
on_actionView_Registers_triggered()822 void QtDebugger::on_actionView_Registers_triggered()
823 {
824 GetRegisterViewWindow()->show();
825 static_cast<QWidget*>(GetRegisterViewWindow()->parent())->show();
826 static_cast<QWidget*>(GetRegisterViewWindow()->parent())->setFocus(Qt::ActiveWindowFocusReason);
827 }
828
on_actionMemory_triggered()829 void QtDebugger::on_actionMemory_triggered()
830 {
831 GetMemoryViewWindow()->show();
832 GetMemoryViewWindow()->setFocus(Qt::ActiveWindowFocusReason);
833 }
834
on_actionEmotionEngine_View_triggered()835 void QtDebugger::on_actionEmotionEngine_View_triggered()
836 {
837 ActivateView(DEBUGVIEW_EE);
838 }
839
on_actionVector_Unit_0_triggered()840 void QtDebugger::on_actionVector_Unit_0_triggered()
841 {
842 ActivateView(DEBUGVIEW_VU0);
843 }
844
on_actionVector_Unit_1_triggered()845 void QtDebugger::on_actionVector_Unit_1_triggered()
846 {
847 ActivateView(DEBUGVIEW_VU1);
848 }
849
on_actionIOP_View_triggered()850 void QtDebugger::on_actionIOP_View_triggered()
851 {
852 ActivateView(DEBUGVIEW_IOP);
853 }
854