Como procurar uma sequência de bytes no modo hexl?

7

É possível procurar uma sequência de bytes hexl-modee possivelmente destacá-la?

Por exemplo, no arquivo abaixo, quero pesquisar a sequência de bytes f9beb4d9. isearchnão funciona porque pesquisa a apresentação no buffer e não no arquivo original.

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
fonte
Por favor, esclareça o que você quer dizer com "pesquisar uma sequência de bytes" com um exemplo.
Stefan
@Stefan eu penso "procurar uma seqüência de byte" tem de ser substituído por "procurar por uma seqüência de byte". O OP deve corrigir isso. Se a versão corrigida estiver correta, é bastante claro o que significa "procurar uma sequência de bytes" em um buffer hexl. É preciso levar em consideração que o buffer hexl realmente representa a sequência de bytes do buffer original. O usuário não precisa saber como o hexl funciona e se há uma diferença entre a sequência de bytes no buffer hexl e a sequência de bytes no original.
9118 Tobias
11
A principal questão é como ele pretende especificar a sequência que está procurando.
Stefan
Espero que a pergunta esteja clara agora.
Gdkrmr 09/12/19
@ Stefan, pontos de bônus se você puder procurar a string e a representação hexadecimal :-) Estou interessado apenas na representação hexadecimal dos bytes.
Gdkrmr 09/12/19

Respostas:

2

Se você usar nhexl-mode(disponível a partir de sua vizinhança arquivo GNU ELPA), então você pode fazer C-s f9beb4d9e vai procurar a seqüência de 4 bytes com os códigos f9 be b4 d9(bem como para os 8 bytes de texto f9beb4d9claro, e também os bytes de endereços que incluem f9beb4d9em sua representação hexadecimal).

Stefan
fonte
obrigado por isso, ele funciona, mas o desempenho em arquivos grandes é terrível.
Gdkrmr
11
@gdkrmr: Parte da minha motivação para o desenvolvimento do modo nhexl foi contornar problemas de desempenho no modo hexl em arquivos grandes. Mas não estou completamente surpreso que você esteja enfrentando problemas de desempenho, para ser sincero. Relate-os M-x report-emacs-bugfornecendo o máximo de detalhes possível (um URL para um arquivo grande de amostra também pode ser útil, pois o desempenho pode ser significativamente afetado pelo conteúdo do arquivo).
21418 Stefan
11
Oi Stefan, Estou apenas pesquisando o binário e traduzir endereços em posições do buffer hexl. Parece que isso não tem problemas de desempenho. Talvez essa seja uma alternativa para hexl ou nhexl? Eu já corrigi um problema no repositório git: github.com/TobiasZawada/hexl-isearch .
11268 Tobias
2

O código lisp a seguir coloca uma entrada "Hexl Isearch Mode" no menu "Hexl".

Esse item de menu (des-) ativa o modo secundário hexl-isearch-mode. Se você ativar esse modo, isearchprocurará nos dados binários em vez do buffer hexl.

A cadeia de pesquisa é lida com read. Portanto, todas as seqüências de escape para strings lisp funcionam. Como exemplo, você pode procurar \x0a\x0dou \^M\npesquisar por finais da linha dos.

O código não é perfeito.

  1. Digamos que você pesquise uma string ELF\x01que só ocorra no início de um arquivo. Além disso, suponha que exista uma string ELf\x00posteriormente no binário. Então, quando você ELF\x0digitar o Emacs, encontrará a correspondência posterior e, se continuar digitando, o ELF\x01Emacs acha que não há ocorrências dessa string, porque ela já chegou ao ELF\x0que vem depois no arquivo ELF\x01. Vale a pena fazer uma pesquisa sobreposta nesse caso. (Esse problema já foi corrigido na versão git do pacote .)

  2. Somente a sequência de bytes é iluminada corretamente no buffer hexl, e não na representação de string no lado direito.

  3. Se a cadeia de pesquisa se estender por duas linhas no buffer hexl, a representação da cadeia no final da linha e o endereço no início da linha também serão destacados. Isso não ocorre porque eles pertencem à correspondência, mas porque eles estão no caminho ao destacar a sequência de bytes.

(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
fonte
O seu também funciona e tem muito mais desempenho em arquivos grandes!
Gdkrmr