chargement ELFE de fichier dans C dans l'espace utilisateur

Je suis en train de charger un ELFE fichier compilé avec gcc -m32 test.c -o test.exe" sur Linux en 64 bits x86 environnement. Je suis en train de charger cette 32bit fichier (test.exe) à l'intérieur d'un espace utilisateur chargeur ELF qui est la suite logique de base (32 bits ELF).

Le problème, c'est que l'appel dans le retour de l'adresse de démarrage des résultats dans
une erreur de segmentation core dump. Voici le code:

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 suggère un module du noyau, tandis que mmap & mprotect sont l'espace utilisateur. Si vous êtes le codage d'une application de l'espace utilisateur, avez-vous pensé à le compiler avec gcc -Wall -g et le débogage avec gdb ? Et l'adresse de début d'un ELFE image est pas le main routine (mais certains _start dans certains crt0.o)

OriginalL'auteur Smokey | 2012-12-17