Arm assembly - multiple push/pop order and SP - arm

I've seen an annotation for pushing/popping multiple registers in the same line, e.g:
push {fp, lr}
I couldn't find out who is pushed first - fp or lr?
An additional question - does SP point to the last occupied address in the stack or the first free one?

From the ARM ARM:
The registers are stored in sequence, the lowest-numbered register to the lowest memory address (start_address), through to the highest-numbered register to the highest memory address (end_address)
On ARM, the stack pointer normally points to the last occupied address on the stack. For example, when setting up the initial stack pointer, you normally initialize with with the address one past the end of the stack.
PUSH is just a synonym for STMDB using sp as the base register. The DB indicates the 'decrement-before' addressing mode.

Related

Is compiler using relative addresses for stack variables in the scope?

I've programmed a task scheduler for STM32 (ARM) MCU which enables multitasking. I can create concurrent tasks, each having an own allocated stack, as this is the most straightforward way to do it. These stacks are allocated on the heap. Since these stacks are static in size, which is a very inefficient way to use memory space, I'm planning to add dynamic stack reallocation.
My question is: If I reallocate a task's stack on another memory address and copy all stack contents and update the task (ie. stack pointer), can the task continue running without any problem, if I'm not using in the task's code any absolute address of the stack? Is the C compiler using relative addressing only in the stack even if I'm taking an address of a variable in the scope?
Example:
void A() {
int i = 0;
int* iPtr = &i;
}
In the case above the value of iPtr will be a static address, or relative like currAddress-4? (If I'm not passing it to another function, just using it inside the scope.)
So is there any way the compiler uses relative address with offset in this scope, or just uses the direct address of the variable?
If there is relative address handling then I can reallocate the stack freely on another memory space, if not then I can't, which would be a problem.
I didn't really find any good documentation about this, so that also would be appreciated!
If not this is the right approach, then how stack reallocation for tasks used to be implemented?
Sorry to say it, but pointers are always absolute. You can confirm this by looking at the assembly of a small program that takes a pointer to a local variable and passes it to another function:
void set(int *p) {
*p = 42;
}
void bar(void) {
int l;
set(&l);
}
compiles to
set:
movs r3, #42
str r3, [r0] // store to absolute address in r0
bx lr
bar:
push {lr}
sub sp, sp, #12
add r0, sp, #4 // form absolute pointer to stack location [sp+4]
bl set
add sp, sp, #12
ldr pc, [sp], #4
https://godbolt.org/z/7EWoK3eda
This really couldn't work any other way: the function set has to compile to code that will do the right thing whether it is passed a pointer to the stack, or static memory, or heap. Also, an sp-relative pointer wouldn't even make sense when passed to a function with a different stack frame and hence a different value for sp.
So if you try to relocate the stack out from under a C program, it is almost certain to break.
Normally, the way you avoid wasting a ton of memory on stack is with virtual memory: you allocate a large block of virtual address space for the task's stack. Then you map physical memory into only a small part of it. As the stack grows and touches previously unused pages, the MMU signals a page fault, which your OS handles by allocating and mapping another page of physical memory. Because the mapping of virtual to physical pages is arbitrary, the stack remains at a fixed virtual address whereas the physical memory underneath need not be contiguous. It could even be copied and remapped while the task is suspended.

Determining return address of function on ARM Cortex-M series

I want to determine the return address of a function in Keil. I opened diassembly section at debugging mode in Keil uvision. What is shown is some assembly code like this:
My intention is to inject a simple binary code to microcontroller via using buffer overflow at microcontroller.see: Buffer overflow
I want to determine the return address of "test" function . Is it a must to know how to read assembly code or are there any trick to find the return address?
I am newbie to assembly.
R14 or in other name LR hold the return address. On the left you can see it in the picture. It is 0x08000287.
When a function is called, R14 will be overwritten with the address following the call ("BL" or "BLX") instruction. If that function doesn't call any other functions, R14 will often be left holding the return address for its duration. Further, if the function tail-calls another function, the tail call may be replaced with a branch ("B" or "BX"), with R14 holding the return address of the original caller. If a function makes a non-tail call to another function, it will be necessary to save R14 "somewhere" (typically the stack, but possibly to another previously-used caller-saved register) at some time before that, and retrieve that value from the stack at some later time, but if optimizations are enabled the location where R14 is saved will generally be unpredictable.
Some compilers may have a mode that would stack things consistently enough to be usable, but code will be very compiler-dependent. The technique most likely to be successful may be to do something like:
extern int getStackAddress(uint8_t **addr); // Always returns zero
void myFunction(...whavever...)
{
uint8_t *returnAddress;
if (getStackAddress(&returnAddress)) return; // Put this first.
}
where the getStackAddress would be a machine-code function that stores R14 to the address in R0, loads R0 with zero, and then branches to R14. There are relatively few code sequences that would be likely to follow that, and if a code examines instructions at the address stored in returnAddress and recognizes one of these code sequences, it would know that the return address for myFunction is stored in a spot appropriate for the sequence in question. For example, if it sees:
test r0,r0
be ...
pop {r0,pc}
It would know that the caller's address is second on the stack. Likewise if it sees:
cmp r0,#0
bne somewhere:
somewhere: ; Compute address based on lower byte of bne
pop {r0,r1,r2,r4,r5,pc}
then it would know that the caller's address is sixth.
There are a few instructons compilers could use to test a register against zero, and some compilers might use be while others use bne, but for the code above compilers would be likely to use the above pattern, and so counting how many bits are set in the pop instruction would reveal the whereabouts of the return address on the stack. One wouldn't know until runtime whether this test would actually work, but in cases where it claims to identify the return address it should actually be correct.
You can find all the answers in the Cortex-M documentation
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337h/Chdedegj.html

Understanding gdb format

I am trying to familiarize myself with gdb and had a few questions based upon its format and what it shows:
─── Assembly ────
0x00000000004004ed main+0 push %rbp
0x00000000004004ee main+1 mov %rsp,%rbp
!0x00000000004004f1 main+4 movl $0x539,-0x4(%rbp)
What does the memory address on the left column signify, and why is each instruction a variable-width "between" the next address?
What does the second column mean?
.
─── Registers ───────────────────────
rax 0x00000000004004ed
rbx 0x0000000000000000
rcx 0x0000000000000000
Is the value next to the register its memory location, or the value contained in the registry?
.
─── Stack ───────────────────
[0] from 0x000000000040058c in main+47 at main.c:7
What is this line telling us: does the stack start at memory address 0x000000000040058c, and what does the main+47 refer to?
What does the memory address on the left column signify, and why is
each instruction a variable-width "between" the next address?
x86 machine-code instructions are variable length. So some instructions take a single byte while for example movabs $0x12345678abcdef, %rax takes 10. The hard limit is 15 bytes, but only intentional padding with redundant prefixes can get all the way to 15.
Many other architectures are RISC and have fixed-width instructions.
What does the second column mean?
It tells you the relative address from the symbol main. Note that the actual location in memory is not assigned at compile time.
(Editor's note: this is not a PIE executable so the absolute address actually is set at link time. We can tell because the address is 0x00400... in the low 32 bits of address space, not 0x55555555....)
Is the value next to the register its memory location, or the value
contained in the registry?
Registers are not stored in memory (except in rare architectures); registers don't have addresses and are a separate space from memory. It's also not showing the value pointed to by a register that happens to be holding a valid address.
The value shown is the value in the resister itself. Note that rbx and rcx are both showing 0x0.
What is this line telling us: does the stack start at memory address
0x000000000040058c, and what does the main+47 refer to?
(editor's note: this part is wrong but I'm not sure enough exactly what it is to replace it with something else. But 0x40058c is definitely not a plausible value for RSP. main+47 is a code address somewhere inside main, like always for GDB symbol+number).
This is the location of the stack. Your code is small, so main is only taking space less than 48 addresses. Note that memory is normally allocated in blocks, so the stack would not appear at main+7, or whatever immediately follows the movl instruction.
#daShier's answer is mostly right, but is completely wrong about this part:
What is this line telling us: does the stack start at memory address
0x000000000040058c, and what does the main+47 refer to?
I think this is a qword value on the stack (pointed to by RSP). It's probably main's return address, or maybe just a value that was in RBP when main pushed it.
(But a return address is plausible: main starting at 0x4004ed is not far from 0x40058c).
main + 47 = 0x40051c is a code address inside main, corresponding to C source on line 7 of main.c. (main.c:7). This symbol+number is GDB's way of printing addresses in a human-readable way, relative to the closest symbol above them. i.e. what function they're in. ; I think that's the breakpoint you're stopped at when you copy/pasted this. It's telling you where execution is now. Or was when this snapshot of data on the stack was taken.
I'm not sure how you got GDB to print that Stack dump. It's a slightly different format from info stack or backtrace. TUI mode layout reg or any other layout doesn't include a Stack pane.
But anyway, 0x000000000040058c is most certainly not a stack address; it's in the same 4kiB virtual memory page as main so it's in the .text section. (In fact it's only 0x70 bytes past main + 47). That virtual page will be executable and not writeable.
RSP (stack pointer) values are things like 0x7ffff7fd4100, near the top of the lower 48 bits of virtual address space. (The top of the user-space part of the usable (canonical) part of virtual address space on x86-64).
As I said, main+47 is just a code address inside main. It has nothing to do with 47 or 48 bytes of stack space.

How assembly accesses/stores variables on the stack

In assembly You can store data in registers or on the stack. Only the top of the stack can be accessed at any given moment (right?). Consider the following C code:
main(){
int x=2;
func();
}
func( int x ){
int i;
char a;
}
Upon calling func() the following is pushed onto the stack (consider a 32bit system):
variable x (4 bytes, pushed by main)
<RETURN ADDRESS> (4 bytes pushed by main?)
<BASE POINTER> (4 bytes pushed by func())
variable i (4 bytes, pushed by func())
variable a (1 byte, pushed by func())
I have the following questions:
In C code you can access the local variable from anywhere inside the function, but in assembly you can only access the top of the stack. The C code is translated into assembly (in machine code but assembly is the readable form of it). So how does assembly support the reading of variables that are not on top of the stack?
Did I leave out anything that would also be pushed to the stack in my example?
In assembly if you push a char on the stack or an int, how can it determine whethere it needs to push 4 bytes or 1 byte? Because it uses the same operation (push) right?
Thanks in advance
Gr. Maricruzz
The stack pointer at the beginning of the function is put into a register, and then the variables/arguments are accessed via this base address plus the offset for the variable.
If you want to see the code, instead of creating object files, let the compiler stop at creating assembler files. Then you can see exactly how it works. (Of course, that requires you to have a valid C program, unlike the one you have in the question now.)
The compiler is generating the assembly, each instruction set may differ but at the end of the day the stack is just a register holding an address to memory. The compiler is creating and knows the whole scope of the function it is creating and knows how far down to find each data item on the stack for local data items, so it will then create the appropriate code based on that instruction set to access those local items.
Some instruction sets you need to make a copy of the stack pointer and/or do math with the stack pointer as an operand but some other register as a result of that math, then based on that math (stack pointer + 8 words for example) you access that memory address. Some instruction sets have an addressing mode where you can in the load or store apply an offset to the stack pointer the math is done as part of the instruction execution and you dont have to use an intermediate result and a register.
Only the top of the stack can be accessed at any given moment (right?)
No, generally the ISA has instructions to access other elements on the stack as well. That is, accessing elements on the stack is not limited to push and pop like operations; typically you can just mov things back and forth between a stack location and a register.
Assembly can accesss any memory by address (just like C).
Simple, not optimized programs would put all local variables on stack before method execution, so variables addresses are address of execution frame plus some shift.
Then program can simple use pop and push method to store additional variables (i.e. subresults of some expression) on the top of the stack.
Summary:
There is register (ESP in x86) pointing to the top of the stack
Calling push is moving variable to the top of the stack and increasing this register
Calling pop is moving variable from the top of the stack and decreasing this register
Calling mov is moving variable between memory and registers and do nothing to stack register (ESP).

What is exactly the base pointer and stack pointer? To what do they point?

Using this example coming from wikipedia, in which DrawSquare() calls DrawLine(),
(Note that this diagram has high addresses at the bottom and low addresses at the top.)
Could anyone explain me what ebp and esp are in this context?
From what I see, I'd say the stack pointer points always to the top of the stack, and the base pointer to the beginning of the the current function? Or what?
edit: I mean this in the context of windows programs
edit2: And how does eip work, too?
edit3: I have the following code from MSVC++:
var_C= dword ptr -0Ch
var_8= dword ptr -8
var_4= dword ptr -4
hInstance= dword ptr 8
hPrevInstance= dword ptr 0Ch
lpCmdLine= dword ptr 10h
nShowCmd= dword ptr 14h
All of them seem to be dwords, thus taking 4 bytes each. So I can see there is a gap from hInstance to var_4 of 4 bytes. What are they? I assume it is the return address, as can be seen in wikipedia's picture?
(editor's note: removed a long quote from Michael's answer, which doesn't belong in the question, but a followup question was edited in):
This is because the flow of the function call is:
* Push parameters (hInstance, etc.)
* Call function, which pushes return address
* Push ebp
* Allocate space for locals
My question (last, i hope!) now is, what is exactly what happens from the instant I pop the arguments of the function i want to call up to the end of the prolog? I want to know how the ebp, esp evolve during those moments(I already understood how the prolog works, I just want to know what is happening after i pushed the arguments on the stack and before the prolog).
esp is as you say it is, the top of the stack.
ebp is usually set to esp at the start of the function. Function parameters and local variables are accessed by adding and subtracting, respectively, a constant offset from ebp. All x86 calling conventions define ebp as being preserved across function calls. ebp itself actually points to the previous frame's base pointer, which enables stack walking in a debugger and viewing other frame's local variables to work.
Most function prologs look something like:
push ebp ; Preserve current frame pointer
mov ebp, esp ; Create new frame pointer pointing to current stack top
sub esp, 20 ; allocate 20 bytes worth of locals on stack.
Then later in the function you may have code like (presuming both local variables are 4 bytes)
mov [ebp-4], eax ; Store eax in first local
mov ebx, [ebp - 8] ; Load ebx from second local
FPO or frame pointer omission optimization which you can enable will actually eliminate this and use ebp as another register and access locals directly off of esp, but this makes debugging a bit more difficult since the debugger can no longer directly access the stack frames of earlier function calls.
EDIT:
For your updated question, the missing two entries in the stack are:
nShowCmd = dword ptr +14h
hlpCmdLine = dword ptr +10h
PrevInstance = dword ptr +0Ch
hInstance = dword ptr +08h
return address = dword ptr +04h <==
savedFramePointer = dword ptr +00h <==
var_4 = dword ptr -04h
var_8 = dword ptr -08h
var_C = dword ptr -0Ch
This is because the flow of the function call is:
Push parameters (hInstance, PrevInstance, hlpCmdLine, nShowCmd)
Call function, which pushes return address
Push ebp
Allocate space for locals
ESP (Stack Pointer) is the current stack pointer, which will change any time a word or address is pushed or popped on/off the stack. EBP (Base Pointer) is a more convenient way for the compiler to keep track of a function's parameters and local variables than using the ESP directly.
Generally (and this may vary from compiler to compiler), all of the arguments to a function being called are pushed onto the stack by the calling function (usually in the reverse order that they're declared in the function prototype, but this varies). Then the function is called, which pushes the return address (EIP, Instruction Pointer) onto the stack.
Upon entry to the function, the old EBP value is pushed onto the stack and EBP is set to the value of ESP. Then the ESP is decremented (because the stack grows downward in memory) to allocate space for the function's local variables and temporaries. From that point on, during the execution of the function, the arguments to the function are located on the stack at positive offsets from EBP (because they were pushed prior to the function call), and the local variables are located at negative offsets from EBP (because they were allocated on the stack after the function entry). That's why the EBP is called the Frame Pointer, because it points to the center of the function call frame.
Upon exit, all the function has to do is set ESP to the value of EBP (which deallocates the local variables from the stack, and exposes the entry EBP on the top of the stack), then pop the old EBP value from the stack, and then the function returns (popping the return address into EIP).
Upon returning back to the calling function, it can then increment ESP in order to remove the function arguments it pushed onto the stack just prior to calling the other function. At this point, the stack is back in the same state it was in prior to invoking the called function.
You have it right. The stack pointer points to the top item on the stack and the base pointer points to the "previous" top of the stack before the function was called.
When you call a function, any local variable will be stored on the stack and the stack pointer will be incremented. When you return from the function, all the local variables on the stack go out of scope. You do this by setting the stack pointer back to the base pointer (which was the "previous" top before the function call).
Doing memory allocation this way is very, very fast and efficient.
EDIT: For a better description, see x86 Disassembly/Functions and Stack Frames in a WikiBook about x86 assembly. I try to add some info you might be interested in using Visual Studio.
Storing the caller EBP as the first local variable is called a standard stack frame, and this may be used for nearly all calling conventions on Windows. Differences exist whether the caller or callee deallocates the passed parameters, and which parameters are passed in registers, but these are orthogonal to the standard stack frame problem.
Speaking about Windows programs, you might probably use Visual Studio to compile your C++ code. Be aware that Microsoft uses an optimization called Frame Pointer Omission, that makes it nearly impossible to do walk the stack without using the dbghlp library and the PDB file for the executable.
This Frame Pointer Omission means that the compiler does not store the old EBP on a standard place and uses the EBP register for something else, therefore you have hard time finding the caller EIP without knowing how much space the local variables need for a given function. Of course Microsoft provides an API that allows you to do stack-walks even in this case, but looking up the symbol table database in PDB files takes too long for some use cases.
To avoid FPO in your compilation units, you need to avoid using /O2 or need to explicitly add /Oy- to the C++ compilation flags in your projects. You probably link against the C or C++ runtime, which uses FPO in the Release configuration, so you will have hard time to do stack walks without the dbghlp.dll.
First of all, the stack pointer points to the bottom of the stack since x86 stacks build from high address values to lower address values. The stack pointer is the point where the next call to push (or call) will place the next value. It's operation is equivalent to the C/C++ statement:
// push eax
--*esp = eax
// pop eax
eax = *esp++;
// a function call, in this case, the caller must clean up the function parameters
move eax,some value
push eax
call some address // this pushes the next value of the instruction pointer onto the
// stack and changes the instruction pointer to "some address"
add esp,4 // remove eax from the stack
// a function
push ebp // save the old stack frame
move ebp, esp
... // do stuff
pop ebp // restore the old stack frame
ret
The base pointer is top of the current frame. ebp generally points to your return address. ebp+4 points to the first parameter of your function (or the this value of a class method). ebp-4 points to the first local variable of your function, usually the old value of ebp so you can restore the prior frame pointer.
Long time since I've done Assembly programming, but this link might be useful...
The processor has a collection of registers which are used to store data. Some of these are direct values while others are pointing to an area within RAM. Registers do tend to be used for certain specific actions and every operand in assembly will require a certain amount of data in specific registers.
The stack pointer is mostly used when you're calling other procedures. With modern compilers, a bunch of data will be dumped first on the stack, followed by the return address so the system will know where to return once it's told to return. The stack pointer will point at the next location where new data can be pushed to the stack, where it will stay until it's popped back again.
Base registers or segment registers just point to the address space of a large amount of data. Combined with a second regiser, the Base pointer will divide the memory in huge blocks while the second register will point at an item within this block. Base pointers therefor point to the base of blocks of data.
Do keep in mind that Assembly is very CPU specific. The page I've linked to provides information about different types of CPU's.

Resources