LINUX.ORG.RU

Как узнать реальный, не plt, адрес библиотечной функции

 ,


0

3
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void) {
	printf("printf address: %p\n", printf);

	char cmd[50];
	snprintf(cmd, 50, "cat /proc/%d/maps", getpid());
	system(cmd);

	return 0;
}

Этот код выводит адрес в plt в исполняемом файле. Мне нужен реальный адрес printf, там, куда ld.so загрузил libc. Как?


#define _GNU_SOURCE
#include <dlfcn.h>

dlsym(RTLD_NEXT, "printf");

выводит другой адрес, но может есть варианты получше.

В man dladdr:

The problem is that the function pointer will still be resolved at compile time,
but merely point to the plt (Procedure Linkage Table) section of the original
object (which dispatches the  call  after  asking the  dynamic  linker to
resolve the symbol).  To work around this, you can try to compile the code to be
position-independent: then, the compiler cannot prepare the pointer at compile
time any more and gcc(1) will generate code that just loads the final symbol
address from the got (Global Offset Table) at run time before passing it to dladdr().

xaizek ★★★★★
()

Этот код выводит адрес в plt в исполняемом файле. Мне нужен реальный адрес printf, там, куда ld.so загрузил libc. Как?

Если переносимость между архитектурами не нужна, то по тому адресу находится один джамп с нужным тебе адресом. Правда, не адрес, а смещение с текущего места (следующая инструкция), но он тебе ведь известен.

printf address: 0x4004d0
(gdb) disas 0x4004d0
Dump of assembler code for function printf@plt:
   0x00000000004004d0 <+0>:	jmpq   *0x200b52(%rip)        # 0x601028
   0x00000000004004d6 <+6>:	pushq  $0x2
   0x00000000004004db <+11>:	jmpq   0x4004a0
End of assembler dump.
0x4004d0 <printf@plt>:	0xff	0x25	0x52	0x0b	0x20	0x00	0x68	0x02

0x200b52 + 0x4004d6 = 0x601028

Ой, то есть, это будет указатель на global offset table, и вот уже там-то будет указатель на printf:

(gdb) x/g 0x601028
0x601028:	0x00007ffff7a61230
(gdb) disas 0x00007ffff7a61230
Dump of assembler code for function printf:
   0x00007ffff7a61230 <+0>:	sub    $0xd8,%rsp
   0x00007ffff7a61237 <+7>:	test   %al,%al
   0x00007ffff7a61239 <+9>:	mov    %rsi,0x28(%rsp)
   0x00007ffff7a6123e <+14>:	mov    %rdx,0x30(%rsp)
   0x00007ffff7a61243 <+19>:	mov    %rcx,0x38(%rsp)
   0x00007ffff7a61248 <+24>:	mov    %r8,0x40(%rsp)
   0x00007ffff7a6124d <+29>:	mov    %r9,0x48(%rsp)
   0x00007ffff7a61252 <+34>:	je     0x7ffff7a6128b <printf+91>
   0x00007ffff7a61254 <+36>:	movaps %xmm0,0x50(%rsp)
   0x00007ffff7a61259 <+41>:	movaps %xmm1,0x60(%rsp)
   0x00007ffff7a6125e <+46>:	movaps %xmm2,0x70(%rsp)
   0x00007ffff7a61263 <+51>:	movaps %xmm3,0x80(%rsp)
   0x00007ffff7a6126b <+59>:	movaps %xmm4,0x90(%rsp)
   0x00007ffff7a61273 <+67>:	movaps %xmm5,0xa0(%rsp)
   0x00007ffff7a6127b <+75>:	movaps %xmm6,0xb0(%rsp)
   0x00007ffff7a61283 <+83>:	movaps %xmm7,0xc0(%rsp)
   0x00007ffff7a6128b <+91>:	lea    0xe0(%rsp),%rax
   0x00007ffff7a61293 <+99>:	mov    %rdi,%rsi
   0x00007ffff7a61296 <+102>:	lea    0x8(%rsp),%rdx
   0x00007ffff7a6129b <+107>:	mov    %rax,0x10(%rsp)
   0x00007ffff7a612a0 <+112>:	lea    0x20(%rsp),%rax
   0x00007ffff7a612a5 <+117>:	movl   $0x8,0x8(%rsp)
   0x00007ffff7a612ad <+125>:	movl   $0x30,0xc(%rsp)
   0x00007ffff7a612b5 <+133>:	mov    %rax,0x18(%rsp)
   0x00007ffff7a612ba <+138>:	mov    0x372c7f(%rip),%rax        # 0x7ffff7dd3f40
   0x00007ffff7a612c1 <+145>:	mov    (%rax),%rdi
   0x00007ffff7a612c4 <+148>:	callq  0x7ffff7a56430 <vfprintf>
   0x00007ffff7a612c9 <+153>:	add    $0xd8,%rsp
   0x00007ffff7a612d0 <+160>:	retq   
End of assembler dump.
mv ★★★★★
()
Последнее исправление: mv (всего исправлений: 1)

Ещё способ, этот везде будет работать, где binutils есть:

$ grep r-xp.*libc /proc/$$/maps
7f6b37e01000-7f6b37fc4000 r-xp 00000000 fd:02 7875055                    /usr/lib64/libc-2.17.so
$ nm libc.so.6  | grep ' printf$'
0000000000053230 T printf

0x7f6b37e01000+0x53230=7f6b37e54230

mv ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.