मैं 64 बिट x86 वातावरण में लिनक्स पर "gcc -m32 test.c -o test.exe" के साथ संकलित एक ईएलएफ फ़ाइल लोड करने का प्रयास कर रहा हूं। मैं उस उपयोगकर्ता स्थान ईएलएफ लोडर के अंदर उस 32 बिट फ़ाइल (test.exe) को लोड करने का प्रयास कर रहा हूं जिसमें निम्न कोर तर्क (32 बिट ईएलएफ) है।उपयोगकर्ता स्थान में सी में ईएलएफ फ़ाइल लोड करना
समस्या यह है कि लौटे हुए प्रारंभ पते में कॉलिंग सेगमेंटेशन फॉल्ट कोर डंप में परिणाम देती है। यहां कोड है:
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', एक कर्नेल मॉड्यूल पता चलता है, जबकि' mmap' और 'mprotect' उपयोगकर्ता के अंतरिक्ष हैं। यदि आप उपयोगकर्ता-स्पेस एप्लिकेशन को कोड कर रहे हैं, तो क्या आपने इसे 'gcc -Wall -g' के साथ संकलित करने और इसे' gdb' से डीबग करने पर विचार किया था? और ईएलएफ छवि का प्रारंभ पता * मुख्य * दिनचर्या नहीं है (लेकिन कुछ 'crt0.o' में कुछ '_start') –