1 /* 2 * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, 20 * CA 94065 USA or visit www.oracle.com if you need additional information or 21 * have any questions. 22 * 23 */ 24 25 #include "salibelf.h" 26 #include <stdlib.h> 27 #include <unistd.h> 28 29 extern void print_debug(const char*,...); 30 31 // ELF file parsing helpers. Note that we do *not* use libelf here. 32 int read_elf_header(int fd, ELF_EHDR* ehdr) { 33 if (pread(fd, ehdr, sizeof (ELF_EHDR), 0) != sizeof (ELF_EHDR) || 34 memcmp(&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0 || 35 ehdr->e_version != EV_CURRENT) { 36 return 0; 37 } 38 return 1; 39 } 40 41 bool is_elf_file(int fd) { 42 ELF_EHDR ehdr; 43 return read_elf_header(fd, &ehdr); 44 } 45 46 // read program header table of an ELF file 47 ELF_PHDR* read_program_header_table(int fd, ELF_EHDR* hdr) { 48 ELF_PHDR* phbuf = 0; 49 // allocate memory for program header table 50 size_t nbytes = hdr->e_phnum * hdr->e_phentsize; 51 52 if ((phbuf = (ELF_PHDR*) malloc(nbytes)) == NULL) { 53 print_debug("can't allocate memory for reading program header table\n"); 54 return NULL; 55 } 56 57 if (pread(fd, phbuf, nbytes, hdr->e_phoff) != nbytes) { 58 print_debug("ELF file is truncated! can't read program header table\n"); 59 free(phbuf); 60 return NULL; 61 } 62 63 return phbuf; 64 } 65 66 // read section header table of an ELF file 67 ELF_SHDR* read_section_header_table(int fd, ELF_EHDR* hdr) { 68 ELF_SHDR* shbuf = 0; 69 // allocate memory for section header table 70 size_t nbytes = hdr->e_shnum * hdr->e_shentsize; 71 72 if ((shbuf = (ELF_SHDR*) malloc(nbytes)) == NULL) { 73 print_debug("can't allocate memory for reading section header table\n"); 74 return NULL; 75 } 76 77 if (pread(fd, shbuf, nbytes, hdr->e_shoff) != nbytes) { 78 print_debug("ELF file is truncated! can't read section header table\n"); 79 free(shbuf); 80 return NULL; 81 } 82 83 return shbuf; 84 } 85 86 // read a particular section's data 87 void* read_section_data(int fd, ELF_EHDR* ehdr, ELF_SHDR* shdr) { 88 void *buf = NULL; 89 if (shdr->sh_type == SHT_NOBITS || shdr->sh_size == 0) { 90 return buf; 91 } 92 if ((buf = calloc(shdr->sh_size, 1)) == NULL) { 93 print_debug("can't allocate memory for reading section data\n"); 94 return NULL; 95 } 96 if (pread(fd, buf, shdr->sh_size, shdr->sh_offset) != shdr->sh_size) { 97 free(buf); 98 print_debug("section data read failed\n"); 99 return NULL; 100 } 101 return buf; 102 } 103 104 uintptr_t find_base_address(int fd, ELF_EHDR* ehdr) { 105 uintptr_t baseaddr = (uintptr_t)-1; 106 int cnt; 107 ELF_PHDR *phbuf, *phdr; 108 109 // read program header table 110 if ((phbuf = read_program_header_table(fd, ehdr)) == NULL) { 111 goto quit; 112 } 113 114 // the base address of a shared object is the lowest vaddr of 115 // its loadable segments (PT_LOAD) 116 for (phdr = phbuf, cnt = 0; cnt < ehdr->e_phnum; cnt++, phdr++) { 117 if (phdr->p_type == PT_LOAD && phdr->p_vaddr < baseaddr) { 118 baseaddr = phdr->p_vaddr; 119 } 120 } 121 122 quit: 123 if (phbuf) free(phbuf); 124 return baseaddr; 125 }