Почему мой раздел данных дважды появляется в скомпилированном двоичном файле? Ubuntu, x86, nasm, gdb, reaelf - PullRequest
3 голосов
/ 14 июля 2020

Был дан ответ на предыдущий вопрос, связанный с . Спасибо! Однако это создает для меня новый вопрос. Почему nasm помещает байты данных в два разных места в памяти? Я включаю информацию о программе и дамп других данных ниже.

---------- code snippet compiled with nasm, ld -----------------
section .text
...
zero: jmp short two
one:  pop ebx
      xor eax, eax
      mov [ebx+12], eax
      mov [ebx+8], ebx
      mov [ebx+7], al
      lea ecx, [ebx+8]
      lea edx, [ebx+12]
      mov al, 11
      int 0x80
two:  call one
section .data align=1
msg:   db '/bin/sh0argvenvp' 

-------- readelf output to show load locations --------
readelf -Wl myshdb

Elf file type is EXEC (Executable file)
Entry point 0x8048080
There are 2 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x08048000 0x08048000 0x0009d 0x0009d R E 0x1000
  LOAD           0x00009d 0x0804909d 0x0804909d 0x00010 0x00010 RW  0x1000

 Section to Segment mapping:
  Segment Sections...
   00     .text 
   01     .data 

-------------- run with gdb and debug step to mov instructions ----------
---------------registers--------------
EAX: 0x0 
EBX: 0x804809d ("/bin/sh0argvenvp")

----------- memory address checks ------------
gdb-peda$ p zero
$15 = {<text variable, no debug info>} 0x8048080 <zero>
gdb-peda$ p one
$16 = {<text variable, no debug info>} 0x8048082 <one>
gdb-peda$ p two
$17 = {<text variable, no debug info>} 0x8048098 <two>
gdb-peda$ p $ebx
$18 = 0x804809d
gdb-peda$ p msg
$19 = 0x6e69622f
gdb-peda$ x 0x804809d
0x804809d:  "/bin/sh0argvenvp"
gdb-peda$ x msg
0x6e69622f: <error: Cannot access memory at address 0x6e69622f>

Другими словами, строковое сообщение доступно из области памяти сразу после кода (0x804809d). Тем не менее, метка msg сопоставляется с 0x6e69622f, который является меткой моих данных. Как можно использовать GDB для просмотра данных по второму адресу? Располагает ли nasm данными в двух разных местах? Почему?

1 Ответ

5 голосов
/ 14 июля 2020

Давайте посмотрим на сегменты LOAD:

Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x08048000 0x08048000 0x0009d 0x0009d R E 0x1000
LOAD 0x00009d 0x0804909d 0x0804909d 0x00010 0x00010 RW 0x1000

Первый инструктирует загрузчик в mmap 0x9d байтов от смещения файла 0 в виртуальную память по адресу 0x08048000.

Загрузчик не может сделать точно это , потому что отображение памяти работает только с детализацией на одной странице (4096 байт). Таким образом, это mmap s .text и все, что следует за ним в файле , до одной страницы, по адресу 0x08048000.

Это означает, что все, что .data после .text в файле после смещения 0x9d появится по адресу 0x0804809d и позже, но с неправильными разрешениями (R ead и E xecute).

Второй сегмент LOAD указывает загрузчику содержимое файла mmap, начиная со смещения 0x9d по виртуальному адресу 0x0804909d.

Загрузчик не может делать это либо по той же причине "гранулярности страницы".

Вместо этого будет округлено смещение и адрес, а также mmap содержимое файла, начиная со смещения 0 по адресу 0x08049000 .

Это означает, что все, что .text предшествует .data в файле, будет отображаться по адресу до 0x0804909d, опять же с неправильными разрешениями (R ead и W на этот раз ритуал).

Вы можете подтвердить, что именно это происходит, используя GDB x/10i 0x8049080 - вы получите ee точно те же инструкции, что и с x/10i 0x8048080.

Вы также можете наблюдать фактические mmap системные вызовы, выполняемые загрузчиком с strace.

...