Mercurial > hg > chrpath
diff elf.c @ 1:bbbfb3f97919
implement 32 and 64 bit support
author | Peter Meerwald <p.meerwald@bct-electronic.com> |
---|---|
date | Fri, 20 Jul 2012 11:26:24 +0200 |
parents | b8f7423e385c |
children |
line wrap: on
line diff
--- a/elf.c Fri Jul 20 01:51:24 2012 +0200 +++ b/elf.c Fri Jul 20 11:26:24 2012 +0200 @@ -17,7 +17,7 @@ #include "protos.h" int -elf_open(const char *filename, int flags, Elf_Ehdr *ehdr) +elf32_open(const char *filename, int flags, Elf32_Ehdr *ehdr) { int fd; @@ -36,7 +36,7 @@ } if (0 != memcmp(ehdr->e_ident, ELFMAG, SELFMAG) || - ehdr->e_ident[EI_CLASS] != ELFCLASS || + ehdr->e_ident[EI_CLASS] != ELFCLASS32 || ehdr->e_ident[EI_DATA] != ELFDATA2 || ehdr->e_ident[EI_VERSION] != EV_CURRENT) { @@ -46,16 +46,18 @@ #else /* not WORD_BIGENDIAN */ "`%s' probably isn't a %d-bit LSB-first ELF file.\n", #endif /* not WORD_BIGENDIAN */ - filename, SIZEOF_VOID_P * 8); + filename, 32); close(fd); errno = ENOEXEC; /* Hm, is this the best errno code to use? */ return -1; } - if (ehdr->e_phentsize != sizeof(Elf_Phdr)) + printf("32-bit ELF file\n"); + + if (ehdr->e_phentsize != sizeof(Elf32_Phdr)) { - fprintf(stderr, "section size was read as %d, not %d!\n", - ehdr->e_phentsize, sizeof(Elf_Phdr)); + fprintf(stderr, "section size was read as %d, not %lu!\n", + ehdr->e_phentsize, sizeof(Elf32_Phdr)); close(fd); return -1; } @@ -63,7 +65,90 @@ } int -elf_find_dynamic_section(int fd, Elf_Ehdr *ehdr, Elf_Phdr *phdr) +elf64_open(const char *filename, int flags, Elf64_Ehdr *ehdr) +{ + int fd; + + fd = open(filename, flags); + if (fd == -1) + { + perror ("open"); + return -1; + } + + if (read(fd, ehdr, sizeof(*ehdr)) != sizeof(*ehdr)) + { + perror ("reading header"); + close(fd); + return -1; + } + + if (0 != memcmp(ehdr->e_ident, ELFMAG, SELFMAG) || + ehdr->e_ident[EI_CLASS] != ELFCLASS64 || + ehdr->e_ident[EI_DATA] != ELFDATA2 || + ehdr->e_ident[EI_VERSION] != EV_CURRENT) + { + fprintf(stderr, +#ifdef WORDS_BIGENDIAN + "`%s' probably isn't a %d-bit MSB-first ELF file.\n", +#else /* not WORD_BIGENDIAN */ + "`%s' probably isn't a %d-bit LSB-first ELF file.\n", +#endif /* not WORD_BIGENDIAN */ + filename, 64); + close(fd); + errno = ENOEXEC; /* Hm, is this the best errno code to use? */ + return -1; + } + + printf("64-bit ELF file\n"); + + if (ehdr->e_phentsize != sizeof(Elf64_Phdr)) + { + fprintf(stderr, "section size was read as %d, not %lu!\n", + ehdr->e_phentsize, sizeof(Elf64_Phdr)); + close(fd); + return -1; + } + return fd; +} + +int +elf32_find_dynamic_section(int fd, Elf32_Ehdr *ehdr, Elf32_Phdr *phdr) +{ + int i; + if (lseek(fd, ehdr->e_phoff, SEEK_SET) == -1) + { + perror ("positioning for sections"); + return 1; + } + + for (i = 0; i < ehdr->e_phnum; i++) + { + if (read(fd, phdr, sizeof(*phdr)) != sizeof(*phdr)) + { + perror ("reading section header"); + return 1; + } + if (phdr->p_type == PT_DYNAMIC) + break; + } + if (i == ehdr->e_phnum) + { + fprintf (stderr, "No dynamic section found.\n"); + return 2; + } + + if (0 == phdr->p_filesz) + { + fprintf (stderr, "Length of dynamic section is zero.\n"); + return 3; + } + + return 0; +} + +int +elf64_find_dynamic_section(int fd, Elf64_Ehdr *ehdr, Elf64_Phdr *phdr) { int i; if (lseek(fd, ehdr->e_phoff, SEEK_SET) == -1)