18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include <unistd.h> 26 #include <sys/procfs.h> 27 #include <search.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include "symtab.h" 31 #include "salibelf.h" 32 33 34 // ---------------------------------------------------- 35 // functions for symbol lookups 36 // ---------------------------------------------------- 37 38 struct elf_section { 39 ELF_SHDR *c_shdr; 40 void *c_data; 41 }; 42 43 struct elf_symbol { 44 char *name; 45 uintptr_t offset; 46 uintptr_t size; 47 }; 48 49 typedef struct symtab { 50 char *strs; 51 size_t num_symbols; 52 struct elf_symbol *symbols; 53 struct hsearch_data *hash_table; 54 } symtab_t; 55 56 57 // Directory that contains global debuginfo files. In theory it 58 // should be possible to change this, but in a Java environment there 59 // is no obvious place to put a user interface to do it. Maybe this 60 // could be set with an environment variable. 61 static const char debug_file_directory[] = "/usr/lib/debug"; 62 139 int fd = pathmap_open(pathname); 140 141 if (fd < 0) 142 return -1; 143 144 lseek(fd, 0, SEEK_SET); 145 146 for (;;) { 147 int len = read(fd, buffer, sizeof buffer); 148 if (len <= 0) 149 break; 150 file_crc = gnu_debuglink_crc32(file_crc, buffer, len); 151 } 152 153 if (crc == file_crc) 154 return fd; 155 else { 156 close(fd); 157 return -1; 158 } 159 } 160 161 /* Find an ELF section. */ 162 static struct elf_section *find_section_by_name(char *name, 163 int fd, 164 ELF_EHDR *ehdr, 165 struct elf_section *scn_cache) 166 { 167 char *strtab; 168 int cnt; 169 int strtab_size; 170 171 // Section cache have to already contain data for e_shstrndx section. 172 // If it's not true - elf file is broken, so just bail out 173 if (scn_cache[ehdr->e_shstrndx].c_data == NULL) { 174 return NULL; 175 } 176 177 strtab = scn_cache[ehdr->e_shstrndx].c_data; 178 strtab_size = scn_cache[ehdr->e_shstrndx].c_shdr->sh_size; 179 180 for (cnt = 0; cnt < ehdr->e_shnum; ++cnt) { 181 if (scn_cache[cnt].c_shdr->sh_name < strtab_size) { 182 if (strcmp(scn_cache[cnt].c_shdr->sh_name + strtab, name) == 0) { 183 scn_cache[cnt].c_data = read_section_data(fd, ehdr, scn_cache[cnt].c_shdr); 184 return &scn_cache[cnt]; 185 } 186 } 187 } 188 189 return NULL; 190 } 191 192 /* Look for a ".gnu_debuglink" section. If one exists, try to open a 193 suitable debuginfo file. */ 194 static int open_file_from_debug_link(const char *name, 195 int fd, 196 ELF_EHDR *ehdr, 197 struct elf_section *scn_cache) 198 { 199 int debug_fd; 200 struct elf_section *debug_link = find_section_by_name(".gnu_debuglink", fd, ehdr, 201 scn_cache); 202 if (debug_link == NULL) 203 return -1; 204 char *debug_filename = debug_link->c_data; 205 int offset = (strlen(debug_filename) + 4) >> 2; 206 static unsigned int crc; 207 crc = ((unsigned int*)debug_link->c_data)[offset]; 208 char *debug_pathname = malloc(strlen(debug_filename) 209 + strlen(name) | 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include <unistd.h> 26 #include <sys/procfs.h> 27 #include <search.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include "symtab.h" 31 #include "salibelf.h" 32 33 34 // ---------------------------------------------------- 35 // functions for symbol lookups 36 // ---------------------------------------------------- 37 38 struct elf_symbol { 39 char *name; 40 uintptr_t offset; 41 uintptr_t size; 42 }; 43 44 typedef struct symtab { 45 char *strs; 46 size_t num_symbols; 47 struct elf_symbol *symbols; 48 struct hsearch_data *hash_table; 49 } symtab_t; 50 51 52 // Directory that contains global debuginfo files. In theory it 53 // should be possible to change this, but in a Java environment there 54 // is no obvious place to put a user interface to do it. Maybe this 55 // could be set with an environment variable. 56 static const char debug_file_directory[] = "/usr/lib/debug"; 57 134 int fd = pathmap_open(pathname); 135 136 if (fd < 0) 137 return -1; 138 139 lseek(fd, 0, SEEK_SET); 140 141 for (;;) { 142 int len = read(fd, buffer, sizeof buffer); 143 if (len <= 0) 144 break; 145 file_crc = gnu_debuglink_crc32(file_crc, buffer, len); 146 } 147 148 if (crc == file_crc) 149 return fd; 150 else { 151 close(fd); 152 return -1; 153 } 154 } 155 156 /* Look for a ".gnu_debuglink" section. If one exists, try to open a 157 suitable debuginfo file. */ 158 static int open_file_from_debug_link(const char *name, 159 int fd, 160 ELF_EHDR *ehdr, 161 struct elf_section *scn_cache) 162 { 163 int debug_fd; 164 struct elf_section *debug_link = find_section_by_name(".gnu_debuglink", fd, ehdr, 165 scn_cache); 166 if (debug_link == NULL) 167 return -1; 168 char *debug_filename = debug_link->c_data; 169 int offset = (strlen(debug_filename) + 4) >> 2; 170 static unsigned int crc; 171 crc = ((unsigned int*)debug_link->c_data)[offset]; 172 char *debug_pathname = malloc(strlen(debug_filename) 173 + strlen(name) |