Given stack pointer value, is it possible to determine the value of the passed arguments to the function? Where are the arguments stored in the stack frame.
Lets say, executing gcc compiled ELF binary on x86 architecture on Linux platform:
int foo(int a, int b)
{
...
}
foo(a,b) is called from main() and I know the stack pointer(SP) value which is pointing to foo() now. How can I retrive the value of arguments a and b?
EDIT: If stack grows from smaller address to larger address, and arguments are passed right to left using cdecl, can I obtain args value like this:
b = *(SP + 1);
a = *(SP + 2);
EDIT: The following program prints the value of functions args a, b using above arch and specifications.
void foo(int a, int b)
{
int i;
register int stackptr asm("sp");
int *sp = (int *)stackptr;
printf("\n\ta=%d b=%d\n", a, b);
for (i=0; i<16; i++) {
printf("*(sp + %d) = %d\n", i, *(sp +i));
}
}
int main()
{
foo(3, 8);
foo(9, 2);
foo(1, 4);
return 0;
}
The output of above code is:
a=3 b=8
*(sp + 0) = 134514016
*(sp + 1) = 0
*(sp + 2) = 0
*(sp + 3) = 134513373
*(sp + 4) = 8239384
*(sp + 5) = 134513228
*(sp + 6) = 6
*(sp + 7) = -1076716032
*(sp + 8) = 134513456
*(sp + 9) = 0
*(sp + 10) = -1076715960
*(sp + 11) = 134513759
*(sp + 12) = 3 //value of arg a
*(sp + 13) = 8 //value of arg b
*(sp + 14) = 134513817
*(sp + 15) = 10612724
a=9 b=2
*(sp + 0) = 134514016
*(sp + 1) = 0
*(sp + 2) = 0
*(sp + 3) = 134513373
*(sp + 4) = 8239384
*(sp + 5) = 134513228
*(sp + 6) = 6
*(sp + 7) = -1076716032
*(sp + 8) = 134513456
*(sp + 9) = 0
*(sp + 10) = -1076715960
*(sp + 11) = 134513779
*(sp + 12) = 9 //value of arg a
*(sp + 13) = 2 //value of arg b
*(sp + 14) = 134513817
*(sp + 15) = 10612724
a=1 b=4
*(sp + 0) = 134514016
*(sp + 1) = 0
*(sp + 2) = 0
*(sp + 3) = 134513373
*(sp + 4) = 8239384
*(sp + 5) = 134513228
*(sp + 6) = 6
*(sp + 7) = -1076716032
*(sp + 8) = 134513456
*(sp + 9) = 0
*(sp + 10) = -1076715960
*(sp + 11) = 134513799
*(sp + 12) = 1 //value of arg a
*(sp + 13) = 4 //value of arg b
*(sp + 14) = 134513817
*(sp + 15) = 10612724
Why function arguments are stored from offset 12 of SP? Also notice values at offset 0 to 10 are always same, and value at offset 11 increases by 20 on each invocation of function foo().
UPDATE: I found that gcc has in-build function to retrieve frame pointer address
void * __builtin_frame_address (unsigned int level)
When I print values at offsets starting from __builtin_frame_address(0) the function arguments start from offset 2. How can I confirm that this behavior is always consistent?
You must know the calling convention to know what order the arguments are pushed onto the stack, or even if they are on the stack. Many pass the first few arguments in registers. Even on x86, you have fastcall, pascal, register, stdcall and cdecl, just to name a few.
EDIT: Don't forget that printf is also a function, and local variables also go on the stack. So, in your sample app, you have your parameters (since it's cdecl), then your locals, then your function saved state and return address, then parameters to printf (maybe, not sure if it's cdecl or fastcall), then printf's locals by the time anything actually makes it to the screen.
There's no easy way and certainly there's no portable way (for the same source file this could even change between gcc 4.1 and gcc 4.2) but gdb sure can do it. Using gcc, you can probably find all you need analyzing the DWARF info.
gdb also uses prologue analysis to detect how local variables are assigned in the stack (among other things) but I'm not sure if something like a "calling analysis" exists in gdb's source. May be reading prologue-value.h in gdb's source could help you.
The local variables are allocated on the stack, thus variables i, stackptr and sp are allocated on the call stack. So, if we print all the stack records we will find these variables, then the return pointer, then the saved frame pointer (if saved) and then the function parameters. Hence, in example above the args start at 12.
If you want to access immediately to the function call parameters you should start from the frame pointer address obtained using __builtin_frame_address(unsigned int level). Arguments are pushed on the stack before the saved frame pointer, thus you have to add an offset equal to the frame pointer address size if you start from the beginning of the saved frame pointer record on the stack. Hence, in example above, args start at offset 2.
Related
I need a branchless number cycle code.
like this:
int i = 0;
i = (i + 1) % 4 //1
i = (i + 1) % 4 //2
i = (i + 1) % 4 //3
i = (i + 1) % 4 //0
i = (i + 1) % 4 //1
...
But it should work in the reverse order of the code above. (3 > 2 > 1 > 0 > 3 > ...)
I first tried "i = (i - 1) % 4".
But this worked differently than I wanted. (-1 > -2 > -3 > 0 > -1 > ...)
However, if I use the method of adding 4 when i is negative, this code is no longer branchless.
How can I implement the functionality which I want (without additional variables or arrays)?
(This article has been translated by Google Translate.)
The error happens because in C89 the remainder of negative numbers was underspecified and from C99, negative % positive will result in a negative number which is unlike in some programming languages such as Python, where (-1) % 4 would indeed result in 3.
But it is easy to circumvent. When you subtract 1, it is the same as adding -1. Since 0 - 1 will get to -1, we would have a negative remainder. To stay positive, instead of adding the negative -1 we can add a positive number that's congruent to -1 (mod m). The smallest positive such number is m - 1 for an m > 1. Therefore we can use:
#define MODULUS 4 // or any other moduli > 1
int i = 0;
i = (i + (MODULUS - 1)) % MODULUS; //3
i = (i + (MODULUS - 1)) % MODULUS; //2
i = (i + (MODULUS - 1)) % MODULUS; //1
i = (i + (MODULUS - 1)) % MODULUS; //0
i = (i + (MODULUS - 1)) % MODULUS; //3
You need to change your expression a bit. It should be:
i = ( i + 3 ) % 4;
In general, if you want a number in range [0,N-1] with such cycle then the equation should be:
i = (i + (N - 1)) % N;
You can see it working here(manually several times) and here (in loop):
int main()
{
int i = 0;
i = ( i + 3 ) % 4; //3
i = ( i + 3 ) % 4; //2
i = ( i + 3 ) % 4; //1
i = ( i + 3 ) % 4; //0
i = ( i + 3 ) % 4; //3
i = ( i + 3 ) % 4; //2
i = ( i + 3 ) % 4; //1
i = ( i + 3 ) % 4; //0
return 0;
}
You can use unsigned arithmetic, then the numbers won't become negative.
unsigned i = 0;
i = (i - 1) % 4 //3
i = (i - 1) % 4 //2
i = (i - 1) % 4 //1
i = (i - 1) % 4 //0
i = (i - 1) % 4 //3
Also, maybe more intuitive, you can use bitwise operations to implement a 2-bit counter.
unsigned i = 0;
i = (i - 1) & 3;
i = (i - 1) & 3;
i = (i - 1) & 3;
i = (i - 1) & 3;
i = (i - 1) & 3;
On machine code level, this is identical to the code above.
There are two cases:
Case 1: The modulo is a power of 2
In this case, you can simply use unsigned arithmetic with a bit mask:
unsigned i = ...;
i = (i - 1) & (modulo - 1);
When i = 0, subtracting 1 will yield a value with all bits set in unsigned arithmetic, and the mask operation & will yield the value modulo - 1.
Case 2: The modulo is not a power of 2
In this case, no fancy bit tricks work. You can only avoid going negative:
i = (i + modulo - 1) % modulo;
As the title suggests, I am using the following function to read the parameters of some g-code files present on the SD card:
long parseParameters(String data, char* c){
int offset = data.indexOf(c);
int offset1 = data.lastIndexOf(" ", offset + 1);
return offset1 > 0 ? data.substring(offset + 1, offset + offset1 + 1).toInt() : data.substring(offset + 1).toInt();
}
void setup(){
Serial.begin(9600);
String q = "P3 S255"; // input
Serial.println(parseParameters(p, "S")); // output
}
void loop(){
}
Only today, in an attempt to read the value of S in the string P3 S255 has emerged in a small bug:
INPUT -> OUTPUT
P3 S255 -> 25 (wrong)
A20 P3 S255 -> 255 (Correct)
S255 -> 255 (Correct)
Why? Yet the code would seem correct to me..where did I go wrong?
Thanks in advance to everyone.. :)
Thats the explanation:
int offset = data.indexOf(c); //in your example S
"P3 S255";
^
offset = 3
then you parse for offset1 but take another param namely " " after offset - but there is no " " in the string from offset+1 see above where the index is so it returns -1 why?
myString.lastIndexOf(val, from) The index of val within the String, or -1 if not found. But we find something:
offset = 3;
offset1 = 2 ==> offset1 > 0 ==> data.substring(offset + 1, offset + offset1 + 1).toInt()
which leads to
data.substring(3 + 1, 3 + 2 + 1).toInt()
"P3 S*4*25*6*5"; which results to 25 as you already know
to (optional): the index to end the substring before.
So you have correct for the S in the begin by changing to
data.substring(offset + 1, offset + 1 + offset1 + 1).toInt()
Explanation: You start at offset + 1 this has to be equal in from and to (= same starting point for your calculation)
I found a recursion function in GeeksforGeeks website. Can someone explain how this function works?
int fun1(int x, int y)
{
if(x == 0)
return y;
else
return fun1(x - 1, x + y);
}
It says it will return y+(x+x-1+x-2+x-3+...2+1). I appreciate if someone can explain why. I thought it should return y+1 as when x becomes 1 on stack memory, it will return y+1 (since x-1 becomes 0), and eventually it will return the other functions on stack as y+1 until the early first function.
You're right that when x == 1, this returns y+1. But for the other cases, remember that y is also different between the calls. For example, when x==2, it calls fun1(2 - 1, 2 + y), so for the next invocation y is two more than it was before. This next invocation has x == 1, so it ends up returning one more than the y it has, which itself is 2 more than the original value, so the call to fun1(2, y) returns y + 2 + 1.
An illustration of the call stack might be more helpful. Let's say we call fun1(5, 7).
fun1(5, 7) returns the value of fun1(5 - 1, 5 + 7)
fun1(4, 12) returns the value of fun1(4 - 1, 4 + 12)
fun1(3, 16) returns the value of fun1(3 - 1, 3 + 16)
fun1(2, 19) returns the value of fun1(2 - 1, 2 + 19)
fun1(1, 21) returns the value of fun1(1 - 1, 1 + 21)
fun1(0, 22) returns 22.
Thus, all together (and rearranging slightly), the fun1(5, 7) call returned 7 + (5 + 4 + 3 + 2 + 1), as the documentation said.
The function fun() calculates and returns ((1 + 2 … + x-1 + x) +y) which is x(x+1)/2 + y. For example if x is 5 and y is 2, then fun() should return 15 + 2 = 17.
I am trying Pthreads and its pretty basic program: I have two shared variables (declared global) among all threads
long Sum = 0;
long Sum1 = 0;
pthread_mutex_t mutexLock = PTHREAD_MUTEX_INITIALIZER;
In thread function:
for(int i=start; i<end; i++) //start and end are being passed to thread and they are being passed correctly
{
pthread_mutex_lock(&mutexLock);
Sum1+=i;
Sum+=Sum1;
pthread_mutex_unlock(&mutexLock);
}
main() in case one needs for reference:
int main()
{
pthread_t threadID[10];
for(int i=0; i<10; i++)
{
int a = (i*500) + 1;
int b =(i + 1)*500;
ThreadStruct* obj = new ThreadStruct(a,b);
pthread_create(&threadID[i],NULL,ThreadFunc,obj);
}
for(int i=0; i<10; i++)
{
pthread_join(threadID[i], NULL);
}
cout<<"Sum: "<<Sum<<endl;
cout<<"Sum1: "<<Sum1<<endl;
return 0;
}
OUTPUT
Sum: 40220835000
Sum1: 12502500
Run again
Sum: 38720835000
Sum1: 12502500
Run again
Sum: 39720835000
Sum1: 12502500
PROBLEM
Why I am getting a different value for Sum in each iteration?
Rest whole code is working ok and output of Sum1 is correct - no matter how much times do I run the code. (Only issue is in Sum). Am I doing something wrong in use of mutex here?
UPDATE
If I use local variables as #molbdnilo specified in his well detailed answer, this problem is solved. In start, I thought that mutex is irrelevant here but I tested it a number of times and observed the cases when not using a mutex results in recurrence of this problem. So, solution of this problem (courtesy: Answer by #molbdnilo) is to use local variables WITH mutex and I have tested it to work perfectly!
It's not a threading problem – the problem is that even though the order of additions to Sum1 doesn't matter, the order of additions to Sum does.
Consider the much shorter sum 1 + 2 + 3 and the following interleavings
1:
Sum1 = 1 + 2 = 3
Sum = 0 + 3 = 3
Sum1 = 3 + 3 = 6
Sum = 3 + 6 = 9
2:
Sum1 = 1 + 3 = 4
Sum = 0 + 4 = 4
Sum1 = 4 + 2 = 6
Sum = 4 + 6 = 10
3:
Sum1 = 2 + 3 = 5
Sum = 0 + 5 = 5
Sum1 = 5 + 1 = 6
Sum = 5 + 6 = 11
You could solve this by having the threads compute their own sum-of-sums independently and adding them afterwards.
(Notice that there's no concurrent mutation here, so locking anything can't make any difference.)
For a more concrete example, let's limit your program to two threads and the sum from 1 to 6.
You then have one thread computing 1 + 2 + 3 and one doing 4 + 5 + 6.
At a glance, thread one should also compute 1 + (1 + 2) + (1 + 2 + 3) and thread 2, 4 + (4 + 5) + (4 + 5 + 6).
Except they don't – every time they use it, Sum may have been modified by the other thread.
So thread one may compute 1 + ((1 + 4) + 2) + ((1 + 4) + 2 + 3), or something else.
When you use local variables, you keep each thread's result independent of the others.
(I think this problem is a pretty good illustration of how shared mutable state can complicate things in unexpected ways, by the way.)
It is my understanding that rand() % a + b will return numbers between a and b including both a and b. I must be misunderstanding this though, because when I run the code below int r will return 2, 3, or 4. I, of course, am expecting it to return 2 or 3. I'm calling srand(time(NULL)); in main and I'm using
#include <time.h> and #include <stdlib.h>
Am I missing something?
int r = (rand() % 3) + 2;
if (r ==2)
g_fan.draw(r); // skin == 2
else
g_fan.draw(1 + r); //skin == 4
It is my understanding that rand() % a + b will return numbers between a and b including both a and b.
No. It will result in a number between b and (a+b-1), both including.
Range of values of rand() % a is 0 and a-1, both including.
Hence, the range of values of rand() % a + b is b and (a-1+b), both including.
To get random values between a and b, both including, use:
auto interval = (b-a+1);
auto result = a + rand() % interval;
let num be any number you get by calling rand() and if you do % with 3 , there is a possibility of getting one of these number 0, 1, 2.
therefore you are getting 2 ,3, 4 for :
int r = (rand() % 3) + 2;
int r = (rand() % 3) + 2;
The rand() % 3 will return a number between 0 and 2. When you add t2 to each number, that means it will return 2 to 4. The rand() % afunction in general returns a value form 0 to a - 1. When you do rand() % a + b, then the resulting value will range from 0 + b to a - 1 + b.
To get a value between 2 and 3, use:
int r = (rand() % 2) + 2;
The folloing rand() function gives a number from 0 to 2 - 1, which is 1. When you add 2 to each number, you get a range of 0 + 2, which is 2, to 2 - 1 + 2, which is 3.