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 #include <stdarg.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <fcntl.h>
29 #include <sys/procfs.h>
30 #include "libproc_impl.h"
31 #include "proc_service.h"
32
33 #define SA_ALTROOT "SA_ALTROOT"
34
35 int pathmap_open(const char* name) {
36 static const char *alt_root = NULL;
37 static int alt_root_initialized = 0;
38
39 int fd;
40 char alt_path[PATH_MAX + 1], *alt_path_end;
41 const char *s;
42 int free_space;
43
44 if (!alt_root_initialized) {
45 alt_root_initialized = -1;
46 alt_root = getenv(SA_ALTROOT);
47 }
48
49 if (alt_root == NULL) {
50 return open(name, O_RDONLY);
51 }
110
111 bool is_debug() {
112 return _libsaproc_debug;
113 }
114
115 // initialize libproc
116 JNIEXPORT bool JNICALL
117 init_libproc(bool debug) {
118 // init debug mode
119 _libsaproc_debug = debug;
120 return true;
121 }
122
123 static void destroy_lib_info(struct ps_prochandle* ph) {
124 lib_info* lib = ph->libs;
125 while (lib) {
126 lib_info *next = lib->next;
127 if (lib->symtab) {
128 destroy_symtab(lib->symtab);
129 }
130 free(lib);
131 lib = next;
132 }
133 }
134
135 static void destroy_thread_info(struct ps_prochandle* ph) {
136 thread_info* thr = ph->threads;
137 while (thr) {
138 thread_info *next = thr->next;
139 free(thr);
140 thr = next;
141 }
142 }
143
144 // ps_prochandle cleanup
145
146 // ps_prochandle cleanup
147 JNIEXPORT void JNICALL
148 Prelease(struct ps_prochandle* ph) {
149 // do the "derived class" clean-up first
150 ph->ops->release(ph);
151 destroy_lib_info(ph);
152 destroy_thread_info(ph);
153 free(ph);
154 }
155
156 lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base) {
157 return add_lib_info_fd(ph, libname, -1, base);
158 }
159
160 lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, uintptr_t base) {
161 lib_info* newlib;
162
163 if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) {
164 print_debug("can't allocate memory for lib_info\n");
165 return NULL;
166 }
167
168 if (strlen(libname) >= sizeof(newlib->name)) {
169 print_debug("libname %s too long\n", libname);
170 free(newlib);
171 return NULL;
172 }
173 strcpy(newlib->name, libname);
174
175 newlib->base = base;
176
177 if (fd == -1) {
178 if ( (newlib->fd = pathmap_open(newlib->name)) < 0) {
179 print_debug("can't open shared object %s\n", newlib->name);
180 free(newlib);
181 return NULL;
182 }
183 } else {
184 newlib->fd = fd;
185 }
186
187 // check whether we have got an ELF file. /proc/<pid>/map
188 // gives out all file mappings and not just shared objects
189 if (is_elf_file(newlib->fd) == false) {
190 close(newlib->fd);
191 free(newlib);
192 return NULL;
193 }
194
195 newlib->symtab = build_symtab(newlib->fd, libname);
196 if (newlib->symtab == NULL) {
197 print_debug("symbol table build failed for %s\n", newlib->name);
198 }
199
200 // even if symbol table building fails, we add the lib_info.
201 // This is because we may need to read from the ELF file for core file
202 // address read functionality. lookup_symbol checks for NULL symtab.
203 if (ph->libs) {
204 ph->lib_tail->next = newlib;
205 ph->lib_tail = newlib;
206 } else {
207 ph->libs = ph->lib_tail = newlib;
208 }
209 ph->num_libs++;
210
211 return newlib;
212 }
213
214 // lookup for a specific symbol
215 uintptr_t lookup_symbol(struct ps_prochandle* ph, const char* object_name,
216 const char* sym_name) {
217 // ignore object_name. search in all libraries
218 // FIXME: what should we do with object_name?? The library names are obtained
219 // by parsing /proc/<pid>/maps, which may not be the same as object_name.
337 lib_info* lib = ph->libs;
338 while (lib) {
339 if (count == index) {
340 return lib->base;
341 }
342 count++;
343 lib = lib->next;
344 }
345 return (uintptr_t)NULL;
346 }
347
348 bool find_lib(struct ps_prochandle* ph, const char *lib_name) {
349 lib_info *p = ph->libs;
350 while (p) {
351 if (strcmp(p->name, lib_name) == 0) {
352 return true;
353 }
354 p = p->next;
355 }
356 return false;
357 }
358
359 //--------------------------------------------------------------------------
360 // proc service functions
361
362 // get process id
363 JNIEXPORT pid_t JNICALL
364 ps_getpid(struct ps_prochandle *ph) {
365 return ph->pid;
366 }
367
368 // ps_pglobal_lookup() looks up the symbol sym_name in the symbol table
369 // of the load object object_name in the target process identified by ph.
370 // It returns the symbol's value as an address in the target process in
371 // *sym_addr.
372
373 JNIEXPORT ps_err_e JNICALL
374 ps_pglobal_lookup(struct ps_prochandle *ph, const char *object_name,
375 const char *sym_name, psaddr_t *sym_addr) {
376 *sym_addr = (psaddr_t) lookup_symbol(ph, object_name, sym_name);
|
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 #include <stdarg.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <fcntl.h>
29 #include <sys/procfs.h>
30 #include "libproc_impl.h"
31 #include "proc_service.h"
32 #include "salibelf.h"
33
34 #define SA_ALTROOT "SA_ALTROOT"
35
36 int pathmap_open(const char* name) {
37 static const char *alt_root = NULL;
38 static int alt_root_initialized = 0;
39
40 int fd;
41 char alt_path[PATH_MAX + 1], *alt_path_end;
42 const char *s;
43 int free_space;
44
45 if (!alt_root_initialized) {
46 alt_root_initialized = -1;
47 alt_root = getenv(SA_ALTROOT);
48 }
49
50 if (alt_root == NULL) {
51 return open(name, O_RDONLY);
52 }
111
112 bool is_debug() {
113 return _libsaproc_debug;
114 }
115
116 // initialize libproc
117 JNIEXPORT bool JNICALL
118 init_libproc(bool debug) {
119 // init debug mode
120 _libsaproc_debug = debug;
121 return true;
122 }
123
124 static void destroy_lib_info(struct ps_prochandle* ph) {
125 lib_info* lib = ph->libs;
126 while (lib) {
127 lib_info *next = lib->next;
128 if (lib->symtab) {
129 destroy_symtab(lib->symtab);
130 }
131 free(lib->eh_frame.data);
132 free(lib);
133 lib = next;
134 }
135 }
136
137 static void destroy_thread_info(struct ps_prochandle* ph) {
138 thread_info* thr = ph->threads;
139 while (thr) {
140 thread_info *next = thr->next;
141 free(thr);
142 thr = next;
143 }
144 }
145
146 // ps_prochandle cleanup
147
148 // ps_prochandle cleanup
149 JNIEXPORT void JNICALL
150 Prelease(struct ps_prochandle* ph) {
151 // do the "derived class" clean-up first
152 ph->ops->release(ph);
153 destroy_lib_info(ph);
154 destroy_thread_info(ph);
155 free(ph);
156 }
157
158 lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base) {
159 return add_lib_info_fd(ph, libname, -1, base);
160 }
161
162 static bool fill_instr_info(lib_info* lib) {
163 off_t current_pos;
164 ELF_EHDR ehdr;
165 ELF_PHDR* phbuf = NULL;
166 ELF_PHDR* ph = NULL;
167 int cnt;
168 long align = sysconf(_SC_PAGE_SIZE);
169
170 current_pos = lseek(lib->fd, (off_t)0L, SEEK_CUR);
171 lseek(lib->fd, (off_t)0L, SEEK_SET);
172 read_elf_header(lib->fd, &ehdr);
173 if ((phbuf = read_program_header_table(lib->fd, &ehdr)) == NULL) {
174 lseek(lib->fd, current_pos, SEEK_SET);
175 return false;
176 }
177
178 lib->exec_start = (uintptr_t)-1L;
179 lib->exec_end = (uintptr_t)-1L;
180 for (ph = phbuf, cnt = 0; cnt < ehdr.e_phnum; cnt++, ph++) {
181 if ((ph->p_type == PT_LOAD) && (ph->p_flags & PF_X)) {
182 print_debug("[%d] vaddr = 0x%lx, memsz = 0x%lx, filesz = 0x%lx\n", cnt, ph->p_vaddr, ph->p_memsz, ph->p_filesz);
183 if ((lib->exec_start == -1L) || (lib->exec_start > ph->p_vaddr)) {
184 lib->exec_start = ph->p_vaddr;
185 }
186 if ((lib->exec_end == (uintptr_t)-1L) || (lib->exec_end < (ph->p_vaddr + ph->p_memsz))) {
187 lib->exec_end = ph->p_vaddr + ph->p_memsz;
188 }
189 align = ph->p_align;
190 }
191 }
192
193 free(phbuf);
194 lseek(lib->fd, current_pos, SEEK_SET);
195
196 if ((lib->exec_start == -1L) || (lib->exec_end == -1L)) {
197 return false;
198 } else {
199 lib->exec_start = (lib->exec_start + lib->base) & ~(align - 1);
200 lib->exec_end = (lib->exec_end + lib->base + align) & ~(align - 1);
201 return true;
202 }
203
204 }
205
206 bool read_eh_frame(struct ps_prochandle* ph, lib_info* lib) {
207 off_t current_pos = -1;
208 ELF_EHDR ehdr;
209 ELF_SHDR* shbuf = NULL;
210 ELF_SHDR* sh = NULL;
211 char* strtab = NULL;
212 void* result = NULL;
213 int cnt;
214
215 current_pos = lseek(lib->fd, (off_t)0L, SEEK_CUR);
216 lseek(lib->fd, (off_t)0L, SEEK_SET);
217
218 read_elf_header(lib->fd, &ehdr);
219 shbuf = read_section_header_table(lib->fd, &ehdr);
220 strtab = read_section_data(lib->fd, &ehdr, &shbuf[ehdr.e_shstrndx]);
221
222 for (cnt = 0, sh = shbuf; cnt < ehdr.e_shnum; cnt++, sh++) {
223 if (strcmp(".eh_frame", sh->sh_name + strtab) == 0) {
224 lib->eh_frame.library_base_addr = lib->base;
225 lib->eh_frame.v_addr = sh->sh_addr;
226 lib->eh_frame.data = read_section_data(lib->fd, &ehdr, sh);
227 break;
228 }
229 }
230
231 free(strtab);
232 free(shbuf);
233 lseek(lib->fd, current_pos, SEEK_SET);
234 return lib->eh_frame.data != NULL;
235 }
236
237 lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, uintptr_t base) {
238 lib_info* newlib;
239
240 if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) {
241 print_debug("can't allocate memory for lib_info\n");
242 return NULL;
243 }
244
245 if (strlen(libname) >= sizeof(newlib->name)) {
246 print_debug("libname %s too long\n", libname);
247 free(newlib);
248 return NULL;
249 }
250 strcpy(newlib->name, libname);
251
252 newlib->base = base;
253
254 if (fd == -1) {
255 if ( (newlib->fd = pathmap_open(newlib->name)) < 0) {
256 print_debug("can't open shared object %s\n", newlib->name);
257 free(newlib);
258 return NULL;
259 }
260 } else {
261 newlib->fd = fd;
262 }
263
264 // check whether we have got an ELF file. /proc/<pid>/map
265 // gives out all file mappings and not just shared objects
266 if (is_elf_file(newlib->fd) == false) {
267 close(newlib->fd);
268 free(newlib);
269 return NULL;
270 }
271
272 newlib->symtab = build_symtab(newlib->fd, libname);
273 if (newlib->symtab == NULL) {
274 print_debug("symbol table build failed for %s\n", newlib->name);
275 }
276
277 if (fill_instr_info(newlib)) {
278 if (!read_eh_frame(ph, newlib)) {
279 print_debug("Could not find .eh_frame section in %s\n", newlib->name);
280 }
281 } else {
282 print_debug("Could not find executable section in %s\n", newlib->name);
283 }
284
285 // even if symbol table building fails, we add the lib_info.
286 // This is because we may need to read from the ELF file for core file
287 // address read functionality. lookup_symbol checks for NULL symtab.
288 if (ph->libs) {
289 ph->lib_tail->next = newlib;
290 ph->lib_tail = newlib;
291 } else {
292 ph->libs = ph->lib_tail = newlib;
293 }
294 ph->num_libs++;
295
296 return newlib;
297 }
298
299 // lookup for a specific symbol
300 uintptr_t lookup_symbol(struct ps_prochandle* ph, const char* object_name,
301 const char* sym_name) {
302 // ignore object_name. search in all libraries
303 // FIXME: what should we do with object_name?? The library names are obtained
304 // by parsing /proc/<pid>/maps, which may not be the same as object_name.
422 lib_info* lib = ph->libs;
423 while (lib) {
424 if (count == index) {
425 return lib->base;
426 }
427 count++;
428 lib = lib->next;
429 }
430 return (uintptr_t)NULL;
431 }
432
433 bool find_lib(struct ps_prochandle* ph, const char *lib_name) {
434 lib_info *p = ph->libs;
435 while (p) {
436 if (strcmp(p->name, lib_name) == 0) {
437 return true;
438 }
439 p = p->next;
440 }
441 return false;
442 }
443
444 struct lib_info *find_lib_by_address(struct ps_prochandle* ph, uintptr_t pc) {
445 lib_info *p = ph->libs;
446 while (p) {
447 if ((p->exec_start <= pc) && (pc < p->exec_end)) {
448 return p;
449 }
450 p = p->next;
451 }
452 return NULL;
453 }
454
455 //--------------------------------------------------------------------------
456 // proc service functions
457
458 // get process id
459 JNIEXPORT pid_t JNICALL
460 ps_getpid(struct ps_prochandle *ph) {
461 return ph->pid;
462 }
463
464 // ps_pglobal_lookup() looks up the symbol sym_name in the symbol table
465 // of the load object object_name in the target process identified by ph.
466 // It returns the symbol's value as an address in the target process in
467 // *sym_addr.
468
469 JNIEXPORT ps_err_e JNICALL
470 ps_pglobal_lookup(struct ps_prochandle *ph, const char *object_name,
471 const char *sym_name, psaddr_t *sym_addr) {
472 *sym_addr = (psaddr_t) lookup_symbol(ph, object_name, sym_name);
|