1 /*
2 * Copyright (c) 2003, 2019, 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, 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)
|
1 /*
2 * Copyright (c) 2003, 2020, 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, 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)
|