Я хочу написать свой собственный ld.so, и я хочу сделать это шаг за шагом.Я не смог найти «руководства» по кодированию моего ld.so, поэтому я хочу сделать это сам.Я думал, что сначала попробую загрузить простой двоичный файл в память, как показано ниже;тогда позвони.Это очень просто, и это уже не работает.
Двоичный файл:
section .text
global _start
_start:
mov edi, 123
mov eax, 60
syscall
вызывающий выход (123):
$ nasm -f elf64 bin.asm && ld bin.o && ./a.out; echo $?
$ 123
Загрузчик:
FILE *fp = fopen(argv[1], "r");
if (!fp) {
fprintf(stderr, "cannot open file %s", argv[1]);
return 1;
}
fseek(fp, 0L, SEEK_END);
size_t sz = ftell(fp) + 1;
rewind(fp);
char *contents = malloc(sizeof(char) * sz);
size_t pagesize = getpagesize();
void *base_addr = (void*) (pagesize * (1 << 20));
char *region = mmap(
base_addr,
pagesize,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANON | MAP_PRIVATE,
0, 0
);
if (region == MAP_FAILED) {
fprintf(stderr, "could not mmap");
return 1;
}
for (int i = 1, nread = 0; nread != sz * sizeof(char) && i > 0; nread += i) {
i = fread(contents, sizeof(char), sz, fp);
}
contents[sz - 1] = 0;
if (ferror(fp)) {
fprintf(stderr, "error reading file %s", argv[1]);
return 1;
}
memcpy(region, contents, sz);
if (mprotect(region, pagesize, PROT_READ | PROT_EXEC)) {
fprintf(stderr, "mprotect failed");
return 1;
}
return ((int (*)()) base_addr)();
Я думаю, что произойдет: my_linker -> двоичный файл в памяти -> вызов mov edi, 123
, возвращение 123.
Что происходит: "SIGSEGV по адресу 0x0"
IЯ запускаю это в Linux x86_64.
EDIT: в ответ на @Ctx.memcpy
вместо strncpy
.
Я должен был заявить, что он очищен.Я бегу nasm -f elf...
, чтобы показать, что он делает то, что ожидается.В качестве аргумента программы, nasm -f bin -o prog.bin ...
двоичный файл.