LOGBOOK

HELP

1 / 427
time's up — finish this card
Other keys: show • Space: good • 1-4: rate • 0: skip • 5: flag
Topic C Programming

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) clears the lowest set bit

* 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:

A plot of Hamming weight for numbers 0 to 256[4]
A plot of Hamming weight for numbers 0 to 256[4]
Laurence R. Ugalde URL: https://formulae.org/?script=examples/Population_count  This image was created with Fōrmulæ. · CC BY-SA 4.0 · Wikimedia Commons
or press any other key
Topic The Processor Interface

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.

PIC reaching nearby data RIP-relative, external data via the GOT and calls via the PLT.

* 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), %eax computes 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:

or press any other key