ELF loader 질문
글쓴이: declspec / 작성시간: 토, 2012/01/14 - 9:32오후
안녕하세요, 32비트 ELF Loader 를 공부할겸
아주 단순하게 만들어보려고 하는데요
아래와 같이 컴파일러 책에 있는 코드를 따라하고
테스트 해봤습니다.
단지 프로그램 헤더를 따라가서 segment 들을
mmap 으로 로드할때 기존 프로그램의 주소랑 충돌하는
문제때문에 메모리 로드위치를 바꿔야한다고해서
어떻게 해야할지 잘몰라 주소에 임의로 +0x5000 씩을
해줬는데요;
마지막에 엔트리포인트로 이동을 하니 바로 Segmentation Fault 가 뜨네요
한번 ELF 구조 공부할겸
단순하게 다른 프로그램을 로드하는 로더를 만들어보고 싶은데
인터넷에 관련 소스도 없고...
도와주세요~!!
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/mman.h> #include <elf.h> #define ELF_EXEC_PAGESIZE 4096 #define PAGEMASK (~(ELF_EXEC_PAGESIZE-1)) #define EXTEND(addr) (((addr) + (ELF_EXEC_PAGESIZE-1)) & PAGEMASK) static void* load_elf(char* path){ printf("start load_elf\n"); Elf32_Ehdr eh; int fd, i; if((fd=open(path, O_RDWR)) < 0) printf("open\n"); printf("%s open ok\n", path); if(read(fd, &eh, sizeof(Elf32_Ehdr)) < 0) printf("read ehdr\n"); printf("read elf header ok\n"); if(lseek(fd, eh.e_phoff, SEEK_SET) < 0) printf("lseek\n"); printf("seek ph ok\n"); // 프로그램 헤더 테이블의 엔트리들을 체크하며 PT_LOAD 해야할 경우 메모리에 로드. int tmp=0; for(i=0; i<eh.e_phnum; i++){ Elf32_Phdr ph; if((tmp = read(fd, &ph, eh.e_phentsize)) < 0) printf("read phdr\n"); printf("read program header %d bytes, type %d\n", tmp, ph.p_type); if(ph.p_type == PT_LOAD){ void* s_beg = (void*)(ph.p_vaddr +0x5000 & PAGEMASK); void* s_end = (void*)EXTEND(ph.p_vaddr +0x5000 + ph.p_filesz); void* z_end = (void*)EXTEND(ph.p_vaddr +0x5000 + ph.p_memsz); int prot = PROT_R림EAD | PROT_WRITE | PROT_EXEC; int flags = MAP_FIXED | MAP_PRIVATE; off_t offset = ph.p_offset & PAGEMASK; printf("mmap start : %x, size :%x, foffset : %x\n", (unsigned int)s_beg, (unsigned int)(s_end-s_beg), (unsigned int)offset); void* addr = mmap(s_beg, s_end - s_beg, prot, flags, fd, offset); if(addr == MAP_FAILED) printf("mmap\n"); printf("mmap ok\n"); if(z_end > s_end){ addr = mmap(s_end, z_end - s_end, prot, flags | MAP_ANONYMOUS, 0, 0); if(addr == MAP_FAILED) printf("mmap zero page\n"); } } } close(fd); return (void*)(eh.e_entry+0x5000); } int main(int argc, char* argv[]){ if(argc<2){ printf("usage: ./load [elfname]\n"); return 0; } void (*func)(); printf("loading segments...\n"); func = load_elf( argv[1] ); printf("entry point : %08X\n", (unsigned int)func); func(); // jump to entry point. return 0; }
Forums:
댓글 달기