Wie suche ich im Hexl-Modus nach einer Folge von Bytes?

7

Ist es möglich, nach einer Bytefolge zu suchen hexl-modeund diese möglicherweise hervorzuheben?

ZB in der Datei unten möchte ich die Bytesequenz durchsuchen f9beb4d9. isearchfunktioniert nicht, da die Präsentation im Puffer und nicht in der Originaldatei durchsucht wird.

00000000: f9be b4d9 1d01 0000 0100 0000 0000 0000  ................
00000010: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000020: 0000 0000 0000 0000 0000 0000 3ba3 edfd  ............;...
00000030: 7a7b 12b2 7ac7 2c3e 6776 8f61 7fc8 1bc3  z{..z.,>gv.a....
00000040: 888a 5132 3a9f b8aa 4b1e 5e4a 29ab 5f49  ..Q2:...K.^J)._I
00000050: ffff 001d 1dac 2b7c 0101 0000 0001 0000  ......+|........
00000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
gdkrmr
quelle
Bitte klären Sie anhand eines Beispiels, was Sie unter "Suche nach einer Byte-Sequenz" verstehen.
Stefan
@Stefan Ich denke, "Suche nach einer Byte-Sequenz" muss durch "Suche nach einer Byte-Sequenz" ersetzt werden. Das OP sollte das korrigieren. Wenn die korrigierte Version richtig ist, ist es ziemlich klar, was "Suche nach einer Byte-Sequenz" in einem Hexl-Puffer bedeutet. Man muss berücksichtigen, dass der Hexl-Puffer tatsächlich die Byte-Sequenz des ursprünglichen Puffers darstellt. Der Benutzer muss nicht wissen, wie Hexl funktioniert und dass es einen feinen Unterschied zwischen der Byte-Sequenz im Hexl-Puffer und der Byte-Sequenz im Original gibt.
Tobias
1
Die Hauptfrage ist, wie er die gesuchte Reihenfolge angeben will.
Stefan
Ich hoffe die Frage ist jetzt klar.
gdkrmr
@Stefan, Bonuspunkte, wenn Sie sowohl nach der Zeichenfolge als auch nach der Hex-Darstellung suchen können :-) Ich interessiere mich nur für die Hex-Darstellung der Bytes.
gdkrmr

Antworten:

2

Wenn Sie verwenden nhexl-mode(verfügbar in Ihrem nachbarschaftlichen GNU ELPA-Archiv), können Sie dies tun C-s f9beb4d9und es wird nach der Folge von 4 Bytes mit Codes gesucht f9 be b4 d9(sowie f9beb4d9natürlich nach dem 8-Bytes-Text und auch nach den Bytes an Adressen, die f9beb4d9in enthalten sind) ihre hexadezimale Darstellung).

Stefan
quelle
Danke dafür, es funktioniert, aber die Leistung in großen Dateien ist schrecklich.
gdkrmr
1
@gdkrmr: Ein Teil meiner Motivation für die Entwicklung des Nhexl-Modus war es, Leistungsprobleme im Hexl-Modus in großen Dateien zu umgehen. Aber ich bin nicht ganz überrascht, dass Sie Leistungsprobleme haben, um ehrlich zu sein. Bitte melden Sie sie, M-x report-emacs-bugindem Sie so viele Details wie möglich angeben (eine URL zu einer großen Beispieldatei kann ebenfalls nützlich sein, da die Leistung durch den Inhalt der Datei erheblich beeinträchtigt werden kann).
Stefan
1
Hallo Stefan, ich suche nur die Binärdatei und übersetze Adressen in Positionen des Hexl-Puffers. Sieht so aus, als hätte das keine Leistungsprobleme. Vielleicht ist das eine Alternative für Hexl oder Nhexl? Ich habe bereits ein Problem im Git-Repository behoben: github.com/TobiasZawada/hexl-isearch .
Tobias
2

Der folgende Lisp-Code fügt einen Eintrag "Hexl Isearch Mode" in das Menü "Hexl" ein.

Dieser Menüpunkt (de-) aktiviert den Nebenmodus hexl-isearch-mode. Wenn Sie diesen Modus aktivieren, isearchsuchen Sie in den Binärdaten anstelle des Hexl-Puffers.

Die Suchzeichenfolge wird mit gelesen read. Alle Escape-Sequenzen für Lisp-Strings funktionieren also. Als Beispiel können Sie nach Dos-Zeilenenden suchen \x0a\x0doder \^M\ndiese suchen.

