user2142343
user2142343

Reputation: 25

Unable to figure out what this c syntax is

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

Answers (3)

Lee Daniel Crocker
Lee Daniel Crocker

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

Tawnos
Tawnos

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

Barmar
Barmar

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

Related Questions