"Fossies" - the Fresh Open Source Software Archive

Member "cutter-1.10.3/src/widgets/SearchWidget.cpp" (8 May 2020, 9063 Bytes) of package /linux/privat/cutter-1.10.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "SearchWidget.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.10.2_vs_1.10.3.

    1 #include "SearchWidget.h"
    2 #include "ui_SearchWidget.h"
    3 #include "core/MainWindow.h"
    4 #include "common/Helpers.h"
    5 
    6 #include <QDockWidget>
    7 #include <QTreeWidget>
    8 #include <QComboBox>
    9 #include <QShortcut>
   10 
   11 namespace {
   12 
   13 static const int kMaxTooltipWidth = 500;
   14 static const int kMaxTooltipDisasmPreviewLines = 10;
   15 static const int kMaxTooltipHexdumpBytes = 64;
   16 
   17 }
   18 
   19 static const QMap<QString, QString> searchBoundaries {
   20     {"io.maps", "All maps"},
   21     {"io.map", "Current map"},
   22     {"raw", "Raw"},
   23     {"block", "Current block"},
   24     {"bin.section", "Current mapped section"},
   25     {"bin.sections", "All mapped sections"},
   26 };
   27 
   28 static const QMap<QString, QString> searchBoundariesDebug {
   29     {"dbg.maps", "All memory maps"},
   30     {"dbg.map", "Memory map"},
   31     {"block", "Current block"},
   32     {"dbg.stack", "Stack"},
   33     {"dbg.heap", "Heap"}
   34 };
   35 
   36 SearchModel::SearchModel(QList<SearchDescription> *search, QObject *parent)
   37     : AddressableItemModel<QAbstractListModel>(parent),
   38       search(search)
   39 {
   40 }
   41 
   42 int SearchModel::rowCount(const QModelIndex &) const
   43 {
   44     return search->count();
   45 }
   46 
   47 int SearchModel::columnCount(const QModelIndex &) const
   48 {
   49     return Columns::COUNT;
   50 }
   51 
   52 QVariant SearchModel::data(const QModelIndex &index, int role) const
   53 {
   54     if (index.row() >= search->count())
   55         return QVariant();
   56 
   57     const SearchDescription &exp = search->at(index.row());
   58 
   59     switch (role) {
   60     case Qt::DisplayRole:
   61         switch (index.column()) {
   62         case OFFSET:
   63             return RAddressString(exp.offset);
   64         case SIZE:
   65             return RSizeString(exp.size);
   66         case CODE:
   67             return exp.code;
   68         case DATA:
   69             return exp.data;
   70         default:
   71             return QVariant();
   72         }
   73     case Qt::ToolTipRole: {
   74 
   75         QString previewContent = QString();
   76         // if result is CODE, show disassembly
   77         if (!exp.code.isEmpty()) {
   78             previewContent = Core()->getDisassemblyPreview(exp.offset, kMaxTooltipDisasmPreviewLines)
   79                                     .join("<br>");
   80         // if result is DATA or Disassembly is N/A                                    
   81         } else if (!exp.data.isEmpty() || previewContent.isEmpty()) {
   82             previewContent = Core()->getHexdumpPreview(exp.offset, kMaxTooltipHexdumpBytes);
   83         }
   84 
   85         const QFont &fnt = Config()->getBaseFont();
   86         QFontMetrics fm{ fnt };
   87 
   88         QString toolTipContent = QString("<html><div style=\"font-family: %1; font-size: %2pt; white-space: nowrap;\">")
   89                 .arg(fnt.family())
   90                 .arg(qMax(6, fnt.pointSize() - 1)); // slightly decrease font size, to keep more text in the same box
   91         
   92         toolTipContent += tr("<div style=\"margin-bottom: 10px;\"><strong>Preview</strong>:<br>%1</div>")
   93                 .arg(previewContent);
   94 
   95         toolTipContent += "</div></html>";
   96         return toolTipContent;
   97     }
   98     case SearchDescriptionRole:
   99         return QVariant::fromValue(exp);
  100     default:
  101         return QVariant();
  102     }
  103 }
  104 
  105 QVariant SearchModel::headerData(int section, Qt::Orientation, int role) const
  106 {
  107     switch (role) {
  108     case Qt::DisplayRole:
  109         switch (section) {
  110         case SIZE:
  111             return tr("Size");
  112         case OFFSET:
  113             return tr("Offset");
  114         case CODE:
  115             return tr("Code");
  116         case DATA:
  117             return tr("Data");
  118         default:
  119             return QVariant();
  120         }
  121     default:
  122         return QVariant();
  123     }
  124 }
  125 
  126 RVA SearchModel::address(const QModelIndex &index) const
  127 {
  128     const SearchDescription &exp = search->at(index.row());
  129     return exp.offset;
  130 }
  131 
  132 
  133 SearchSortFilterProxyModel::SearchSortFilterProxyModel(SearchModel *source_model, QObject *parent)
  134     : AddressableFilterProxyModel(source_model, parent)
  135 {
  136 }
  137 
  138 bool SearchSortFilterProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const
  139 {
  140     QModelIndex index = sourceModel()->index(row, 0, parent);
  141     SearchDescription search = index.data(
  142                                    SearchModel::SearchDescriptionRole).value<SearchDescription>();
  143     return search.code.contains(filterRegExp());
  144 }
  145 
  146 bool SearchSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
  147 {
  148     SearchDescription left_search = left.data(
  149                                         SearchModel::SearchDescriptionRole).value<SearchDescription>();
  150     SearchDescription right_search = right.data(
  151                                          SearchModel::SearchDescriptionRole).value<SearchDescription>();
  152 
  153     switch (left.column()) {
  154     case SearchModel::SIZE:
  155         return left_search.size < right_search.size;
  156     case SearchModel::OFFSET:
  157         return left_search.offset < right_search.offset;
  158     case SearchModel::CODE:
  159         return left_search.code < right_search.code;
  160     case SearchModel::DATA:
  161         return left_search.data < right_search.data;
  162     default:
  163         break;
  164     }
  165 
  166     return left_search.offset < right_search.offset;
  167 }
  168 
  169 
  170 SearchWidget::SearchWidget(MainWindow *main, QAction *action) :
  171     CutterDockWidget(main, action),
  172     ui(new Ui::SearchWidget)
  173 {
  174     ui->setupUi(this);
  175     setStyleSheet(QString("QToolTip { max-width: %1px; opacity: 230; }").arg(kMaxTooltipWidth));
  176 
  177     updateSearchBoundaries();
  178 
  179     search_model = new SearchModel(&search, this);
  180     search_proxy_model = new SearchSortFilterProxyModel(search_model, this);
  181     ui->searchTreeView->setModel(search_proxy_model);
  182     ui->searchTreeView->setMainWindow(main);
  183     ui->searchTreeView->sortByColumn(SearchModel::OFFSET, Qt::AscendingOrder);
  184 
  185     setScrollMode();
  186 
  187     connect(Core(), &CutterCore::toggleDebugView, this, &SearchWidget::updateSearchBoundaries);
  188     connect(Core(), &CutterCore::refreshAll, this, &SearchWidget::refreshSearchspaces);
  189 
  190     QShortcut *enter_press = new QShortcut(QKeySequence(Qt::Key_Return), this);
  191     connect(enter_press, &QShortcut::activated, this, [this]() {
  192         refreshSearch();
  193     });
  194     enter_press->setContext(Qt::WidgetWithChildrenShortcut);
  195 
  196     connect(ui->searchButton, &QAbstractButton::clicked, this, [this]() {
  197         refreshSearch();
  198     });
  199 
  200     connect(ui->searchspaceCombo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
  201             this, [this](int index) { updatePlaceholderText(index);});
  202 }
  203 
  204 SearchWidget::~SearchWidget() {}
  205 
  206 void SearchWidget::updateSearchBoundaries()
  207 {
  208     QMap<QString, QString>::const_iterator mapIter;
  209     QMap<QString, QString> boundaries;
  210 
  211     if (Core()->currentlyDebugging && !Core()->currentlyEmulating) {
  212         boundaries = searchBoundariesDebug;
  213     } else {
  214         boundaries = searchBoundaries;
  215     }
  216 
  217     mapIter = boundaries.cbegin();
  218     ui->searchInCombo->setCurrentIndex(ui->searchInCombo->findData(mapIter.key()));
  219     Config()->setConfig("search.in", mapIter.key());
  220 
  221     ui->searchInCombo->blockSignals(true);
  222     ui->searchInCombo->clear();
  223     for (; mapIter != boundaries.cend(); ++mapIter) {
  224         ui->searchInCombo->addItem(mapIter.value(), mapIter.key());
  225     }
  226     ui->searchInCombo->blockSignals(false);
  227 
  228     ui->filterLineEdit->clear();
  229 }
  230 
  231 void SearchWidget::searchChanged()
  232 {
  233     refreshSearchspaces();
  234 }
  235 
  236 void SearchWidget::refreshSearchspaces()
  237 {
  238     int cur_idx = ui->searchspaceCombo->currentIndex();
  239     if (cur_idx < 0)
  240         cur_idx = 0;
  241 
  242     ui->searchspaceCombo->clear();
  243     ui->searchspaceCombo->addItem(tr("asm code"),   QVariant("/acj"));
  244     ui->searchspaceCombo->addItem(tr("string"),     QVariant("/j"));
  245     ui->searchspaceCombo->addItem(tr("hex string"), QVariant("/xj"));
  246     ui->searchspaceCombo->addItem(tr("ROP gadgets"), QVariant("/Rj"));
  247     ui->searchspaceCombo->addItem(tr("32bit value"), QVariant("/vj"));
  248 
  249     if (cur_idx > 0)
  250         ui->searchspaceCombo->setCurrentIndex(cur_idx);
  251 
  252     refreshSearch();
  253 }
  254 
  255 void SearchWidget::refreshSearch()
  256 {
  257     QString search_for = ui->filterLineEdit->text();
  258     QVariant searchspace_data = ui->searchspaceCombo->currentData();
  259     QString searchspace = searchspace_data.toString();
  260 
  261     search_model->beginResetModel();
  262     search = Core()->getAllSearch(search_for, searchspace);
  263     search_model->endResetModel();
  264 
  265     qhelpers::adjustColumns(ui->searchTreeView, 3, 0);
  266 }
  267 
  268 void SearchWidget::setScrollMode()
  269 {
  270     qhelpers::setVerticalScrollMode(ui->searchTreeView);
  271 }
  272 
  273 void SearchWidget::updatePlaceholderText(int index)
  274 {
  275     switch (index) {
  276     case 1: // string
  277         ui->filterLineEdit->setPlaceholderText("foobar");
  278         break;
  279     case 2: // hex string
  280         ui->filterLineEdit->setPlaceholderText("deadbeef");
  281         break;
  282     case 3: // ROP gadgets
  283         ui->filterLineEdit->setPlaceholderText("pop,,pop");
  284         break;
  285     case 4: // 32bit value
  286         ui->filterLineEdit->setPlaceholderText("0xdeadbeef");
  287         break;
  288     default:
  289         ui->filterLineEdit->setPlaceholderText("jmp rax");
  290     }
  291 }
  292 
  293 
  294 void SearchWidget::on_searchInCombo_currentIndexChanged(int index)
  295 {
  296     Config()->setConfig("search.in",
  297                       ui->searchInCombo->itemData(index).toString());
  298 }