The following lisp code puts an entry "Hexl Isearch Mode" into the "Hexl" menu.
That menu item (de-)activates the minor mode
If you activate that mode
isearch searches in the binary data instead of the hexl buffer.
The search string is read with
So all escape sequences for lisp strings do work.
As an example you can search for
\^M\n to search for dos line ends.
The code is not perfect.
Let's say you search for a string
ELF\x01 which only occurs at the beginning of a file. Furthermore, assume there is a string
ELf\x00 later on in the binary. Then when you arrive at
ELF\x0 with typing Emacs will find the later match and if you go on in typing
ELF\x01 Emacs thinks there are no occurrences of that string because it already arrived at
ELF\x0 which comes later in the file than
ELF\x01. It is worth to do an overlapped search in such a case. (That problem is already fixed in the git-version of the package.)
Only the byte sequence is correctly high-lighted in the hexl buffer not the string representation at the right-hand side.
If the search string spans two lines in the hexl buffer the string representation at the end of the line and the address at the beginning of the line are also highlighted. That is not because they belong to the match but because they are in the way when highlighting the byte sequence.
(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."
(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))
(setq-local hexl-isearch-original-buffer original-buf)
(insert-buffer-substring original-buf 1 (buffer-size original-buf))
(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)
(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)))
(setq point (funcall (if isearch-forward #'re-search-forward #'re-search-backward)
bound noerror count))
(setq match-data (match-data t nil t)))
(hexl-goto-address (1- point))
(mapcar (lambda (el)
(if (integerp el)
(hexl-address-to-marker (1- el))
"Search for binary string with isearch in hexl buffer."
:lighter " hi"
(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")