Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use a function parameter 'foo' in this way: *(&foo)?

A code snippet in Linux kernel 0.12 use a function parameter like this:

int do_signal(int signr, int eax /* other parameters... */) {     /* ... */      *(&eax) = -EINTR;      /* ... */ } 

The purpose of the code is to put -EINTR to the memory where eax lives, but I can not tell why it won't work if just assigning to eax:

eax = -EINTR 

How would the compiler make a difference between eax and *(&eax)?

like image 276
Gurity Avatar asked Aug 27 '14 14:08

Gurity


People also ask

Why do we use parameters in functions?

A function can take parameters which are just values you supply to the function so that the function can do something utilising those values. These parameters are just like variables except that the values of these variables are defined when we call the function and are not assigned values within the function itself.

What is a void * parameter?

In computer programming, when void is used as a function return type, it indicates that the function does not return a value. When void appears in a pointer declaration, it specifies that the pointer is universal. When used in a function's parameter list, void indicates that the function takes no parameters.

How do parameters work in functions?

A function parameter is a variable used in a function. Function parameters work almost identically to variables defined inside the function, but with one difference: they are always initialized with a value provided by the caller of the function.

What do parameters do in code?

Parameters allow a function to perform tasks without knowing the specific input values ahead of time. Parameters are indispensable components of functions, which programmers use to divide their code into logical blocks.


1 Answers

The old Linux you posted was trying to perform an very fragile hack. The function was defined like this:

int do_signal(long signr,long eax,long ebx, long ecx, long edx, long orig_eax,     long fs, long es, long ds,     long eip, long cs, long eflags,     unsigned long * esp, long ss) 

The function arguments don't actually represent arguments to the function (except signr), but the values that calling function (a kernel interrupt/exception handler written in assembly) preserved on the stack before calling do_signal. The *(&eax) = -EINTR statement is meant to modify the preserved value of EAX on the stack. Similarly the statement *(&eip) = old_eip -= 2 is meant to modify the return address of the calling handler. After do_signal returns the handler pops the first 9 "arguments" off the stack restoring them to the named registers. It then executes an IRETD instruction that pops the remaining arguments off the stack and return to user mode.

Needless to say this hack is incredibly unreliable. It's dependent on the compiler generating code exactly the way they expected it to. I'm surprised it even worked the GCC compiler of the era, I doubt it was long before GCC introduced an optimization that broke it.

like image 151
Ross Ridge Avatar answered Sep 21 '22 20:09

Ross Ridge