core: Fix libdwarf and Qt build failure
[clinton/Virtual-Jaguar-Rx.git] / src / debugger / localbrowser.cpp
CommitLineData
0203b5fd
JPM
1//\r
2// localbrowser.cpp - Local variables\r
3//\r
4// by Jean-Paul Mari\r
5//\r
6// JPM = Jean-Paul Mari <djipi.mari@gmail.com>\r
c4fe5864 7// RG = Richard Goedeken\r
0203b5fd
JPM
8//\r
9// Who When What\r
10// --- ---------- -----------------------------------------------------------\r
11// JPM 11/03/2017 Created this file\r
6642f781 12// JPM Sept./2018 Added a status bar and better status report, and set information values in a tab\r
c4fe5864 13// RG Jan./2021 Linux build fixes\r
d0774971 14// JPM May/2021 Display the structure's members\r
2b91c435
JPM
15//\r
16\r
17// STILL TO DO:\r
18// Feature to list the pointer(s) in the code using the allocation\r
19// To set the information display at the right\r
20// To support the array\r
d0774971 21// To support the union\r
6642f781
JPM
22// To support the static variables\r
23// To add a filter\r
0203b5fd
JPM
24//\r
25\r
c89f8ff7 26#include <stdlib.h>\r
0203b5fd
JPM
27\r
28#include "debugger/localbrowser.h"\r
29#include "memory.h"\r
30#include "debugger/DBGManager.h"\r
31#include "settings.h"\r
32#include "m68000/m68kinterface.h"\r
33\r
34\r
35// \r
36LocalBrowserWindow::LocalBrowserWindow(QWidget * parent/*= 0*/) : QWidget(parent, Qt::Dialog),\r
2b91c435 37layout(new QVBoxLayout),\r
d0774971 38TableView(new QTreeView),\r
2b91c435 39model(new QStandardItemModel),\r
2b91c435 40NbLocal(0),\r
d0774971 41FuncName(NULL),\r
2b91c435
JPM
42LocalInfo(NULL),\r
43statusbar(new QStatusBar)\r
0203b5fd 44{\r
2b91c435 45 setWindowTitle(tr("Locals"));\r
d0774971 46#ifdef LOCAL_FONTS\r
2b91c435 47 // Set the font\r
0203b5fd 48 QFont fixedFont("Lucida Console", 8, QFont::Normal);\r
0203b5fd 49 fixedFont.setStyleHint(QFont::TypeWriter);\r
d0774971 50#endif\r
2b91c435
JPM
51 // Set the new layout with proper identation and readibility\r
52 model->setColumnCount(3);\r
53 model->setHeaderData(0, Qt::Horizontal, QObject::tr("Name"));\r
54 model->setHeaderData(1, Qt::Horizontal, QObject::tr("Value"));\r
55 model->setHeaderData(2, Qt::Horizontal, QObject::tr("Type"));\r
56 // Information table\r
57 TableView->setModel(model);\r
58 TableView->setEditTriggers(QAbstractItemView::NoEditTriggers);\r
d0774971 59#ifdef LOCAL_FONTS\r
2b91c435 60 TableView->setFont(fixedFont);\r
2b91c435 61#endif\r
d0774971 62 layout->addWidget(TableView);\r
2b91c435
JPM
63\r
64 // Status bar\r
65 layout->addWidget(statusbar);\r
66 setLayout(layout);\r
0203b5fd
JPM
67}\r
68\r
69\r
70//\r
71LocalBrowserWindow::~LocalBrowserWindow(void)\r
72{\r
73 free(LocalInfo);\r
0203b5fd
JPM
74}\r
75\r
76\r
d0774971
JPM
77// Get the local variables information\r
78// Return true for a new local variables set\r
0203b5fd
JPM
79bool LocalBrowserWindow::UpdateInfos(void)\r
80{\r
81 size_t Adr;\r
82 char *Ptr;\r
83\r
d0774971
JPM
84 // get number of local variables located in the M68K PC address\r
85 if ((NbLocal = DBGManager_GetNbVariables(Adr = m68k_get_reg(NULL, M68K_REG_PC))))\r
0203b5fd 86 {\r
d0774971
JPM
87 // get function name from the M68K PC address\r
88 if ((Ptr = DBGManager_GetFunctionName(Adr)))\r
0203b5fd 89 {\r
d0774971
JPM
90 // avoid to read the same information in case of the function has not changed\r
91 if (!FuncName || strcmp(FuncName, Ptr))\r
0203b5fd 92 {\r
d0774971
JPM
93 // function is different\r
94 FuncName = Ptr;\r
95 if (LocalInfo = (S_LocalInfo*)realloc(LocalInfo, (sizeof(S_LocalInfo) * NbLocal)))\r
0203b5fd 96 {\r
d0774971 97 for (size_t i = 0; i < NbLocal; i++)\r
0203b5fd 98 {\r
d0774971
JPM
99 // get local variable name and his information\r
100 if ((LocalInfo[i].PtrVariable = DBGManager_GetInfosVariable(Adr, i + 1)))\r
47b6ecae 101 {\r
d0774971
JPM
102 LocalInfo[i].Adr = 0;\r
103 LocalInfo[i].PtrCPURegisterName = NULL;\r
47b6ecae 104 }\r
0203b5fd
JPM
105 }\r
106 }\r
0203b5fd 107\r
d0774971
JPM
108 return true;\r
109 }\r
110 else\r
111 {\r
112 return false;\r
113 }\r
0203b5fd
JPM
114 }\r
115 }\r
116\r
d0774971 117 FuncName = NULL;\r
0203b5fd
JPM
118\r
119 return false;\r
120}\r
121\r
122\r
d0774971
JPM
123// Prepare a complete row based on the variable information\r
124// The row will append rows if necessary\r
125QList<QStandardItem *> LocalBrowserWindow::prepareRow(void* Info)\r
126{\r
127 // set the list\r
128 QList<QStandardItem *> ptrRow = { new QStandardItem(((S_VariablesStruct*)Info)->PtrName), new QStandardItem(""), new QStandardItem(((S_VariablesStruct*)Info)->PtrTypeName) };\r
129\r
130 // check if variable has additional variables (such as structure)\r
131 if (size_t nb = ((S_VariablesStruct*)Info)->NbTabVariables)\r
132 {\r
133 for (size_t i = 0; i < nb; i++)\r
134 {\r
135 ptrRow.first()->appendRow(prepareRow(((S_VariablesStruct*)Info)->TabVariables[i]));\r
136 }\r
137 }\r
138\r
139 // return the list\r
140 return ptrRow;\r
141}\r
142\r
143\r
144// Set the values of each line in accordance of the rows created from prepareRow() function\r
145void LocalBrowserWindow::setValueRow(QStandardItem *Row, size_t Adr, char* Value, void* Info)\r
146{\r
147 QStandardItem *child = Row->child(0, 1);\r
148 if (child)\r
149 {\r
150 // check if variable has additional variables list (such as structure)\r
151 if (size_t nb = ((S_VariablesStruct*)Info)->NbTabVariables)\r
152 {\r
153 // get the pointer's value\r
154 Adr = GET32(jagMemSpace, Adr);\r
155\r
156 for (size_t i = 0; i < nb; i++)\r
157 {\r
158 // do not display arrays\r
159 if (!((((S_VariablesStruct*)Info)->TabVariables[i]->TypeTag & DBG_TAG_TYPE_array)))\r
160 {\r
161 // set value in the row\r
162 Value = DBGManager_GetVariableValueFromAdr(Adr + ((S_VariablesStruct*)Info)->TabVariables[i]->Offset, ((S_VariablesStruct*)Info)->TabVariables[i]->TypeEncoding, ((S_VariablesStruct*)Info)->TabVariables[i]->TypeByteSize);\r
163 child = Row->child((int)i, 1);\r
164 child->setText(QString("%1").arg(Value));\r
165 setValueRow(child, Adr + ((S_VariablesStruct*)Info)->TabVariables[i]->Offset, Value, (void*)((S_VariablesStruct*)Info)->TabVariables[i]);\r
166 }\r
167 }\r
168 }\r
169 }\r
170}\r
171\r
172\r
173// Refresh the local and/or parameters contents list\r
0203b5fd
JPM
174void LocalBrowserWindow::RefreshContents(void)\r
175{\r
2b91c435 176 size_t Error = LOCAL_NOERROR;\r
0203b5fd 177 QString Local;\r
2b91c435
JPM
178 QString MSG;\r
179 char Value1[100];\r
0203b5fd 180 char *PtrValue;\r
0203b5fd 181\r
d0774971 182 // local variables may come from M68K registers\r
e857856a
JPM
183 const char *CPURegName[] = { "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7" };\r
184\r
d0774971 185 // refresh only if local's window is displayed\r
0203b5fd
JPM
186 if (isVisible())\r
187 {\r
d0774971 188 // get local's information\r
0203b5fd
JPM
189 if (UpdateInfos())\r
190 {\r
d0774971
JPM
191 // erase the previous variables list\r
192 model->setRowCount(0);\r
193\r
194 // loop on the locals found\r
0203b5fd
JPM
195 for (size_t i = 0; i < NbLocal; i++)\r
196 {\r
d0774971
JPM
197 // check variable's name validity\r
198 if (((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->PtrName)\r
0203b5fd 199 {\r
d0774971
JPM
200 // insert the row\r
201 model->appendRow(prepareRow(LocalInfo[i].PtrVariable));\r
0203b5fd 202\r
d0774971
JPM
203 // check if the local variable is use by the code\r
204 if (((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->Op)\r
205 {\r
206 // local or parameters variables\r
207 if (((((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->Op >= DBG_OP_breg0) && (((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->Op <= DBG_OP_breg31)) || (((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->Op == DBG_OP_fbreg))\r
0203b5fd 208 {\r
d0774971
JPM
209 // get variable's address\r
210 LocalInfo[i].Adr = m68k_get_reg(NULL, M68K_REG_A6) + ((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->Offset;\r
211 // check variable's parameter op\r
212 if ((((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->Op == DBG_OP_fbreg))\r
2b91c435 213 {\r
d0774971 214 LocalInfo[i].Adr += 8;\r
2b91c435 215 }\r
0203b5fd
JPM
216 }\r
217 else\r
218 {\r
d0774971
JPM
219 // variable type from CPU register\r
220 if ((((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->Op >= DBG_OP_reg0) && (((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->Op <= DBG_OP_reg31))\r
221 {\r
222 // set color text for a register type variable\r
223 model->item((int)i, 0)->setForeground(QColor(0, 0, 0xfe));\r
224 model->item((int)i, 1)->setForeground(QColor(0, 0, 0xfe));\r
225 model->item((int)i, 2)->setForeground(QColor(0, 0, 0xfe));\r
226 // get the register's name\r
227 LocalInfo[i].PtrCPURegisterName = (char *)CPURegName[(((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->Op - DBG_OP_reg0)];\r
228 }\r
0203b5fd
JPM
229 }\r
230 }\r
231 else\r
232 {\r
d0774971
JPM
233 // set color text for unused variable (no need to set it for the value's field as no values will be displayed)\r
234 model->item((int)i, 0)->setForeground(QColor(0xc8, 0xc8, 0xc8));\r
235 model->item((int)i, 2)->setForeground(QColor(0xc8, 0xc8, 0xc8));\r
0203b5fd 236 }\r
d0774971
JPM
237 }\r
238 }\r
239 }\r
0203b5fd 240\r
d0774971
JPM
241 // set the values in the fields\r
242 if (NbLocal)\r
243 {\r
244 // loop on the locals found\r
245 for (size_t i = 0; i < NbLocal; i++)\r
246 {\r
247 // variable's address must fit in RAM\r
248 if ((LocalInfo[i].Adr >= 4) && (LocalInfo[i].Adr < vjs.DRAM_size))\r
249 {\r
250 // get the variable's value\r
251 PtrValue = DBGManager_GetVariableValueFromAdr(LocalInfo[i].Adr, ((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->TypeEncoding, ((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->TypeByteSize);\r
252 }\r
253 else\r
254 {\r
255 // check CPU register's type variable\r
256 if (LocalInfo[i].PtrCPURegisterName)\r
0203b5fd 257 {\r
d0774971
JPM
258 // get the value from register\r
259 memset(Value1, 0, sizeof(Value1));\r
260 sprintf(Value1, "0x%x", m68k_get_reg(NULL, (m68k_register_t)((size_t)M68K_REG_D0 + (((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->Op - DBG_OP_reg0))));\r
261 PtrValue = Value1;\r
0203b5fd
JPM
262 }\r
263 else\r
264 {\r
d0774971
JPM
265 // no value can be found\r
266 PtrValue = NULL;\r
0203b5fd 267 }\r
d0774971
JPM
268 }\r
269\r
270 // do not display arrays\r
271 if (!(((S_VariablesStruct*)LocalInfo[i].PtrVariable)->TypeTag & DBG_TAG_TYPE_array))\r
272 {\r
273 // set the local's variable value\r
274 model->item((int)i, 1)->setText(QString("%1").arg(PtrValue));\r
275 setValueRow(model->item((int)i), LocalInfo[i].Adr, PtrValue, (S_VariablesStruct*)(LocalInfo[i].PtrVariable));\r
0203b5fd
JPM
276 }\r
277 }\r
278\r
2b91c435 279 MSG += QString("Ready");\r
0203b5fd
JPM
280 }\r
281 else\r
282 {\r
d0774971
JPM
283 // erase the previous variables list\r
284 model->setRowCount(0);\r
285\r
2b91c435
JPM
286 // No locals\r
287 MSG += QString("No locals");\r
288 Error = LOCAL_NOLOCALS;\r
2b91c435
JPM
289 }\r
290\r
d0774971 291 // display status bar\r
2b91c435
JPM
292 if (Error)\r
293 {\r
294 if ((Error & LOCAL_WARNING))\r
295 {\r
296 statusbar->setStyleSheet("background-color: lightyellow; font: bold");\r
297 }\r
298 else\r
299 {\r
300 statusbar->setStyleSheet("background-color: tomato; font: bold");\r
301 }\r
302 }\r
303 else\r
304 {\r
305 statusbar->setStyleSheet("background-color: lightgreen; font: bold");\r
0203b5fd 306 }\r
2b91c435 307 statusbar->showMessage(MSG);\r
0203b5fd
JPM
308 }\r
309}\r
310\r
311\r
d0774971 312// Handle keyboard actions\r
0203b5fd
JPM
313void LocalBrowserWindow::keyPressEvent(QKeyEvent * e)\r
314{\r
d0774971 315 // close / hide the window\r
0203b5fd 316 if (e->key() == Qt::Key_Escape)\r
a2dfb8e5 317 {\r
0203b5fd 318 hide();\r
a2dfb8e5 319 }\r
0203b5fd 320}\r