1 // copyright (c) 2020-2021 hors<horsicq@gmail.com>
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9
10 // The above copyright notice and this permission notice shall be included in all
11 // copies or substantial portions of the Software.
12
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20 //
21 #include "xmemorymapwidget.h"
22 #include "ui_xmemorymapwidget.h"
23
XMemoryMapWidget(QWidget * pParent)24 XMemoryMapWidget::XMemoryMapWidget(QWidget *pParent) :
25 XShortcutsWidget(pParent),
26 ui(new Ui::XMemoryMapWidget)
27 {
28 ui->setupUi(this);
29
30 g_mode=XLineEditHEX::MODE_16;
31 g_bLockHex=false;
32 }
33
~XMemoryMapWidget()34 XMemoryMapWidget::~XMemoryMapWidget()
35 {
36 delete ui;
37 }
38
setData(QIODevice * pDevice,XBinary::FT fileType,QString sSignaturesPath)39 void XMemoryMapWidget::setData(QIODevice *pDevice, XBinary::FT fileType, QString sSignaturesPath)
40 {
41 this->g_pDevice=pDevice;
42
43 XHexView::OPTIONS options={};
44 options.sSignaturesPath=sSignaturesPath;
45
46 ui->widgetHex->setData(pDevice,options);
47
48 QSet<XBinary::FT> stFileType=XBinary::getFileTypes(pDevice,true);
49 stFileType.insert(XBinary::FT_COM);
50 QList<XBinary::FT> listFileTypes=XBinary::_getFileTypeListFromSet(stFileType);
51
52 XFormats::setFileTypeComboBox(ui->comboBoxType,&listFileTypes,fileType);
53
54 updateMemoryMap();
55 }
56
goToOffset(qint64 nOffset)57 void XMemoryMapWidget::goToOffset(qint64 nOffset)
58 {
59 ui->lineEditFileOffset->setModeValue(g_mode,nOffset);
60 }
61
setShortcuts(XShortcuts * pShortcuts)62 void XMemoryMapWidget::setShortcuts(XShortcuts *pShortcuts)
63 {
64 ui->widgetHex->setShortcuts(pShortcuts);
65 XShortcutsWidget::setShortcuts(pShortcuts);
66 }
67
on_comboBoxType_currentIndexChanged(int nIndex)68 void XMemoryMapWidget::on_comboBoxType_currentIndexChanged(int nIndex)
69 {
70 Q_UNUSED(nIndex)
71
72 updateMemoryMap();
73 }
74
on_radioButtonFileOffset_toggled(bool bChecked)75 void XMemoryMapWidget::on_radioButtonFileOffset_toggled(bool bChecked)
76 {
77 Q_UNUSED(bChecked)
78
79 adjust(false);
80 }
81
on_radioButtonVirtualAddress_toggled(bool bChecked)82 void XMemoryMapWidget::on_radioButtonVirtualAddress_toggled(bool bChecked)
83 {
84 Q_UNUSED(bChecked)
85
86 adjust(false);
87 }
88
on_radioButtonRelativeVirtualAddress_toggled(bool bChecked)89 void XMemoryMapWidget::on_radioButtonRelativeVirtualAddress_toggled(bool bChecked)
90 {
91 Q_UNUSED(bChecked)
92
93 adjust(false);
94 }
95
updateMemoryMap()96 void XMemoryMapWidget::updateMemoryMap()
97 {
98 #if QT_VERSION >= 0x050300
99 const QSignalBlocker blocker1(ui->lineEditFileOffset);
100 const QSignalBlocker blocker2(ui->lineEditVirtualAddress);
101 const QSignalBlocker blocker3(ui->lineEditRelativeVirtualAddress);
102 const QSignalBlocker blocker4(ui->tableViewMemoryMap);
103 const QSignalBlocker blocker5(ui->pageHex);
104 #else
105 const bool bBlocked1=ui->lineEditFileOffset->blockSignals(true);
106 const bool bBlocked2=ui->lineEditVirtualAddress->blockSignals(true);
107 const bool bBlocked3=ui->lineEditRelativeVirtualAddress->blockSignals(true);
108 const bool bBlocked4=ui->tableViewMemoryMap->blockSignals(true);
109 const bool bBlocked5=ui->pageHex->blockSignals(true);
110 #endif
111
112 XBinary::FT fileType=(XBinary::FT)(ui->comboBoxType->currentData().toInt());
113
114 g_memoryMap=XFormats::getMemoryMap(fileType,g_pDevice);
115
116 ui->lineEditArch->setText(g_memoryMap.sArch);
117 ui->lineEditMode->setText(XBinary::modeIdToString(g_memoryMap.mode));
118 ui->lineEditEndianness->setText(XBinary::endiannessToString(g_memoryMap.bIsBigEndian));
119
120 ui->radioButtonFileOffset->setChecked(true);
121
122 ui->lineEditFileOffset->setValue((quint32)0);
123
124 XBinary::MODE _mode=XBinary::getWidthModeFromMemoryMap(&g_memoryMap);
125
126 if (_mode==XBinary::MODE_8) g_mode=XLineEditHEX::MODE_8;
127 else if (_mode==XBinary::MODE_16) g_mode=XLineEditHEX::MODE_16;
128 else if (_mode==XBinary::MODE_32) g_mode=XLineEditHEX::MODE_32;
129 else if (_mode==XBinary::MODE_64) g_mode=XLineEditHEX::MODE_64;
130
131 QAbstractItemModel *pOldModel=ui->tableViewMemoryMap->model();
132
133 int nNumberOfRecords=g_memoryMap.listRecords.count();
134
135 QStandardItemModel *pModel=new QStandardItemModel(nNumberOfRecords,4,this);
136
137 pModel->setHeaderData(0,Qt::Horizontal,tr("Offset"));
138 pModel->setHeaderData(1,Qt::Horizontal,tr("Address"));
139 pModel->setHeaderData(2,Qt::Horizontal,tr("Size"));
140 pModel->setHeaderData(3,Qt::Horizontal,tr("Name"));
141
142 // QColor colDisabled=QWidget::palette().color(QPalette::Window);
143
144 for(int i=0;i<nNumberOfRecords;i++)
145 {
146 // bool bIsVirtual=g_memoryMap.listRecords.at(i).bIsVirtual;
147
148 QStandardItem *pItemOffset=new QStandardItem;
149
150 // if(bIsVirtual)
151 // {
152 // pItemOffset->setBackground(colDisabled);
153 // }
154
155 pItemOffset->setData(g_memoryMap.listRecords.at(i).nOffset,Qt::UserRole+0);
156 pItemOffset->setData(g_memoryMap.listRecords.at(i).nAddress,Qt::UserRole+1);
157 pItemOffset->setData(g_memoryMap.listRecords.at(i).nSize,Qt::UserRole+2);
158
159 pItemOffset->setText(XLineEditHEX::getFormatString(g_mode,g_memoryMap.listRecords.at(i).nOffset));
160 pModel->setItem(i,0,pItemOffset);
161
162 QStandardItem *pItemAddress=new QStandardItem;
163
164 // if(bIsVirtual)
165 // {
166 // pItemAddress->setBackground(colDisabled);
167 // }
168
169 pItemAddress->setText(XLineEditHEX::getFormatString(g_mode,g_memoryMap.listRecords.at(i).nAddress));
170 pModel->setItem(i,1,pItemAddress);
171
172 QStandardItem *pItemSize=new QStandardItem;
173
174 // if(bIsVirtual)
175 // {
176 // pItemSize->setBackground(colDisabled);
177 // }
178
179 pItemSize->setText(XLineEditHEX::getFormatString(g_mode,g_memoryMap.listRecords.at(i).nSize));
180 pModel->setItem(i,2,pItemSize);
181
182
183 QStandardItem *pItemName=new QStandardItem;
184
185 // if(bIsVirtual)
186 // {
187 // pItemName->setBackground(colDisabled);
188 // }
189
190 pItemName->setText(g_memoryMap.listRecords.at(i).sName);
191 pModel->setItem(i,3,pItemName);
192 }
193
194 ui->tableViewMemoryMap->setModel(pModel);
195
196 delete pOldModel;
197
198 ui->tableViewMemoryMap->horizontalHeader()->setSectionResizeMode(0,QHeaderView::Interactive);
199 ui->tableViewMemoryMap->horizontalHeader()->setSectionResizeMode(1,QHeaderView::Interactive);
200 ui->tableViewMemoryMap->horizontalHeader()->setSectionResizeMode(2,QHeaderView::Interactive);
201 ui->tableViewMemoryMap->horizontalHeader()->setSectionResizeMode(3,QHeaderView::Stretch);
202
203 qint32 nColumnSize=XLineEditHEX::getWidthFromMode(this,g_mode);
204
205 ui->tableViewMemoryMap->setColumnWidth(0,nColumnSize);
206 ui->tableViewMemoryMap->setColumnWidth(1,nColumnSize);
207 ui->tableViewMemoryMap->setColumnWidth(2,nColumnSize);
208
209 connect(ui->tableViewMemoryMap->selectionModel(),SIGNAL(selectionChanged(QItemSelection, QItemSelection)),this,SLOT(on_tableViewSelection(QItemSelection, QItemSelection)));
210 connect(ui->widgetHex,SIGNAL(cursorChanged(qint64)),this,SLOT(onHexCursorChanged(qint64)));
211
212 adjust(true);
213
214 #if QT_VERSION < 0x050300
215 ui->lineEditFileOffset->blockSignals(bBlocked1);
216 ui->lineEditVirtualAddress->blockSignals(bBlocked2);
217 ui->lineEditRelativeVirtualAddress->blockSignals(bBlocked3);
218 ui->tableViewMemoryMap->blockSignals(bBlocked4);
219 ui->pageHex->blockSignals(bBlocked5);
220 #endif
221 }
222
adjust(bool bInit)223 void XMemoryMapWidget::adjust(bool bInit)
224 {
225 #if QT_VERSION >= 0x050300
226 const QSignalBlocker blocker1(ui->lineEditFileOffset);
227 const QSignalBlocker blocker2(ui->lineEditVirtualAddress);
228 const QSignalBlocker blocker3(ui->lineEditRelativeVirtualAddress);
229 const QSignalBlocker blocker4(ui->tableViewMemoryMap);
230 const QSignalBlocker blocker5(ui->pageHex);
231 #else
232 const bool bBlocked1=ui->lineEditFileOffset->blockSignals(true);
233 const bool bBlocked2=ui->lineEditVirtualAddress->blockSignals(true);
234 const bool bBlocked3=ui->lineEditRelativeVirtualAddress->blockSignals(true);
235 const bool bBlocked4=ui->tableViewMemoryMap->blockSignals(true);
236 const bool bBlocked5=ui->pageHex->blockSignals(true);
237 #endif
238
239 int nTableViewIndex=-1;
240
241 quint64 nFileOffset=ui->lineEditFileOffset->getValue();
242 quint64 nVirtualAddress=ui->lineEditVirtualAddress->getValue();
243 quint64 nRelativeVirtualAddress=ui->lineEditRelativeVirtualAddress->getValue();
244
245 if(ui->radioButtonFileOffset->isChecked())
246 {
247 ui->lineEditFileOffset->setReadOnly(false);
248 ui->lineEditVirtualAddress->setReadOnly(true);
249 ui->lineEditRelativeVirtualAddress->setReadOnly(true);
250
251 nVirtualAddress=XBinary::offsetToAddress(&g_memoryMap,nFileOffset);
252 nRelativeVirtualAddress=XBinary::offsetToRelAddress(&g_memoryMap,nFileOffset);
253
254 XBinary::_MEMORY_RECORD memoryRecord=XBinary::getMemoryRecordByOffset(&g_memoryMap,nFileOffset);
255
256 if(memoryRecord.nSize)
257 {
258 nTableViewIndex=memoryRecord.nIndex;
259 }
260
261 if(bInit)
262 {
263 ui->lineEditFileOffset->setModeValue(g_mode,nFileOffset);
264 }
265
266 ui->lineEditVirtualAddress->setModeValue(g_mode,nVirtualAddress);
267 ui->lineEditRelativeVirtualAddress->setModeValue(g_mode,nRelativeVirtualAddress);
268 }
269 else if(ui->radioButtonVirtualAddress->isChecked())
270 {
271 ui->lineEditFileOffset->setReadOnly(true);
272 ui->lineEditVirtualAddress->setReadOnly(false);
273 ui->lineEditRelativeVirtualAddress->setReadOnly(true);
274
275 nFileOffset=XBinary::addressToOffset(&g_memoryMap,nVirtualAddress);
276 nRelativeVirtualAddress=XBinary::addressToRelAddress(&g_memoryMap,nVirtualAddress);
277
278 XBinary::_MEMORY_RECORD memoryRecord=XBinary::getMemoryRecordByAddress(&g_memoryMap,nVirtualAddress);
279
280 if(memoryRecord.nSize)
281 {
282 nTableViewIndex=memoryRecord.nIndex;
283 }
284
285 if(bInit)
286 {
287 ui->lineEditVirtualAddress->setModeValue(g_mode,nVirtualAddress);
288 }
289
290 ui->lineEditFileOffset->setModeValue(g_mode,nFileOffset);
291 ui->lineEditRelativeVirtualAddress->setModeValue(g_mode,nRelativeVirtualAddress);
292 }
293 else if(ui->radioButtonRelativeVirtualAddress->isChecked())
294 {
295 ui->lineEditFileOffset->setReadOnly(true);
296 ui->lineEditVirtualAddress->setReadOnly(true);
297 ui->lineEditRelativeVirtualAddress->setReadOnly(false);
298
299 nFileOffset=XBinary::relAddressToOffset(&g_memoryMap,nRelativeVirtualAddress);
300 nVirtualAddress=XBinary::relAddressToAddress(&g_memoryMap,nRelativeVirtualAddress);
301
302 XBinary::_MEMORY_RECORD memoryRecord=XBinary::getMemoryRecordByRelAddress(&g_memoryMap,nRelativeVirtualAddress);
303
304 if(memoryRecord.nSize)
305 {
306 nTableViewIndex=memoryRecord.nIndex;
307 }
308
309 if(bInit)
310 {
311 ui->lineEditRelativeVirtualAddress->setModeValue(g_mode,nRelativeVirtualAddress);
312 }
313
314 ui->lineEditFileOffset->setModeValue(g_mode,nFileOffset);
315 ui->lineEditVirtualAddress->setModeValue(g_mode,nVirtualAddress);
316 }
317
318 if(nTableViewIndex!=-1)
319 {
320 ui->tableViewMemoryMap->setCurrentIndex(ui->tableViewMemoryMap->model()->index(nTableViewIndex,0));
321 }
322
323 _goToOffset(nFileOffset,1);
324
325 #if QT_VERSION < 0x050300
326 ui->lineEditFileOffset->blockSignals(bBlocked1);
327 ui->lineEditVirtualAddress->blockSignals(bBlocked2);
328 ui->lineEditRelativeVirtualAddress->blockSignals(bBlocked3);
329 ui->tableViewMemoryMap->blockSignals(bBlocked4);
330 ui->pageHex->blockSignals(bBlocked5);
331 #endif
332 }
333
on_lineEditFileOffset_textChanged(const QString & sText)334 void XMemoryMapWidget::on_lineEditFileOffset_textChanged(const QString &sText)
335 {
336 Q_UNUSED(sText)
337
338 adjust(false);
339 }
340
on_lineEditVirtualAddress_textChanged(const QString & sText)341 void XMemoryMapWidget::on_lineEditVirtualAddress_textChanged(const QString &sText)
342 {
343 Q_UNUSED(sText)
344
345 adjust(false);
346 }
347
on_lineEditRelativeVirtualAddress_textChanged(const QString & sText)348 void XMemoryMapWidget::on_lineEditRelativeVirtualAddress_textChanged(const QString &sText)
349 {
350 Q_UNUSED(sText)
351
352 adjust(false);
353 }
354
on_tableViewSelection(const QItemSelection & selected,const QItemSelection & deselected)355 void XMemoryMapWidget::on_tableViewSelection(const QItemSelection &selected, const QItemSelection &deselected)
356 {
357 Q_UNUSED(selected)
358 Q_UNUSED(deselected)
359
360 #if QT_VERSION >= 0x050300
361 const QSignalBlocker blocker1(ui->lineEditFileOffset);
362 const QSignalBlocker blocker2(ui->lineEditVirtualAddress);
363 const QSignalBlocker blocker3(ui->lineEditRelativeVirtualAddress);
364 const QSignalBlocker blocker4(ui->tableViewMemoryMap);
365 const QSignalBlocker blocker5(ui->pageHex);
366 #else
367 const bool bBlocked1=ui->lineEditFileOffset->blockSignals(true);
368 const bool bBlocked2=ui->lineEditVirtualAddress->blockSignals(true);
369 const bool bBlocked3=ui->lineEditRelativeVirtualAddress->blockSignals(true);
370 const bool bBlocked4=ui->tableViewMemoryMap->blockSignals(true);
371 const bool bBlocked5=ui->pageHex->blockSignals(true);
372 #endif
373
374 QItemSelectionModel *pSelectionModel=ui->tableViewMemoryMap->selectionModel();
375
376 if(pSelectionModel)
377 {
378 QModelIndexList listIndexes=pSelectionModel->selectedRows(0);
379
380 if(listIndexes.count())
381 {
382 qint64 nFileOffset=listIndexes.at(0).data(Qt::UserRole+0).toLongLong();
383 qint64 nVirtualAddress=listIndexes.at(0).data(Qt::UserRole+1).toLongLong();
384 qint64 nSize=listIndexes.at(0).data(Qt::UserRole+2).toLongLong();
385
386 qint64 nRelativeVirtualAddress=XBinary::addressToRelAddress(&g_memoryMap,nVirtualAddress);
387
388 ui->lineEditFileOffset->setModeValue(g_mode,nFileOffset);
389 ui->lineEditVirtualAddress->setModeValue(g_mode,nVirtualAddress);
390 ui->lineEditRelativeVirtualAddress->setModeValue(g_mode,nRelativeVirtualAddress);
391
392 _goToOffset(nFileOffset,nSize);
393 }
394 }
395
396 #if QT_VERSION < 0x050300
397 ui->lineEditFileOffset->blockSignals(bBlocked1);
398 ui->lineEditVirtualAddress->blockSignals(bBlocked2);
399 ui->lineEditRelativeVirtualAddress->blockSignals(bBlocked3);
400 ui->tableViewMemoryMap->blockSignals(bBlocked4);
401 ui->pageHex->blockSignals(bBlocked5);
402 #endif
403 }
404
_goToOffset(qint64 nOffset,qint64 nSize)405 void XMemoryMapWidget::_goToOffset(qint64 nOffset, qint64 nSize)
406 {
407 if(!g_bLockHex)
408 {
409 if(nSize==0)
410 {
411 nSize=1;
412 }
413
414 if(XBinary::isOffsetValid(&g_memoryMap,nOffset))
415 {
416 ui->stackedWidgetHex->setCurrentIndex(0);
417
418 ui->widgetHex->goToOffset(nOffset);
419 ui->widgetHex->setSelection(nOffset,nSize);
420 ui->widgetHex->reload();
421 }
422 else
423 {
424 // Invalid offset
425 ui->stackedWidgetHex->setCurrentIndex(1);
426 }
427 }
428 }
429
onHexCursorChanged(qint64 nOffset)430 void XMemoryMapWidget::onHexCursorChanged(qint64 nOffset)
431 {
432 g_bLockHex=true;
433 ui->lineEditFileOffset->setModeValue(g_mode,nOffset);
434 g_bLockHex=false;
435 }
436
registerShortcuts(bool bState)437 void XMemoryMapWidget::registerShortcuts(bool bState)
438 {
439 Q_UNUSED(bState)
440 // TODO
441 }
442