Disassemble and debug RISC-V and CHERI-RISC-V programs

This exercise steps you through disassembling and debugging RISC-V and CHERI-RISC-V programs. It draws attention to differences in program structure and code generation, particularly relating to control flow, between the two compilation targets.

First, use llvm-objdump on the host (which you can find at ~/cheri/output/sdk/bin/llvm-objdump, unless you have altered cheribuild's default paths) to disassemble and explore the two binaries from the previous exercise:

  1. Using llvm-objdump -dS, disassemble the print-pointer-riscv and print-pointer-cheri binaries.
  2. What jump instruction is used to call printf() in print-pointer-riscv? Where does the target address for that jump originate?
  3. What jump instruction is used to call printf() in print-pointer-cheri? Where does the target capability for that jump originate? (Hint, you may find it helpful to add the -s flag to your llvm-objdump command to see all sections.)

Next use GDB to explore binary execution for RISC-V:

  1. Run print-pointer-riscv under GDB, setting a breakpoint at the start of printf(). Note: GDB can't find the run-time linker of binaries of the non-default ABI on its own so you need to invoke set program-interpreter /libexec/ld-elf64.so.1 before running the program.
  2. Run the program and at the breakpoint, print out the value of the string pointer argument.
  3. Use info proc mappings in GDB to print out the layout of the process address space.
  4. Print out the program counter (info reg pc). What memory mapping is it derived from?

And for CHERI-RISC-V:

  1. Run print-pointer-cheri under GDB, setting a breakpoint at the start of printf().
  2. Print out the value of the string pointer argument.
  3. Use info proc mappings (in GDB) to print out the layout of the process address space.
  4. Print out the program counter (info reg pcc). What memory mapping is it derived from? Where do its bounds appear to originate from?
  5. Print out the register file using info registers. What mappings do the capabilities in the register file point to? Notice that some capabilities are labeled with (sentry) (or (sealed) in the case of older versions of GDB which do not distinguish sentries from other sealed capabilities). Sentry capabilities are sealed (cannot be modified or used to load or store), but can be used as a jump target (where they are unsealed and installed in pcc). What implications does this have for attackers?