4.4 KiB
Embedded Systems Reverse Engineering
Week 3
Embedded System Analysis: Understanding the RP2350 Architecture w/ Comprehensive Firmware Analysis
Non-Credit Practice Exercise 2: Find the Stack Size
Objective
Calculate the size of the stack by examining the vector table, understanding the linker script's memory layout, and performing manual calculations.
Prerequisites
- Raspberry Pi Pico 2 with debug probe connected
- OpenOCD and
arm-none-eabi-gdbavailable build\0x0001_hello-world.elfflashed to the board- Understanding of memory regions from Week 3 Part 5 (Linker Script)
Task Description
You will examine the initial stack pointer value from the vector table, identify the stack limit, calculate the total stack size in bytes and kilobytes, and verify your calculations.
Background Information
From the Week 3 lesson, we learned:
- The initial stack pointer is stored at
0x10000000(first entry in vector table) - The linker script defines:
SCRATCH_Y: ORIGIN = 0x20081000, LENGTH = 4k - Stack top is calculated as:
ORIGIN + LENGTH = 0x20082000 - The stack grows downward from high addresses to low addresses
Step-by-Step Instructions
Step 1: Connect and Halt
(gdb) target extended-remote :3333
(gdb) monitor reset halt
Step 2: Examine the Initial Stack Pointer
(gdb) x/x 0x10000000
Expected output:
0x10000000 <__vectors>: 0x20082000
This is the top of the stack (where the stack starts before growing downward).
Step 3: Find the Stack Limit
The stack limit is defined in the linker script and can be found by examining stack-related symbols or calculating from memory regions.
From the Week 3 lesson, the stack limit is 0x20078000.
You can verify this in GDB:
(gdb) info symbol __StackLimit
or check registers after boot:
(gdb) info registers
Look for stack limit values or calculate: The main RAM starts at 0x20000000, and SCRATCH_Y starts at 0x20081000.
Step 4: Calculate Stack Size in Bytes
Formula:
Stack Size = Stack Top - Stack Limit
Stack Size = 0x20082000 - 0x20078000
Let's convert to decimal:
0x20082000= 537,108,480 decimal0x20078000= 537,067,520 decimal- Difference = 40,960 bytes
Alternative hex calculation:
0x20082000
- 0x20078000
-----------
0x0000A000 = 40,960 bytes
Step 5: Convert to Kilobytes
Bytes to KB = 40,960 ÷ 1,024 = 40 KB
So the stack is 40 KB in size.
Step 6: Verify Using Memory Regions
Cross-check with the memory layout:
- RAM:
0x20000000-0x20080000(512 KB) - SCRATCH_X:
0x20080000-0x20081000(4 KB) - SCRATCH_Y:
0x20081000-0x20082000(4 KB) ? Stack lives here - Stack range:
0x20078000-0x20082000(40 KB)
The stack extends from SCRATCH_Y down into the upper portion of main RAM.
Step 7: Examine Stack Usage at Runtime
You can see the current stack pointer value:
(gdb) b main
(gdb) c
(gdb) info registers sp
Expected output:
sp 0x20081fc8 0x20081fc8
This shows the stack has used:
0x20082000 - 0x20081fc8 = 0x38 = 56 bytes
Expected Output
- Initial stack pointer:
0x20082000 - Stack limit:
0x20078000 - Stack size: 40,960 bytes or 40 KB
- Current stack usage (at main): approximately 56 bytes
Questions for Reflection
Question 1: Why is the stack 40 KB instead of just fitting in the 4 KB SCRATCH_Y region?
Question 2: What happens if the stack grows beyond 0x20078000?
Question 3: How would you detect a stack overflow during runtime?
Question 4: Why does the stack grow downward instead of upward?
Tips and Hints
- Use Windows Calculator in Programmer mode to convert hex to decimal
- Remember: 1 KB = 1,024 bytes (not 1,000)
- The stack pointer (SP) decreases as the stack grows (push operations)
- Use
bt(backtrace) in GDB to see how much stack is currently in use
Next Steps
- Monitor the stack pointer as you step through functions to see it change
- Calculate stack usage for specific function calls
- Move on to Exercise 3 to examine all vector table entries
Additional Challenge
Write a GDB command to automatically calculate and display stack usage:
(gdb) define stackusage
> set $used = 0x20082000 - $sp
> printf "Stack used: %d bytes (%d KB)\n", $used, $used/1024
> end
(gdb) stackusage