Search⌘ K
AI Features

Introduction to Pointers

Understand pointers as memory cells or registers holding addresses of other memory locations in Linux ARM64 debugging. Learn pointer arithmetic and indirection through examples involving registers and memory layouts, enhancing your low-level debugging and reverse engineering skills.

The concept of a pointer is one of the most important to thoroughly understand in order to master Linux debugging. By definition, a pointer is a memory cell or a processor register that contains the address of another memory cell, as shown in the illustration below. It has its own address as any memory cell. Sometimes, a pointer is called an indirect address (whereas, a direct address is the address of a memory cell).

Iteratively, we can define another level of indirection and introduce a pointer to a pointer as a memory cell or a processor register that contains the address of another memory cell, and so on.

Pointers example: Memory layout and registers

In our debugging example shown below, we have two memory addresses (locations), a and b. We can think about a and b as names of addresses (locations).

We also have registers x0 and x1 as pointers to a and b. These registers contain addresses of a and b, respectively. The notation [x0] means the contents of a memory cell whose address is in the register x0.

In C and C++, we declare and define pointers to a and b as follows:

C++
int *a, *b;

Our example memory layout, before program execution, is shown in the illustration below. Addresses always occupy 64-bit memory cells or full 64-bit registers like x0 or x1 (they cannot fit in w0 or w1 or a 32-bit memory cell). We also use lower halves of x2x4 registers and w2w4 to hold temporary integer values, if necessary.

Pointers example: Calculations

In order to understand pointers better from a low-level assembly language perspective, we perform arithmetic calculations using pointers to memory instead of direct memory addresses: