>Требуется определить физический адрес первого байта программы в ОП;
>скажем что-то, типа:
>
>mian()
>{
>printf("%d",main);
>}
Чтобы найти адрес функции main, проанализируем заголовок исполняемого файла формата ELF32. Структура заголовка находится в файле <linux/elf.h>. Поле e_entry структуры struct elf32_hdr содержит стартовый адрес программы. Найти его можно следующим способом:
#include <stdio.h>
#include <linux/elf.h>
#include <fcntl.h>
int main (int argc, char **argv)
{
int fd, kmem;
unsigned long addr = 0; - здесь мы сохраним адрес main
struct elf32_hdr ehdr;
memset(&ehdr, 0, sizeof(struct elf32_hdr));
Откроем исполняемый файл и прочитаем заголовок:
fd=open(argv[0], O_RDONLY);
read(fd, (char *)&ehdr, sizeof(struct elf32_hdr));
close(fd);
Отобразим стартовый адрес программы:
printf("start\t-\t0xx\n", ehdr.e_entry);
Итак, стартовый адрес у нас есть.
Адрес main находится по смещению 24 байта относительно стартового адреса (ниже рассмотрено, почему это так). Воспользуемся файлом /dev/kmem, в котором отображено все виртуальное адресное пространство. Любой адрес задается как смещение в этом файле:
kmem=open("/dev/kmem", O_RDONLY);
lseek(kmem, ehdr.e_entry+24, 0);
read(kmem, (char *)&addr, 4);
close(kmem);
Адрес функции main:
printf("main\t-\t0xx\n",addr);
return 0;
}
Дизассемблируем исполняемый файл при помощи objdump и найдем стартовый адрес. По этому адресу будет расположена секция <_start>. Рассмотрев ассемблерный листинг, мы увидим, что сначала в стек загружаются параметры, а затем следует вызов библиотечной функции __libc_start_main (call <адрес><_init+0x48>). Первым параметром этой функции является адрес main. Этот параметр загружается в стек последним. Адрес main находится по смещению 24 байт относительно стартового адреса.