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