Print resolution by character
I am writing a small program that keeps track of all system calls and binary (elf) calls using ptrace (singlelestep, getregs, pick_text, opcode comparison, etc.).
So far, I've managed to keep track of system calls and simple calls like custom functions.
But I was unable to get the name of the printf symbol from the address I choose, thanks to ptrace.
My question is: . For a dynamic linked function like printf, strlen, etc., how can I get the character name from the address in the elf file?
With simple calls this is easy, I go through the .strtab section and when the address matches, it returns the corresponding string.
But for printf the character is known in .strtab, but has the address "0".
objdump -d somehow managed to bind the printf call to its address.
Do you have any ideas?
source to share
I think you might need to read a little about dynamic linking. Let's take strlen
an example as a symbol, as it is a printf
little special (fortification material).
Your problem (I think) is that you want to take the address of the character and translate it back into the address. You are trying to do this by parsing the ELF file of the program you are debugging. This works for symbols that are in your program, but not dynamically linked symbols like strlen
. And you want to know how to resolve this.
The reason for this is because the address of characters such as strlen
is not stored in your ELF program. Instead, they are unresolved links that are dynamically resolved when the program is loaded. Indeed, modern Linux (I suppose) loads dynamic libraries (which contain relocatable or position-independent code) in randomized order and randomized addresses, so the location of these symbols is not known until the program is loaded.
For libraries that you opened with dlopen()
(i.e. where you load yourself into a program), you can get the address of such symbols using dlsym()
; which is not good if they are linked to the program at compile / link time.
In gcc, to resolve character position in general, use the gcc extension dladdr()
. From the man page:
The function dladdr() takes a function pointer and tries to
resolve name and file where it is located. Information is
stored in the Dl_info structure:
typedef struct {
const char *dli_fname; /* Pathname of shared object that
contains address */
void *dli_fbase; /* Address at which shared object
is loaded */
const char *dli_sname; /* Name of nearest symbol with address
lower than addr */
void *dli_saddr; /* Exact address of symbol named
in dli_sname */
} Dl_info;
If no symbol matching addr could be found, then dli_sname and
dli_saddr are set to NULL.
dladdr() returns 0 on error, and nonzero on success.
I believe this will work for you.
For more information, I suggest you look at the source on ltrace
which tracks library calls and how backtrace_symbols
(and here ) it works; note that this will be unreliable for non-global characters in particular, and note that re-adding the comment -r dynamic
to the link line.
source to share