October 30, 2024

Sun 3/80 bootrom -- vim customization to aid disassembly

I run Gnu objdump as my disassembler, then go to work on the naive output. This disassembles everything as code, even if it is blocks of data, strings, or whatever. Some people would call this a "sweep" disassembler. Another way is to use a smarter disassembler that you give a handfull of code addresses to start and it works up a call tree and stays within called code blocks.

Trick ctags into helping me

I got the idea that as I use vim to poke around in the disassembly, it would be nice to put the cursor on some hex value, click Ctrl-] like I do in C source when using ctags, and go to the line with that address. I wrote a python script to generate a tags file and now I have exactly that. The script is "romtags" in my Github collection. The tags file looks like:
0xfefe0102	rom.dis	/^fefe0102/
0xfefe0104	rom.dis	/^fefe0104/
0xfefe0106	rom.dis	/^fefe0106/
You just need the tag string, the file it is in, and a search command for that file.

Some Vim keyboard mappings

I added these to my .vimrc
:let mapleader = "-"
" special hooks for sun3/80 disassembly
" hook for redoing disassembly
nnoremap d :.!./redisv
nnoremap s :.!./vim_string
These just define the mappings "-d" and "-s". These are just the tip of the iceberg. These do what is called a vim filter on the current line. They send to current line to some external program, which reads it on stdin. Then whatever output that program generates replaces the line that was sent out.

"-d" for out of sync disassembly

Doing what I do, the assembler gets out of sync sometimes. Not very often, but when it does, usually a 2 byte chunk of zeros after a "rts" instruction causes the trouble. Apparently a compiler was padding generated output for some reason. Perhaps to keep subroutine addresses on 4 byte boundaries.

So I need to redo the assembly starting at the right place. Usually the right place is 2 bytes after where the trashed disassembly is.

I set up a keybinding so that when I type "-d" vim sends the current line to an outboard program (written in python). That python code gets the line, pulls the address out of it, adds 2 to it, and then calls objdump to disassemble at that address. Then it returns the result to vim, which replaces the line. I include the original line and some markers and I do have to do some hand editing, but I don't have to exit vim, write addresses on scratch paper, and run objdump with crazy options.

"-s" for strings

Fairly often, the code I am looking at loads the address of a string into a register, then sets up a call to printf or something similar. I set up a "-s" keybinding to send the current line to an outboard program (python again). The python program then calls a helper program written in C (to avoid dealing with binary files in python). The C program extracts the string, hands it back to the python program. The python program then sends the original line followed by the string (set up to look like a comment). I need to send back the original line because the vim filter scheme deletes it when it sends it outboard.

Vim filters

This is what the vim world calls a filter. You can find the python "redisv" program in my Github associated with this project.

The filter takes one or more lines on stdin and spits out replacements on stdout. It can do anything you want. It can even ignore the input.

Here I use ":.!" to trigger the filter, but "!!" is different but equally useful, especially if you don't want to add something to your .vimrc.

Type "help filter" in Vim and read what it has to say.
Or search on "vim filter".