Reputation: 25
I hate asking syntax questions like this, but I've not been able to find an answer through searching. I'm unsure as to what each of these variable declarations means. My best guess for the 3rd was that it's taking the logical and of the address of the label checkpoint and the inverse of the size of the page, casting it as an unsigned long, then recasting it as a void pointer. The code is from here: http://nmav.gnutls.org/2011/12/self-modifying-code-using-gcc.html
int (*my_printf) (const char *format, ...);
void (*my_exit) (int);
void *page =
(void *) ((unsigned long) (&&checkpoint) &
~(getpagesize() - 1));
Thanks!
Upvotes: 2
Views: 149
Reputation: 13171
my_printf
is a pointer for a function returning an int, and which takes a char pointer argument and a variable list of others.
my_exit
is a pointer to a function with no return value, taking one int argument.
page
is a pointer to some unspecified type. It is assigned the value of an expression that shouldn't compile, because &&
is a binary operator and has no left operand, and unary address-of-address is meaningless. The & ~(getpagesize() - 1)
bit masks off the low-order bits of what presumably is meant to be an address, which would then point to the beginning of a page.
The unary &&
is a GNU C extension that takes the address of a (goto) label, so this construction basically gets the address of the start of the code page containing that label. This is very compiler- and OS-specific stuff, and not really part of the C language.
Upvotes: 5
Reputation: 1887
int (*my_printf) (const char *format, ...);
declares a function pointer that returns an int, and takes a c style string as a first parameter, with a variable number of arguments after the format parameter.
void (*my_exit) (int);
declares a function pointer that doesn't return anything, but takes an int.
void *page = (void *) ((unsigned long) (&&checkpoint) & ~(getpagesize() - 1));
declares a generic pointer that is equivalent to the address of the pointer to checkpoint
masked with the page size minus one.
Upvotes: 0
Reputation: 780974
The first two are function pointers that are compatible with printf
and exit
, respectively. E.g. you can do:
my_exit = exit;
my_exit(3);
and it would be equivalent to calling exit(3)
.
Your guess about the third is correct. It's depending on the fact that page size will always be a power of 2. Therefore, pagesize-1
will have a binary pattern that's all 1's in the low-order bits, all 0's in the high-order bits. Inverting it reverses those bits. This can be used as a bit mask with an address to return the address of the beginning of the page that the address points to. It then sets page
to the beginning of the page containing checkpoint
.
Upvotes: 0