paseena
paseena

Reputation: 4315

Please help me understand this bit-wise manipulation of pointer values

I am not able to understand why is addr being typecasted to long, and then complemented with expression.. basically the whole line involving the calculation of peekAddr

void *addr;
char *peekAddr ;
peekAddr = (char *) ((long)addr & ~(sizeof(long) - 1 ) ) ;
peekWord = ptrace( PTRACE_PEEKDATA, pid, peekAddr, NULL ) ;

Upvotes: 2

Views: 1415

Answers (5)

Fred Foo
Fred Foo

Reputation: 363817

It's cast to long because (1) you can't do any operations on a void* except cast it and (2) on the author's platform, a void* value just so happens to fit in a long. He should really have used uintptr_t or size_t instead.

What the piece of code does:

sizeof(long) - 1

is most likely either 3 or 7, depending on the platform.

~(sizeof(long) - 1)

is a bitmask that selects all but the last few bits.

((long)addr & ~(sizeof(long) - 1))

is addr rounded down/aligned to address a long-sized chunk. Rounding occurs because the last lg(3) or lg(7) bits are zeros while the rest is copied from addr (where lg is integer binary logarithm).

Upvotes: 4

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215547

This is a really ugly, unportable way of doing

peakAddr = (char *)addr - ((uintptr_t)addr & -(uintptr_t)sizeof(long));

Note that the original version not only relies on successful round trip conversion of pointers to long and back, but also on size_t (the type of the result of the sizeof operator) being the same width or wider than long. If it's not, the bitmask generated with ~ would zero-extend in the upper bits and obliterate part of the pointer.

Basically, you should make a mental note that whatever program you found this in is bad code and not look to it as a source of ideas...

Upvotes: 3

Mark Ransom
Mark Ransom

Reputation: 308520

This will have a bug on some compilers where sizeof(long) < sizeof(char*), such as Microsoft's.

sizeof(long)-1 is creating a bit mask corresponding to the size of a long. This is a trick that only works on numbers that are a power of 2. The ~ in front inverts it, so now it's a mask of all the address bits that should remain unchanged when you're trying to align an address. The bitwise & is clearing the bottom bits of the address to make it align.

Upvotes: 1

fazo
fazo

Reputation: 1827

sizeof (long)     = (0)00000100
sizeof(long)-1    = (0)00000011
~(sizeof(long)-1) = (1)11111100

so 2 bits set to 0 make the address aligned to 4 bytes. additionally it's mostly used when the address was already incremented by sizeof(long)-1

Upvotes: 5

Mario The Spoon
Mario The Spoon

Reputation: 4869

you basically make peekAddr always aligned on sizeof(long) adresses. the line generates a bitmask and binary ands this to the peek address. The line strips the last sizeof(long)-1 bits from the peekAddr.

hth

Mario

Upvotes: 1

Related Questions