Я га OpenBSD 6.6 64-bit
Есть простая программка hello:
#include <stdio.h>
#include <stdlib.h>int main(int argc, char** argv)
{
// printf("%d\n", argc);
// printf("Hello world!\n");
return argc;
}$ objdump -x hello | grep main
0000000000005680 g F .text 0000000000000010 main
Надо вызвать ее из другой программы используя ручные методы:
#include <stdlib.h>
#include <stdio.h>
#include <err.h>
#include <errno.h>
#include <sys/mman.h>
#include "defines.h"
#include <fcntl.h>void * RAM;
int main(int argc, char **argv)
{
int i = open("disk/hello", O_RDWR);if (i == -1)
errc(errno, errno, "Unable to open file\n");RAM = mmap(0, MEMORY_NPAGE * MEM_PAGE_SIZE,
PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, i, 0);
if (RAM == MAP_FAILED) errc(errno, errno, "Unable to map memory\n");printf("fd an allocated addres %d %lx\n", i, (long int)RAM);
// _Jv_RegisterClasses symbol
long unsigned int * _Jv_RegisterClasses = RAM;
*_Jv_RegisterClasses = (long unsigned int) RAM;
int (*System)(int, char**) = RAM + 0x5680; //Symbol "T main"int j = System(10, argv);
printf("Hello return %d\n", j);
if (munmap(RAM, MEMORY_NPAGE * MEM_PAGE_SIZE) == -1)
errc(errno, errno, "Unable to umap memory\n");
return 0;
}Родительская программа mmap'ит исполняемый файл и легко найти в дочерней int main и вызвать. Пока в int main не обращаются к данным, а содержатся только команды, все естественно выполняется. Как увидеть дочерней программе её сегмент данных. Что означает единственный символ в статическом hello "_Jv_Register_Classes".
Спасибо за любую помощь.
Результат выполнения дочерней программы без printf (обращения к сегменту данных)
fd an allocated addres 3 77f9ad30000
Hello return 10
То есть вызывается именно int main();
Проще, как добиться чтобы дочерняя напечатала Hello world!?
> Проще, как добиться чтобы дочерняя напечатала Hello world!?Раскомментировать // printf("Hello world!\n"); ?
Серьёзнее - mmap штука хорошая, но неплохо бы ещё и сегмент стека заиметь.
Да и STDIN с STDOUT как-то передать.У линухов есть готовый мануал http://www.stratigery.com/userlandexec.html
Для чертей в общих словах тоже объясняют - https://www.netbsd.org/docs/internals/en/chap-processes.html
>> Проще, как добиться чтобы дочерняя напечатала Hello world!?
> Раскомментировать // printf("Hello world!\n"); ?
> Серьёзнее - mmap штука хорошая, но неплохо бы ещё и сегмент стека
> заиметь.
> Да и STDIN с STDOUT как-то передать.
> У линухов есть готовый мануал http://www.stratigery.com/userlandexec.html
> Для чертей в общих словах тоже объясняют - https://www.netbsd.org/docs/internals/en/chap-processes.htmlБольшое спасибо за ссылки.
> Родительская программа mmap'ит исполняемый файл и легко найти в дочерней int main
> и вызвать. Пока в int main не обращаются к данным, а
> содержатся только команды, все естественно выполняется. Как увидеть дочерней программе
> её сегмент данных.В OpenBSD последних версий по умолчанию используется PIE, это отчасти жизнь должно упрощать: read-only константы могут жить внутри свободно релоцируемого сегмента кода, и проблемы нет.
Но могут и не жить, плюс Но если я правильно понимаю задачу, вам нужно выполнить работу ld.so и ручками настроить таблицу смещений, да ещё и регистр процессора в нужное (не помню, кто там на amd64 зарезервирован под PIC) значение выставить.
Ну и это, вы сначала используйте PROT_READ|PROT_WRITE, а потом меняйте на PROT_READ|PROT_EXEC. Ну или придётся собирать с флагом компоновщика -z wxneeded, и запускать на ФС с wxallowed. Но лучше всё-таки по-человечески написать код. ;)
>[оверквотинг удален]
> В OpenBSD последних версий по умолчанию используется PIE, это отчасти жизнь должно
> упрощать: read-only константы могут жить внутри свободно релоцируемого сегмента кода,
> и проблемы нет.
> Но могут и не жить, плюс Но если я правильно понимаю задачу,
> вам нужно выполнить работу ld.so и ручками настроить таблицу смещений, да
> ещё и регистр процессора в нужное (не помню, кто там на
> amd64 зарезервирован под PIC) значение выставить.
> Ну и это, вы сначала используйте PROT_READ|PROT_WRITE, а потом меняйте на PROT_READ|PROT_EXEC.
> Ну или придётся собирать с флагом компоновщика -z wxneeded, и запускать
> на ФС с wxallowed. Но лучше всё-таки по-человечески написать код. ;)Спасибо. Сейчас курю elf.h.
>[оверквотинг удален]
> В OpenBSD последних версий по умолчанию используется PIE, это отчасти жизнь должно
> упрощать: read-only константы могут жить внутри свободно релоцируемого сегмента кода,
> и проблемы нет.
> Но могут и не жить, плюс Но если я правильно понимаю задачу,
> вам нужно выполнить работу ld.so и ручками настроить таблицу смещений, да
> ещё и регистр процессора в нужное (не помню, кто там на
> amd64 зарезервирован под PIC) значение выставить.
> Ну и это, вы сначала используйте PROT_READ|PROT_WRITE, а потом меняйте на PROT_READ|PROT_EXEC.
> Ну или придётся собирать с флагом компоновщика -z wxneeded, и запускать
> на ФС с wxallowed. Но лучше всё-таки по-человечески написать код. ;)Спасибо за наводки. Вопрос раскурен и реализован. Ответ - надо выполнить все relocations elf файла. При этом формируется и BSS область для программы.