How does a debugger work in Linux? How does it gets 'attached' to an already running executable or process. I understand that compiler translates code to machine language, but then how does debugger 'know' what it is being attached to?
Linux – How does a debugger work in Linux
debugginglinux
Related Solutions
The file descriptor 1 translates to the stdout FILE structure in the Kernel's Open Files Table.
This is a misunderstanding. The kernel's file table has nothing whatsoever to do with user-space file structures.
In any event, the kernel has two levels of indirection. There is the internal structure that represents the file itself, which is reference counted. There is an "open file description" that is reference counted. And then there is the file handle, which is not reference counted. The file structure points the way to the inode itself. The open file description contains things like the open mode and file pointer.
When you call close, you always close the file handle. When a file handle is closed, the reference count on its open file description is decremented. If it goes to zero, the open file description is also released and the reference count on the file itself is decremented. Only if that goes to zero is the kernel's file structure freed.
There is no chance for one process to release a resource another process is using because shared resources are reference counted.
This reference seems to have answers to your questions, titled: Linux Kernel Development Second Edition.
excerpt
printk()
The kernel print function,
printk()
, behaves almost identically to the C libraryprintf()
function. Indeed, throughout this book we have not made use of any real differences. For most intentions, this is fine;printk()
is simply the name of the kernel's formatted print function. It does have some differences, however.The Robustness of printk()
One property of
printk()
quickly taken for granted is its robustness. Theprintk()
function is callable from just about anywhere in the kernel at any time. It can be called from interrupt or process context. It can be called while a lock is held. It can be called simultaneously on multiple processors, yet it does not require the caller to hold a lock.It is a resilient function. This is important because the usefulness of
printk()
rests on the fact that it is always there and always works.The Nonrobustness of printk()
A chink in the armor of
printk()
's robustness does exist. It is unusable before a certain point in the kernel boot process, prior to console initialization. Indeed, if the console is not initialized, where is the output supposed to go?This is normally not an issue, unless you are debugging issues very early in the boot process (for example, in
setup_arch()
, which performs architecture-specific initialization). Such debugging is a challenge to begin with, and the absence of any sort of print method only compounds the problem.There is some hope, but not a lot. Hardcore architecture hackers use the hardware that does work (say, a serial port) to communicate with the outside world. Trust me this is not fun for most people. Some supported architectures do implement a sane solution, however and others (i386 included) have patches available that also save the day.
The solution is a
printk()
variant that can output to the console very early in the boot process:early_printk()
. The behavior is the same asprintk()
, only the name and its capability to work earlier are changed. This is not a portable solution, however, because not all supported architectures have such a method implemented. It might become your best friend, though, if it does.Unless you need to write to the console very early in the boot process, you can rely on
printk()
to always work.
Best Answer
There is a system call named ptrace. It takes 4 parameters: the operation, the PID of the target process, an address in the target process memory, and a data pointer. The way the last 2 parameters are used is dependent on the operation.
For example you can attach/detach your debugger to a process:
Single step execution:
You can also read/write the memory of the target process with PTRACE_PEEKDATA and PTRACE_POKEDATA. If you want to see a real example check out gdb.