2016-10-09 12 views
1

Я получаю физические адреса функции «printf» в libc.so в двух программах, а два физических адреса различны. И я читаю два разных физических адреса, контент почти одинаковый. Это означает, что функция «printf» имеет две копии в памяти?Функция общей библиотеки загружается на разные физические адреса для разных процессов

Детали:

  1. Моя ОС 32-битная Linux.

  2. Физический адрес рассчитывается, считая «/ proc/self/pagemap».

  3. Физический адрес считывания осуществляется с модулем fmem, чей исходный код на [email protected]: NateBrune/fmem.git

+0

Что вы имеете в виду под «содержание почти то же самое»? Если две реализации 'printf()' отличаются друг от друга, то, конечно, они должны быть в разных местах, возможно, две программы используют разные версии libc? – unwind

+1

"* физические адреса *" вы уверены? Каждый процесс использует свое * виртуальное * адресное пространство. – alk

+0

Это может быть [рандомизация размещения адресного пространства] (https://en.wikipedia.org/wiki/Address_space_layout_randomization). –

ответ

1

Я получаю физические адреса функции "Printf" в LIBC .so в двух программах, и два физических адреса различны.

Возможно, вы ошибаетесь (но трудно догадаться: вы не указали никаких подробностей).

В частности, обратите внимание, что следующая программа:

#include <stdio.h> 

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

делает не печать фактический адрес printf в libc.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 
[email protected] 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 
+0

У меня вопрос. Я думал, что имя символа в plt - 'printf @ plt'. Но почему 'dlsym (RTLD_DEFAULT," printf ")' находит запись plt? Почему простая не-plt'ed символьная строка не находит реальной вещи, как это, по-видимому, с помощью 'gdb'? –

+1

@litb «Я думал, что имя символа в plt - printf @ plt» - это не так. Это 'printf', как вы можете видеть на выходе' readelf -Ws'. '@ Plt' - это имя, которое GDB производит, чтобы сделать его более понятным, что это за символ. –

+0

@EmployedRussian, вы правы, виртуальный адрес 'printf', который я получил, на самом деле является «printf @ plt», реальный виртуальный адрес «printf» хранится в GOT после привязки «printf». Наконец, в моем эксперименте я получил виртуальные адреса 0xb7581590 и 0xb7635590 из 'printf' в двух программах, а их физические адреса - 0x7bc6b590. –