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
- The
defaultcase always returns -1. The other cases will have a return value that varies based on its input. - You may have missing cases.
- Some of your cases may have a fallthrough condition.
Submission
When mystery_test prints “SUCCESS: All test cases passed correctly!”, submit
the file mystery.c to Gradescope.