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 #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 } 52 53 54 if (strlen(alt_root) + strlen(name) > PATH_MAX) { 55 // Buffer too small. 56 return -1; 57 } 58 59 strncpy(alt_path, alt_root, PATH_MAX); 60 alt_path[PATH_MAX] = '\0'; 61 alt_path_end = alt_path + strlen(alt_path); 62 free_space = PATH_MAX + 1 - (alt_path_end-alt_path); 63 64 // Strip path items one by one and try to open file with alt_root prepended. 65 s = name; 66 while (1) { 67 strncat(alt_path, s, free_space); 68 s += 1; // Skip /. 69 70 fd = open(alt_path, O_RDONLY); 71 if (fd >= 0) { 72 print_debug("path %s substituted for %s\n", alt_path, name); 73 return fd; 74 } 75 76 // Linker always put full path to solib to process, so we can rely 77 // on presence of /. If slash is not present, it means, that SOlib doesn't 78 // physically exist (e.g. linux-gate.so) and we fail opening it anyway 79 if ((s = strchr(s, '/')) == NULL) { 80 break; 81 } 82 83 // Cut off what we appended above. 84 *alt_path_end = '\0'; 85 } 86 87 return -1; 88 } 89 90 static bool _libsaproc_debug; 91 92 void print_debug(const char* format,...) { 93 if (_libsaproc_debug) { 94 va_list alist; 95 96 va_start(alist, format); 97 fputs("libsaproc DEBUG: ", stderr); 98 vfprintf(stderr, format, alist); 99 va_end(alist); 100 } 101 } 102 103 void print_error(const char* format,...) { 104 va_list alist; 105 va_start(alist, format); 106 fputs("ERROR: ", stderr); 107 vfprintf(stderr, format, alist); 108 va_end(alist); 109 } 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. 220 // What we need is a utility to map object_name to real file name, something 221 // dlopen() does by looking at LD_LIBRARY_PATH and /etc/ld.so.cache. For 222 // now, we just ignore object_name and do a global search for the symbol. 223 224 lib_info* lib = ph->libs; 225 while (lib) { 226 if (lib->symtab) { 227 uintptr_t res = search_symbol(lib->symtab, lib->base, sym_name, NULL); 228 if (res) return res; 229 } 230 lib = lib->next; 231 } 232 233 print_debug("lookup failed for symbol '%s' in obj '%s'\n", 234 sym_name, object_name); 235 return (uintptr_t) NULL; 236 } 237 238 239 const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* poffset) { 240 const char* res = NULL; 241 lib_info* lib = ph->libs; 242 while (lib) { 243 if (lib->symtab && addr >= lib->base) { 244 res = nearest_symbol(lib->symtab, addr - lib->base, poffset); 245 if (res) return res; 246 } 247 lib = lib->next; 248 } 249 return NULL; 250 } 251 252 // add a thread to ps_prochandle 253 thread_info* add_thread_info(struct ps_prochandle* ph, lwpid_t lwp_id) { 254 thread_info* newthr; 255 if ( (newthr = (thread_info*) calloc(1, sizeof(thread_info))) == NULL) { 256 print_debug("can't allocate memory for thread_info\n"); 257 return NULL; 258 } 259 260 // initialize thread info 261 newthr->lwp_id = lwp_id; 262 263 // add new thread to the list 264 newthr->next = ph->threads; 265 ph->threads = newthr; 266 ph->num_threads++; 267 return newthr; 268 } 269 270 void delete_thread_info(struct ps_prochandle* ph, thread_info* thr_to_be_removed) { 271 thread_info* current_thr = ph->threads; 272 273 if (thr_to_be_removed == ph->threads) { 274 ph->threads = ph->threads->next; 275 } else { 276 thread_info* previous_thr; 277 while (current_thr && current_thr != thr_to_be_removed) { 278 previous_thr = current_thr; 279 current_thr = current_thr->next; 280 } 281 if (current_thr == NULL) { 282 print_error("Could not find the thread to be removed"); 283 return; 284 } 285 previous_thr->next = current_thr->next; 286 } 287 ph->num_threads--; 288 free(current_thr); 289 } 290 291 // get number of threads 292 int get_num_threads(struct ps_prochandle* ph) { 293 return ph->num_threads; 294 } 295 296 // get lwp_id of n'th thread 297 lwpid_t get_lwp_id(struct ps_prochandle* ph, int index) { 298 int count = 0; 299 thread_info* thr = ph->threads; 300 while (thr) { 301 if (count == index) { 302 return thr->lwp_id; 303 } 304 count++; 305 thr = thr->next; 306 } 307 return -1; 308 } 309 310 // get regs for a given lwp 311 bool get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id, struct user_regs_struct* regs) { 312 return ph->ops->get_lwp_regs(ph, lwp_id, regs); 313 } 314 315 // get number of shared objects 316 int get_num_libs(struct ps_prochandle* ph) { 317 return ph->num_libs; 318 } 319 320 // get name of n'th solib 321 const char* get_lib_name(struct ps_prochandle* ph, int index) { 322 int count = 0; 323 lib_info* lib = ph->libs; 324 while (lib) { 325 if (count == index) { 326 return lib->name; 327 } 328 count++; 329 lib = lib->next; 330 } 331 return NULL; 332 } 333 334 // get base address of a lib 335 uintptr_t get_lib_base(struct ps_prochandle* ph, int index) { 336 int count = 0; 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); 377 return (*sym_addr ? PS_OK : PS_NOSYM); 378 } 379 380 // read "size" bytes info "buf" from address "addr" 381 JNIEXPORT ps_err_e JNICALL 382 ps_pdread(struct ps_prochandle *ph, psaddr_t addr, 383 void *buf, size_t size) { 384 return ph->ops->p_pread(ph, (uintptr_t) addr, buf, size)? PS_OK: PS_ERR; 385 } 386 387 // write "size" bytes of data to debuggee at address "addr" 388 JNIEXPORT ps_err_e JNICALL 389 ps_pdwrite(struct ps_prochandle *ph, psaddr_t addr, 390 const void *buf, size_t size) { 391 return ph->ops->p_pwrite(ph, (uintptr_t)addr, buf, size)? PS_OK: PS_ERR; 392 } 393 394 // ------------------------------------------------------------------------ 395 // Functions below this point are not yet implemented. They are here only 396 // to make the linker happy. 397 398 JNIEXPORT ps_err_e JNICALL 399 ps_lsetfpregs(struct ps_prochandle *ph, lwpid_t lid, const prfpregset_t *fpregs) { 400 print_debug("ps_lsetfpregs not implemented\n"); 401 return PS_OK; 402 } 403 404 JNIEXPORT ps_err_e JNICALL 405 ps_lsetregs(struct ps_prochandle *ph, lwpid_t lid, const prgregset_t gregset) { 406 print_debug("ps_lsetregs not implemented\n"); 407 return PS_OK; 408 } 409 410 JNIEXPORT ps_err_e JNICALL 411 ps_lgetfpregs(struct ps_prochandle *ph, lwpid_t lid, prfpregset_t *fpregs) { 412 print_debug("ps_lgetfpregs not implemented\n"); 413 return PS_OK; 414 } 415 416 JNIEXPORT ps_err_e JNICALL 417 ps_lgetregs(struct ps_prochandle *ph, lwpid_t lid, prgregset_t gregset) { 418 print_debug("ps_lgetfpregs not implemented\n"); 419 return PS_OK; 420 } 421