Reverse Engineering a Switch Statement

In this lab, we will reverse engineer a C function to learn about switch statements and jump tables.

First get a copy of the program by running the following commands in your CS Linux account.

cd ~/cs224
wget --no-check-certificate https://cs224.cs.vassar.edu/labs/mystery_switch.tar
tar xvf mystery_switch.tar
cd mystery_switch

Your job is to reverse engineer the assembly code in mystery_ref.o to reconstruct the switch statement in mystery.c.

I have not given you mystery_ref.c, but below is the output from running the assembler on that file.

mystery_ref.s

mystery_ref:
    addi    a5,a0,-100
    li      a4,7
    bgtu    a5,a4,.L10
    lui     a4,%hi(.L4)
    slli    a5,a5,2
    addi    a4,a4,%lo(.L4)
    add     a5,a5,a4
    lw      a5,0(a5)
    jr      a5

.L4:
    .word   .L8
    .word   .L10
    .word   .L7
    .word   .L10
    .word   .L6
    .word   .L5
    .word   .L10
    .word   .L3

.L10:
    li      a0,-1
.L1:
    ret
.L8:
    neg     a2,a2
.L7:
    add     a0,a2,a1
    ret
.L3:
    srai    a1,a1,12
    andi    a0,a1,255
    ret
.L6:
    mv      a0,a2
    bge     a2,a1,.L1
    mv      a0,a1
    ret
.L5:
    or      a0,a2,a1
    ret

Your job is to recreate the C code that generated the above assembly code. To see if your switch statement matches the reference implementation, type make to build the test program mystery_switch.

Note, you will get some compiler warning if you try to build the program, because your switch statement doesn’t do anything yet and there are unused variables.

make
riscv32-none-elf-gcc -Wall -Wextra -O2 -march=rv32im -mabi=ilp32  -static -o mystery_test mystery_ref.o mystery_test.o mystery.c
mystery.c: In function 'mystery':
mystery.c:3:25: warning: unused parameter 'src1' [-Wunused-parameter]
    3 | int mystery(int op, int src1, int src2) {
      |                     ~~~~^~~~
mystery.c:3:35: warning: unused parameter 'src2' [-Wunused-parameter]
    3 | int mystery(int op, int src1, int src2) {
      |                               ~~~~^~~~

That’s OK. You’ll get rid of those warnings once you fill out your switch statement.

Here’s an example of running the test code.

qemu-riscv32 ./mystery_test

=== TEST FAILED ===
Mismatch found on input:
  op   = 100
  src1 = 0 (0x00000000)
  src2 = 0 (0x00000000)
Expected : 0
Got      : -1

The mystery_test program will run a series of tests. If it fails a test, it will give you the inputs that failed, and what is expected. The quickest way to complete the assignment is by understanding the assembly code, not by brute-forcing a solution based on failing tests.

Hints

Submission

When mystery_test prints “SUCCESS: All test cases passed correctly!”, submit the file mystery.c to Gradescope.