Question
How do you count the number of set bits (popcount) in an integer?
Answer
Either loop testing one bit at a time, use Brian Kernighan's x &= x-1 trick to loop once per set bit, or call a compiler builtin like __builtin_popcount(x).
* x & (x−1) zeroes the lowest set bit, so looping it runs exactly once per set bit — Brian Kernighan's popcount. *
Simple loop method:
int popcount(unsigned int x) {
int count = 0;
while (x) {
// Add lowest bit
count += x & 1;
// Shift right
x >>= 1;
}
return count;
}
Brian Kernighan's trick (faster - only loops for set bits):
int popcount(unsigned int x) {
int count = 0;
while (x) {
// Clear lowest set bit
x &= (x - 1);
count++;
}
return count;
}
Why x & (x-1) clears the lowest set bit:
x = 01011000
x-1 = 01010111 (borrows from lowest 1)
x&x-1 = 01010000 (lowest 1 is gone!)
Compiler builtin (fastest - uses CPU instruction):
// GCC/Clang
int count = __builtin_popcount(x);
// MSVC
int count = __popcnt(x);
Use case in RE: Counting flags, Hamming distance, parity checks.
Go deeper:
Hamming weight — Wikipedia — popcount algorithms, Kernighan's trick, and hardware instructions.
Note saved — thanks!
Question
What is position-independent code (PIC) and why is it used?
Answer
PIC is code that runs correctly no matter what address it's loaded at, because it never hard-codes absolute addresses.
* Position-independent code avoids absolute addresses: nearby data is RIP-relative, external data goes through the GOT, external calls through the PLT — enabling ASLR. *
A shared library can be mapped to a different address in every process, so its code can't assume "my data is at 0x4000." PIC solves this by computing addresses relative to the current instruction instead.
Why it's needed:
- Shared libraries must load at arbitrary addresses (and be shared between processes)
- ASLR (Address Space Layout Randomization) deliberately randomizes load addresses as a security defense, so nothing can be hard-coded
How it works:
- RIP-relative addressing reaches nearby data:
mov global_var(%rip), %eaxcomputes the address from the program counter - A Global Offset Table (GOT) holds addresses of external data
- A Procedure Linkage Table (PLT) handles calls to external functions
mov global_var, %eax # non-PIC: hard-coded absolute address
mov global_var(%rip),%eax # PIC: address computed from %rip
You build it with gcc -fPIC -shared lib.c -o lib.so.
Go deeper:
Position-independent code (Wikipedia) — RIP-relative addressing, GOT/PLT, shared libraries and ASLR.
Note saved — thanks!