共享库的功能在不同的物理地址加载,用于不同的进程

时间:2016-10-09 11:23:39

标签: c linux shared-libraries elf

我在两个程序中获取libc.so中函数“printf”的物理地址,并且两个物理地址不同。而且我读了两个不同的物理地址,内容几乎相同。这意味着函数“printf”在内存中有两个副本吗?

详细说明:

  1. 我的操作系统是32位Linux。

  2. 物理地址的读数为“/ proc / self / pagemap”。

  3. 使用fmem模块实现物理地址读取,其源代码位于git@github.com:NateBrune / fmem.git

1 个答案:

答案 0 :(得分:1)

  

我得到了函数的物理地址" printf"在libc.so中有两个程序,两个物理地址不同。

你可能做错了(但很难猜到:你没有提供任何细节)。

特别要注意以下程序:

#include <stdio.h>

int main()
{
  printf("&printf: %p\n", &printf);
  return 0;
}

打印printflibc.so.6的实际地址,正如GDB可以看到的那样:

(gdb) start
Temporary breakpoint 1 at 0x8048426: file pagemap.c, line 5.
Starting program: /tmp/pagemap

Temporary breakpoint 1, main () at pagemap.c:5
5     printf("&printf: %p\n", &printf);
(gdb) n
&printf: 0x80482f0
6     return 0;

(gdb) info symbol 0x80482f0
printf@plt in section .plt of /tmp/pagemap

(gdb) p &printf
$1 = (<text variable, no debug info> *) 0xf7e5add0 <printf>

(gdb) info sym 0xf7e5add0
printf in section .text of /lib32/libc.so.6

请注意printf @0x80482f0位于主可执行文件中,并且应该共享(除了同时运行的同一个可执行文件的多个实例之间),并且 printf的代码实际存在的位置。

printf @0xf7e5add0位于libc.so.6,而 printf的代码实际所在的位置。 页面应该由使用libc.so.6的所有进程共享。

P.S。要在printf中获取libc.so.6实际地址,可以使用此程序:

#include <stdio.h>
#include <dlfcn.h>

int main()
{
  printf("&printf: %p\n", &printf);
  printf("&printf: %p\n", dlsym(RTLD_NEXT, "printf"));
  return 0;
}

gcc -g pagemap.c -o pagemap -m32 -ldl -D_GNU_SOURCE

(gdb) run
Starting program: /tmp/pagemap
&printf: 0x80483c0
&printf: 0xf7e55dd0

(gdb) info sym 0xf7e55dd0
printf in section .text of /lib32/libc.so.6