Der Code ist nicht perfekt.

  1. Angenommen, Sie suchen nach einer Zeichenfolge, ELF\x01die nur am Anfang einer Datei vorkommt. Angenommen, es gibt ELf\x00später eine Zeichenfolge in der Binärdatei. Wenn Sie dann ELF\x0mit der Eingabe von Emacs ankommen, werden Sie die spätere Übereinstimmung finden, und wenn Sie mit der Eingabe ELF\x01fortfahren, glaubt Emacs, dass diese Zeichenfolge nicht vorkommt, da sie bereits angekommen ist und ELF\x0später in der Datei als ELF\x01. In einem solchen Fall lohnt es sich, eine überlappende Suche durchzuführen. (Dieses Problem ist bereits in der Git-Version des Pakets behoben .)

  2. Nur die Bytesequenz wird im Hexl-Puffer korrekt hervorgehoben, nicht die Zeichenfolgendarstellung auf der rechten Seite.

  3. Wenn sich die Suchzeichenfolge über zwei Zeilen im Hexl-Puffer erstreckt, werden auch die Zeichenfolgendarstellung am Zeilenende und die Adresse am Zeilenanfang hervorgehoben. Das liegt nicht daran, dass sie zur Übereinstimmung gehören, sondern daran, dass sie beim Hervorheben der Bytesequenz im Weg sind.

(require 'hexl)

(defvar-local hexl-isearch-raw-buffer nil
  "Buffer with the dehexlified content of the hexl buffer for hexl-isearch-mode.
This variable is set in the original hexl-mode buffer.")

(defvar-local hexl-isearch-original-buffer nil
  "This variable is set in the buffer with the dehexlified content.
It points to the corresponding hexl buffer.")

(defun hexl-address (position)
  "Return address of hexl buffer POSITION."
  (save-excursion
    (goto-char position)
    (hexl-current-address)))

(defun hexl-isearch-startup ()
  "Prepare hexl buffer for `hexl-isearch'."
  (let ((original-buf (current-buffer)))
    (setq-local hexl-isearch-raw-buffer (generate-new-buffer " hexl"))
    (setq-local isearch-search-fun-function (lambda () #'hexl-isearch-fun))
    (with-current-buffer hexl-isearch-raw-buffer
      (set-buffer-multibyte nil)
      (setq-local hexl-isearch-original-buffer original-buf)
      (insert-buffer-substring original-buf 1 (buffer-size original-buf))
      (dehexlify-buffer))))

(defun hexl-isearch-end ()
  "Cleanup after `hexl-isearch'."
  (let ((isearch-raw-buffer hexl-isearch-raw-buffer))
    (setq-local hexl-isearch-raw-buffer nil)
    (when (buffer-live-p isearch-raw-buffer)
      (kill-buffer isearch-raw-buffer))))

(defun hexl-isearch-fun (string &optional bound noerror count)
  "Search for byte sequence of STRING in hexl buffer.
The arguments BOUND and NOERROR work like in `search-forward'."
  (when bound (setq bound (1+ (hexl-address bound))))
  (setq string (read (concat "\"" string "\"")))
  (let ((point (1+ (hexl-current-address)))
    match-data)
    (with-current-buffer hexl-isearch-raw-buffer
      (goto-char point)
      (setq point (funcall (if isearch-forward #'re-search-forward #'re-search-backward)
               (if isearch-regexp
                   string
                 (regexp-quote string))
               bound noerror count))
      (setq match-data (match-data t nil t)))
    (when point
      (prog1
      (hexl-goto-address (1- point))
    (set-match-data
     (mapcar (lambda (el)
           (if (integerp el)
               (hexl-address-to-marker (1- el))
             el))
         match-data))))))

(define-minor-mode hexl-isearch-mode
  "Search for binary string with isearch in hexl buffer."
  :lighter " hi"
  (if hexl-isearch-mode
      (progn
    (setq-local isearch-search-fun-function #'hexl-isearch-fun)
    (add-hook 'isearch-mode-hook #'hexl-isearch-startup t t)
    (add-hook 'isearch-mode-end-hook #'hexl-isearch-end t t))
    (setq-local isearch-search-fun-function #'isearch-search-fun-default)
    (remove-hook 'isearch-mode-hook #'hexl-isearch-startup t)
    (remove-hook 'isearch-mode-end-hook #'hexl-isearch-end t)))

(easy-menu-add-item hexl-mode-map '(menu-bar Hexl)
            ["Hexl Isearch Mode" (if hexl-isearch-mode (hexl-isearch-mode -1) (hexl-isearch-mode)) :style toggle :selected hexl-isearch-mode] "Go to address")
Tobias
quelle
Ihr arbeitet auch und ist in großen Dateien viel leistungsfähiger!
gdkrmr