WEEK06-BN.md/.pdf mirroring WEEK04-BN: build/flash/symbol map, load the raw .bin,
dynamic (GDB MI break at the first printf, live r1=43) then static (resolve
functions, patch 0x10000264 2a->2b, invert the button logic 0x10000288 01->00,
export/convert/flash). README links it.
New WEEK05-BN.md/.pdf mirroring WEEK04-BN: build/flash/symbol map, load the raw
.bin, dynamic (GDB MI break + live double hack) then static (resolve functions,
patch the 42.5->99.0 one-word and 42.52525->99.99 two-word constants, export,
convert, flash) for both 0x000e float and 0x0011 double. README links it.
The X/Kill ends the BN debug session but leaves the external OpenOCD (started by
debug-server.sh) running and holding the probe. Tell the reader to pkill/taskkill it
too, and give the console form.
Step 29's snippet had no pkill, so with the debug-server OpenOCD still attached the
flash failed with 'CMSIS-DAP command CMD_INFO failed / OpenOCD init failed'. Add the
pkill to Step 29 and both Step 21 blocks.
End each dynamic section by killing the debug session (X / Debugger -> Kill) before
the static pass, so the OpenOCD session is shut down and the probe is free.
Mirror Steps 7-8 for Project 2 (Open with Options, thumb2/thumb2/0x10000000,
verify the vector words, Save As .bndb) and point at Step 26 for resolving the
Project 2 functions.
The console snippets no longer depend on bv.file.original_filename, so they work
with no database open. Step 3 has a one-time setup (pwd > ~/.embedded-hacking-repo,
or the PowerShell equivalent) and every build/flash/server snippet reads root from
that file. Removes the bv asserts.
Every console snippet derives the repo path from bv.file.original_filename, so
with no database open bv is None and it fails with 'NoneType has no attribute
file'. Add 'assert bv is not None, "Open the .bndb first..."' to all 12 snippets
so the failure is explicit.
Every flash step now has the terminal form and the console form (pkill/taskkill,
then Popen flash.sh/.ps1 into flash.log), matching Steps 10/21/29. Steps 5/6 note
they need a database open to derive the repo root.
Step 10 now shows starting the debug server from the console: pkill/taskkill any
running OpenOCD first, then Popen debug-server.sh(.ps1) with BP_ADDR and output to
openocd.log so the console returns immediately. Verified: Popen returns in ~6 ms,
log shows 'Startup breakpoint at 0x10000234' + 'Listening on port 3333'. Ignore
openocd.log/flash.log/build.log.
Add macOS/Linux/Windows console build snippets to Step 3. The console's PATH is
minimal (no Homebrew on macOS), so macOS adds /opt/homebrew/bin to PATH then runs
plain cmake; Linux/Windows already have cmake on PATH. With the Popen flash, the
whole build->patch->flash loop runs inside Binary Ninja.
subprocess.run blocks the console until OpenOCD exits (and can hang it if the
probe is contended). Use subprocess.Popen with output to flash.log and
start_new_session, then poll p.poll() or read the log. Verified: Popen returns in
~1 ms, flash completes ~2 s later with 'Verified OK'. Applied to Steps 21 and 29.
Add the missing Windows PowerShell/cmd forms for flash, stop-server, debug-server
BP_ADDR, and the Step 29 uf2conv call, so no command is platform-ambiguous.
The Pico extension's Arm GNU Toolchain includes arm-none-eabi-gdb (used by the
GDB / GDB MI labs) -- call it out. Keep the identical cmake build for all OSes but
give full Windows / macOS / Linux compile+flash blocks, plus the explicit
PICO_SDK_PATH/PICO_TOOLCHAIN_PATH fallback.
Add the flash.sh / OpenOCD program-over-probe path to Steps 21 and 29: run it
from Binary Ninja's console via subprocess, and note the probe is single-owner
(stop debug-server.sh's OpenOCD first). Verified live: Verified OK, reset, and the
board booted the hacked image.
Install everything for the course without a VM: VS Code Pico extension (SDK,
Arm toolchain, picotool, OpenOCD), Binary Ninja Personal, Ghidra + JDK 21, and a
serial monitor. Ends with a compile + SWD flash example for 0x0001 hello, world.
Read the loadable segment (seg.start + seg.data_length) instead of hardcoding the
range or calling os.path.getsize, and document converting the .bin to UF2 from
Binary Ninja's own Python console (chdir + runpy). Verified: the dump is byte-exact
except the patches, and uf2conv yields a valid UF2 (magic/family/blocks OK).
The console's CWD is read-only, so open('...bin','wb') fails with OSError
Errno 30. Write next to the loaded file via bv.file.original_filename, and read
the image range (0x10000000 + 0x3bbc / 0x3d34) instead of the whole mapped view.
The Python shortcut failed with SyntaxError: unknown type name 'stdio_driver_t'
then 'va_list' then 'uint'. set_user_type re-parses each signature as C, so the
Pico SDK types (uint, va_list, stdio_driver_t, uart_inst_t, gpio_function_t) must
be defined first. Add the sdk parse/define block to both snippets and correct the
stale 'undefined named types are fine' note.
Replace the wrong 'double-click the value' instruction with
dbg.set_reg_value('r1', 0x46) / dbg.set_reg_value('r0', 0x20080000);
right-click + E kept as the alternative. Drop the 'turns orange' claim.
- Step 16: Y is the primary resolution key (Change Type sets name+type); N is
rename-only; explicit how-to and worked examples use G then Y
- Step 4: add exact DWARF signatures to both symbol tables
- Python shortcut now sets names AND types (bv.get_function_at(...).set_user_type)
- Step 26: worked examples use G then Y
- Step 16: G/N/Y key table and worked examples (main, stdio_init_all, uart_init,
__wrap_printf); note BN shows int32_t where Ghidra shows int
- Step 26: worked check + pointer to Step 16
- troubleshooting: macOS serial capture needs raw termios at 115200
- Step 13/14/25 and tables: use Debugger -> Add Hardware Breakpoint... (HE),
warn that F2 Toggle Breakpoint is a software breakpoint and never installs on
read-only flash
- new troubleshooting entry: r1 reverts to 0x2b (core running because the
breakpoint is not installed; registers widget is a per-stop snapshot)
- Step 13 rewritten: set/move breakpoints in the GUI, not the command port
- Steps 14/14b/25/25b: breakpoints via the GUI (command port only for the
RAM string write, which BN cannot do)
- Step 22/23: adapter corrected GDB RSP -> GDB MI
- cheat sheet, GUI-actions and OpenOCD tables: GUI-first, command port as fallback
- troubleshooting: real GDB MI causes (pre-existing breakpoint, gdb path, LLDB);
stops reported as Breakpoint not SingleStep
Single canonical copy at the repo root: full type annotations and
Google-style docstrings, pathlib instead of os.path, explicit except
clauses, upstream error-path bugs fixed, and module globals replaced
with an explicit ConverterContext.