The user_regs_struct structure for x86_64 contains the general-purpose registers, segmentation registers, stack pointer, instruction pointer, CPU flags, and TLS registers:
<sys/user.h>
struct user_regs_struct
{
__extension__ unsigned long long int r15;
__extension__ unsigned long long int r14;
__extension__ unsigned long long int r13;
__extension__ unsigned long long int r12;
__extension__ unsigned long long int rbp;
__extension__ unsigned long long int rbx;
__extension__ unsigned long long int r11;
__extension__ unsigned long long int r10;
__extension__ unsigned long long int r9;
__extension__ unsigned long long int r8;
__extension__ unsigned long long int rax;
__extension__ unsigned long long int rcx;
__extension__ unsigned long long int rdx;
__extension__ unsigned long long int rsi;
__extension__ unsigned long long int rdi;
__extension__ unsigned long long int orig_rax;
__extension__ unsigned long long int rip;
__extension__ unsigned long long int cs;
__extension__ unsigned long long int eflags;
__extension__ unsigned long long int rsp;
__extension__ unsigned long long int ss;
__extension__ unsigned long long int fs_base;
__extension__ unsigned long long int gs_base;
__extension__ unsigned long long int ds;
__extension__ unsigned long long int es;
__extension__ unsigned long long int fs;
__extension__ unsigned long long int gs;
};In the 32-bit Linux kernel, %gs was used as the thread-local-storage (TLS) pointer, although since x86_64, the %fs register has been used for this purpose. Using the registers from user_regs_struct and with read/write access to a process's memory using ptrace, we can have complete control over it. As an exercise, let's write a simple debugger that allows us to set a breakpoint at a certain function in a program. When the program runs, it will stop at the breakpoint and print the register values and the function arguments.