Как понять разницу между Offset и VirAddr в заголовках программ в elf?

Есть файл elf с разделяемой библиотекой, я использую readelf -l для просмотра заголовков программ, вывод такой:

Elf file type is DYN (Shared object file)
Entry point 0x0
There are 11 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x00000034 0x00000034 0x00100 0x00100 R   0x4
  INTERP         0x000194 0x00000194 0x00000194 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /system/bin/linker]
  LOAD           0x000000 0x00000000 0x00000000 0x3aa8c4 0x3aa8c4 R E 0x1000
  LOAD           0x3ab1cc 0x003ac1cc 0x003ac1cc 0x062c0 0x25ee4 RW  0x1000
  LOAD           0x3b2000 0x003d3000 0x003d3000 0x02561 0x02561 R E 0x1000
  LOAD           0x3b4e8c 0x003d6e8c 0x003d6e8c 0x00298 0x00299 RW  0x1000
  LOAD           0x3b5268 0x003d8268 0x003d8268 0x00128 0x00128 RW  0x1000
  DYNAMIC        0x3b5268 0x003d8268 0x003d8268 0x00128 0x00128 RW  0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0
  EXIDX          0x2e71e8 0x002e71e8 0x002e71e8 0x0b558 0x0b558 R   0x4
  GNU_RELRO      0x3ab1cc 0x003ac1cc 0x003ac1cc 0x01e34 0x01e34 RW  0x4

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .interp .dynsym .dynstr .hash .gnu.version .gnu.version_d .rel.dyn .plt .text .ARM.extab .ARM.exidx .rodata 
   03     .data.rel.ro.local .fini_array .data.rel.ro .got .data .bss 
   04     .rel.plt 
   05     .init_array 
   06     .dynamic 
   07     .dynamic 
   08     
   09     .ARM.exidx 
   10     .data.rel.ro.local .fini_array .data.rel.ro .got 

если следующая структура представляет заголовок программы:

   typedef struct {
       uint32_t   p_type;
       Elf32_Off  p_offset;
       Elf32_Addr p_vaddr;
       Elf32_Addr p_paddr;
       uint32_t   p_filesz;
       uint32_t   p_memsz;
       uint32_t   p_flags;
       uint32_t   p_align;
   } Elf32_Phdr;

Тогда мой вопрос: как понять разницу между p_offset и p_vaddr, которая соответствует Offset и VirtAddr на выходе readelf -l? Всегда ли они будут такими же? И будут ли они изменены процедурой динамической загрузки?

p_offset - смещение в файле, p_vaddr - адрес раздела после загрузки в память (скажем, после инициализации среды выполнения c)
user2162550 27.09.2018 11:39
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
753
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вообще говоря-

p_offset - смещение в файле elf

p_vaddr - адрес раздела после загрузки в память (скажем, после завершения инициализации среды выполнения c)

Они не всегда будут одинаковыми, эти адреса можно настроить, например, с помощью скрипта компоновщика. Обратитесь к этому.

Что касается адресов разделяемой библиотеки после загрузки библиотеки в адресное пространство процесса - это зависит от адресного пространства процесса, ASLR и т. д., Но можно с уверенностью сказать, что динамический загрузчик установит новые адреса (p_vaddr, также известный как адрес выполнения)

How to understand the difference between p_offset and p_vaddr which corresponds to Offset and VirtAddr in output of readelf -l?

Загрузчик среды выполнения будет mmap набор страниц со смещением .p_offset (округленным до размера страницы) по виртуальному адресу .p_vaddr (аналогично округленному; к этому адресу фактически будет добавлено большое многостраничное смещение для объекта ET_DYN).

Will them always be the same?

Они не одинаковы даже в вашем примере:

LOAD           0x3ab1cc 0x003ac1cc

0x3ab1! = 0x3ac1. Что гарантирует является, так это то, что .p_offset % pagesize == .p_vaddr % pagesize (иначе mmap станет невозможным).

Другие вопросы по теме