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
Vous devez vous connecter pour publier un commentaire.
Veuillez fournir tous les exécutables code, y compris l'ELFE que vous essayez de charger.
J'ai pris le temps de modifier votre code du mieux que je pouvais, et il semble fonctionner, au moins pour ce simple code.
Noter que le chargeur doit également être compilé en 32 bits, vous ne pouvez pas charger un 32 bits fichier dans une version 64 bits de processus. En outre, puisque vous n'êtes pas charger le code dans le lieu d'origine, il doit être transférable. Enfin, il doit être un binaire statique parce que vous n'êtes pas le chargement des bibliothèques.
Mise à jour: Votre code s'attend à ce que le point d'entrée du code chargé de se conformer à la
int (*main)(int, char **)
prototype qui n'est pas le cas en général (note de côté:main
obtient en fait un troisième argument, l'environnement, aussi). Lisez à propos de la l'état de démarrage de l'ELFE. Si vous créez manuellement la pile mise en page qui y sont décrits, vous devez sauter vers le point d'entrée, et qui ne reviendra jamais. Dans le cas d'un programme C, vous pouvez creuser l'adresse demain
et qui doit correspondre au prototype. Cependant, vous êtes alors le saut de l'initalization de la bibliothèque C (rappelez-vous, votre code ne fait pas de chargement de bibliothèque, de sorte que le chargé de programme doit être lié statiquement) et qui pourrait être un problème.J'ai étendu le code avec les bits nécessaires pour gérer un simple programme en C de la résolution de la libc des références et de l'invocation de
main
.chargeur.c:
elfe.c:
test:
Mise à jour de la réponse.
désolé pour cela, mais je voulais juste savoir où vous les gars obtenir le libelf bibliothèques. Merci
c'est un très vieux thread, mais, n'avez-vous pas besoin de s'inquiéter sur les choses soient alignés dans votre code?
ici, nous sommes chargement d'une bonne binaire ELF créé par les normal de la chaîne, de sorte que tous l'alignement est déjà pris en charge.
OriginalL'auteur Jester
Cette tente de charger le fichier exécutable à l'arbitraire de l'adresse. Un non-PIE exécutable ne peut être chargé à l'adresse où il a été lié à l' (généralement
0x08048000
sur Linux/ix86).Si le programme était liée de façon dynamique, c'est rien mais simple, et votre chargeur a une diable de beaucoup plus à faire: le chargement et le déplacement dépendant des bibliothèques partagées, la fixation de
GOT
etTLS
, etc. etc.OriginalL'auteur Employed Russian
utilisation
au lieu de
OriginalL'auteur Asad