Sto provando a caricare un file ELF compilato con "gcc -m32 test.c -o test.exe" su Linux in un ambiente x86 a 64 bit. Sto cercando di caricare quel file a 32 bit (test.exe) all'interno di un caricatore ELF di spazio utente che ha la seguente logica di base (ELF a 32 bit).caricamento file ELF in C nello spazio utente
Il problema è che la chiamata nell'indirizzo di inizio restituito produce un dump del core di errore di segmentazione. Ecco il codice:
void *image_load (char *elf_start, unsigned int size)
{
Elf32_Ehdr *hdr = NULL;
Elf32_Phdr *phdr = NULL;
unsigned char *start = NULL;
Elf32_Addr taddr = 0;
Elf32_Addr offset = 0;
int i = 0;
unsigned char *exec = NULL;
Elf32_Addr estart = 0;
hdr = (Elf32_Ehdr *) elf_start;
if(!is_image_valid(hdr)) {
printk("image_load:: invalid ELF image\n");
return 0;
}
exec = (unsigned char *)mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
if(!exec) {
printk("image_load:: error allocating memory\n");
return 0;
}
// Start with clean memory.
memset(exec,0x0,size);
phdr = (Elf32_Phdr *)(elf_start + hdr->e_phoff);
for(i=0; i < hdr->e_phnum; ++i) {
if(phdr[i].p_type != PT_LOAD) {
continue;
}
if(phdr[i].p_filesz > phdr[i].p_memsz) {
printk("image_load:: p_filesz > p_memsz\n");
munmap(exec, size);
return 0;
}
if(!phdr[i].p_filesz) {
continue;
}
// p_filesz can be smaller than p_memsz,
// the difference is zeroe'd out.
start = (unsigned char *) (elf_start + phdr[i].p_offset);
// taddr = phdr[i].p_vaddr + (Elf32_Addr)exec;
if(!estart) {
estart = phdr[i].p_paddr;
}
taddr = (Elf32_Addr)exec + offset + (phdr[i].p_paddr - estart);
memmove((unsigned char *)taddr,
(unsigned char *)start,phdr[i].p_filesz);
offset += (phdr[i].p_memsz + (phdr[i].p_paddr - estart));
if(!(phdr[i].p_flags & PF_W)) {
// Read-only.
mprotect((unsigned char *) taddr,
phdr[i].p_memsz,
PROT_READ);
}
if(phdr[i].p_flags & PF_X) {
// Executable.
mprotect((unsigned char *) taddr,
phdr[i].p_memsz,
PROT_EXEC);
}
}
return (void *)((hdr->e_entry - estart) + (Elf32_Addr)exec);
}/* image_load */
...
int (*main)(int, char **)=image_load(...);
main(argc,argv); // Crash...
...
'printk' suggerisce un modulo del kernel, mentre' 'mmap' & mprotect' sono user-space. Se stai codificando un'applicazione per lo spazio utente, hai pensato di compilarlo con 'gcc -Wall -g' e debuggarlo con' gdb'? E l'indirizzo iniziale di un'immagine ELF è * non * la routine 'main' (ma alcuni' _start' in alcuni 'crt0.o') –