40d8e13001e43d75b77774622a8d5023eb98ad9e
[clinton/Virtual-Jaguar-Rx.git] / src / debugger / callstackbrowser.cpp
1 //
2 // callstackbrowser.cpp - Call Stack
3 //
4 // by Jean-Paul Mari
5 //
6 // JPM = Jean-Paul Mari <djipi.mari@gmail.com>
7 //
8 // Who When (M/D/Y) What
9 // --- ------------ -----------------------------------------------------------
10 // JPM 08/31/2018 Created this file
11 // JPM 09/12/2018 Added a status bar and better status report
12 // JPM 10/20/2018 Added the return address information in the call stack
13 // JPM 08/09/2019 Prevent crash in case of call stack is out of range
14 // JPM 03/16/2020 Modified the layout window and added source filename from the called source line
15
16 // STILL TO DO:
17 // To set the information display at the right
18 // To use DWARF frame information?
19 // To check if call stack pointer is used (DWARF information?)
20 //
21
22 #include "debugger/callstackbrowser.h"
23 #include "memory.h"
24 #include "debugger/DBGManager.h"
25 #include "m68000/m68kinterface.h"
26 #include "settings.h"
27
28
29 //
30 CallStackBrowserWindow::CallStackBrowserWindow(QWidget * parent/*= 0*/) : QWidget(parent, Qt::Dialog),
31 #ifdef CS_LAYOUTTEXTS
32 text(new QTextBrowser),
33 #else
34 TableView(new QTableView),
35 model(new QStandardItemModel),
36 #endif
37 statusbar(new QStatusBar),
38 layout(new QVBoxLayout)
39 {
40 setWindowTitle(tr("Call Stack"));
41
42 // Set the font
43 QFont fixedFont("Lucida Console", 8, QFont::Normal);
44 fixedFont.setStyleHint(QFont::TypeWriter);
45
46 #ifdef CS_LAYOUTTEXTS
47 // Set original layout
48 text->setFont(fixedFont);
49 layout->addWidget(text);
50 #else
51 // Set the new layout with proper identation and readibility
52 model->setColumnCount(4);
53 model->setHeaderData(0, Qt::Horizontal, QObject::tr("Function"));
54 model->setHeaderData(1, Qt::Horizontal, QObject::tr("Line"));
55 model->setHeaderData(2, Qt::Horizontal, QObject::tr("Return address"));
56 model->setHeaderData(3, Qt::Horizontal, QObject::tr("Filename"));
57 // Information table
58 TableView->setModel(model);
59 TableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
60 TableView->setShowGrid(0);
61 TableView->setFont(fixedFont);
62 TableView->verticalHeader()->setDefaultSectionSize(TableView->verticalHeader()->minimumSectionSize());
63 TableView->verticalHeader()->setDefaultAlignment(Qt::AlignRight);
64 layout->addWidget(TableView);
65 #endif
66
67 // Status bar
68 layout->addWidget(statusbar);
69 setLayout(layout);
70 }
71
72
73 //
74 CallStackBrowserWindow::~CallStackBrowserWindow(void)
75 {
76 }
77
78
79 //
80 void CallStackBrowserWindow::RefreshContents(void)
81 {
82 char msg[1024];
83 size_t Error = CS_NOERROR;
84 DBGstatus FilenameStatus;
85 unsigned int a6, Sa6, ret;
86 char *Name;
87 size_t NumError = 0;
88 #ifdef CS_LAYOUTTEXTS
89 QString CallStack;
90 char string[1024];
91 #else
92 int NbRaw = 0;
93 QString FunctionName;
94 #endif
95
96 if (isVisible())
97 {
98 #ifndef CS_LAYOUTTEXTS
99 model->setRowCount(0);
100 #endif
101 if ((a6 = m68k_get_reg(NULL, M68K_REG_A6)) && DBGManager_GetType())
102 {
103 while ((Sa6 = a6) && !NumError)
104 {
105 if ((Sa6 >= (m68k_get_reg(NULL, M68K_REG_SP) - 4)) && (Sa6 < vjs.DRAM_size))
106 {
107 a6 = GET32(jaguarMainRAM, Sa6);
108 ret = GET32(jaguarMainRAM, Sa6 + 4);
109 #ifdef CS_LAYOUTTEXTS
110 sprintf(string, "0x%06X | Ret: 0x%06X | From: %s - 0x%06X | Line: %s", Sa6, ret, (Name = DBGManager_GetFunctionName(ret)), (unsigned int)DBGManager_GetAdrFromSymbolName(Name), DBGManager_GetLineSrcFromAdr(ret, DBG_NO_TAG));
111 CallStack += QString(string);
112 if (a6)
113 {
114 CallStack += QString("<br>");
115 }
116 #else
117 // insert line
118 model->insertRow(NbRaw);
119 // display the function name
120 model->setItem(NbRaw, 0, new QStandardItem(QString("%1").arg((Name = DBGManager_GetFunctionName(ret)) ? Name : "(N/A)")));
121 // display the called line
122 FunctionName = QString(Name = DBGManager_GetLineSrcFromAdr(ret, DBG_NO_TAG));
123 //FunctionName.replace("&nbsp;", " ");
124 FunctionName = FunctionName.trimmed();
125 model->setItem(NbRaw, 1, new QStandardItem(QString("%1").arg(Name ? FunctionName : "(N/A)")));
126 // display the return address
127 sprintf(msg, "0x%06X", ret);
128 model->setItem(NbRaw, 2, new QStandardItem(QString("%1").arg(msg)));
129 // display the source filename from called source line
130 model->setItem(NbRaw++, 3, new QStandardItem(QString("%1").arg(((Name = DBGManager_GetFullSourceFilenameFromAdr(ret, &FilenameStatus)) && !FilenameStatus) ? Name : "(N/A)")));
131 #endif
132 }
133 else
134 {
135 NumError = 0x1;
136 }
137 }
138 #ifdef CS_LAYOUTTEXTS
139 text->clear();
140 text->setText(CallStack);
141 #endif
142 switch (NumError)
143 {
144 case 0:
145 sprintf(msg, "Ready");
146 Error = CS_NOERROR;
147 break;
148
149 case 0x1:
150 sprintf(msg, "Call Stack out of range");
151 Error = CS_ERROR;
152 break;
153
154 default:
155 sprintf(msg, "Call Stack in limbo");
156 Error = CS_WARNING;
157 break;
158 }
159 }
160 else
161 {
162 sprintf(msg, "Call Stack not available");
163 Error = CS_NOCALLSTACK;
164 #ifdef CS_LAYOUTTEXTS
165 text->clear();
166 #endif
167 }
168
169 // Display status bar
170 if (Error)
171 {
172 if ((Error & CS_WARNING))
173 {
174 statusbar->setStyleSheet("background-color: lightyellow; font: bold");
175 }
176 else
177 {
178 statusbar->setStyleSheet("background-color: tomato; font: bold");
179 }
180 }
181 else
182 {
183 statusbar->setStyleSheet("background-color: lightgreen; font: bold");
184 }
185 statusbar->showMessage(QString(msg));
186 }
187 }
188
189
190 //
191 void CallStackBrowserWindow::keyPressEvent(QKeyEvent * e)
192 {
193 if (e->key() == Qt::Key_Escape)
194 {
195 hide();
196 }
197 }
198
199