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)?
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With