1/* 2 * Copyright (c) 2003, 2013, 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 "libproc_impl.h" 25 26static const char* alt_root = NULL; 27static int alt_root_len = -1; 28 29#define SA_ALTROOT "SA_ALTROOT" 30 31off_t ltell(int fd) { 32 return lseek(fd, 0, SEEK_CUR); 33} 34 35static void init_alt_root() { 36 if (alt_root_len == -1) { 37 alt_root = getenv(SA_ALTROOT); 38 if (alt_root) { 39 alt_root_len = strlen(alt_root); 40 } else { 41 alt_root_len = 0; 42 } 43 } 44} 45 46int pathmap_open(const char* name) { 47 int fd; 48 char alt_path[PATH_MAX + 1]; 49 50 init_alt_root(); 51 52 if (alt_root_len > 0) { 53 strcpy(alt_path, alt_root); 54 strcat(alt_path, name); 55 fd = open(alt_path, O_RDONLY); 56 if (fd >= 0) { 57 print_debug("path %s substituted for %s\n", alt_path, name); 58 return fd; 59 } 60 61 if (strrchr(name, '/')) { 62 strcpy(alt_path, alt_root); 63 strcat(alt_path, strrchr(name, '/')); 64 fd = open(alt_path, O_RDONLY); 65 if (fd >= 0) { 66 print_debug("path %s substituted for %s\n", alt_path, name); 67 return fd; 68 } 69 } 70 } else { 71 fd = open(name, O_RDONLY); 72 if (fd >= 0) { 73 return fd; 74 } 75 } 76 return -1; 77} 78 79static bool _libsaproc_debug; 80 81void print_debug(const char* format,...) { 82 if (_libsaproc_debug) { 83 va_list alist; 84 85 va_start(alist, format); 86 fputs("libsaproc DEBUG: ", stderr); 87 vfprintf(stderr, format, alist); 88 va_end(alist); 89 } 90} 91 92void print_error(const char* format,...) { 93 va_list alist; 94 va_start(alist, format); 95 fputs("ERROR: ", stderr); 96 vfprintf(stderr, format, alist); 97 va_end(alist); 98} 99 100bool is_debug() { 101 return _libsaproc_debug; 102} 103 104#ifdef __APPLE__ 105// get arch offset in file 106bool get_arch_off(int fd, cpu_type_t cputype, off_t *offset) { 107 struct fat_header fatheader; 108 struct fat_arch fatarch; 109 off_t img_start = 0; 110 111 off_t pos = ltell(fd); 112 if (read(fd, (void *)&fatheader, sizeof(struct fat_header)) != sizeof(struct fat_header)) { 113 return false; 114 } 115 if (fatheader.magic == FAT_CIGAM) { 116 int i; 117 for (i = 0; i < ntohl(fatheader.nfat_arch); i++) { 118 if (read(fd, (void *)&fatarch, sizeof(struct fat_arch)) != sizeof(struct fat_arch)) { 119 return false; 120 } 121 if (ntohl(fatarch.cputype) == cputype) { 122 print_debug("fat offset=%x\n", ntohl(fatarch.offset)); 123 img_start = ntohl(fatarch.offset); 124 break; 125 } 126 } 127 if (img_start == 0) { 128 return false; 129 } 130 } 131 lseek(fd, pos, SEEK_SET); 132 *offset = img_start; 133 return true; 134} 135 136bool is_macho_file(int fd) { 137 mach_header_64 fhdr; 138 off_t x86_64_off; 139 140 if (fd < 0) { 141 print_debug("Invalid file handle passed to is_macho_file\n"); 142 return false; 143 } 144 145 off_t pos = ltell(fd); 146 // check fat header 147 if (!get_arch_off(fd, CPU_TYPE_X86_64, &x86_64_off)) { 148 print_debug("failed to get fat header\n"); 149 return false; 150 } 151 lseek(fd, x86_64_off, SEEK_SET); 152 if (read(fd, (void *)&fhdr, sizeof(mach_header_64)) != sizeof(mach_header_64)) { 153 return false; 154 } 155 lseek(fd, pos, SEEK_SET); // restore 156 print_debug("fhdr.magic %x\n", fhdr.magic); 157 return (fhdr.magic == MH_MAGIC_64 || fhdr.magic == MH_CIGAM_64); 158} 159 160#endif //__APPLE__ 161 162// initialize libproc 163bool init_libproc(bool debug) { 164 _libsaproc_debug = debug; 165#ifndef __APPLE__ 166 // initialize the thread_db library 167 if (td_init() != TD_OK) { 168 print_debug("libthread_db's td_init failed\n"); 169 return false; 170 } 171#endif // __APPLE__ 172 return true; 173} 174 175void destroy_lib_info(struct ps_prochandle* ph) { 176 lib_info* lib = ph->libs; 177 while (lib) { 178 lib_info* next = lib->next; 179 if (lib->symtab) { 180 destroy_symtab(lib->symtab); 181 } 182 free(lib); 183 lib = next; 184 } 185} 186 187void destroy_thread_info(struct ps_prochandle* ph) { 188 sa_thread_info* thr = ph->threads; 189 while (thr) { 190 sa_thread_info* n = thr->next; 191 free(thr); 192 thr = n; 193 } 194} 195 196// ps_prochandle cleanup 197void Prelease(struct ps_prochandle* ph) { 198 // do the "derived class" clean-up first 199 ph->ops->release(ph); 200 destroy_lib_info(ph); 201 destroy_thread_info(ph); 202 free(ph); 203} 204 205lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base) { 206 return add_lib_info_fd(ph, libname, -1, base); 207} 208 209lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, uintptr_t base) { 210 lib_info* newlib; 211 print_debug("add_lib_info_fd %s\n", libname); 212 213 if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) { 214 print_debug("can't allocate memory for lib_info\n"); 215 return NULL; 216 } 217 218 if (strlen(libname) >= sizeof(newlib->name)) { 219 print_debug("libname %s too long\n", libname); 220 free(newlib); 221 return NULL; 222 } 223 strcpy(newlib->name, libname); 224 225 newlib->base = base; 226 227 if (fd == -1) { 228 if ( (newlib->fd = pathmap_open(newlib->name)) < 0) { 229 print_debug("can't open shared object %s\n", newlib->name); 230 free(newlib); 231 return NULL; 232 } 233 } else { 234 newlib->fd = fd; 235 } 236 237#ifdef __APPLE__ 238 // check whether we have got an Macho file. 239 if (is_macho_file(newlib->fd) == false) { 240 close(newlib->fd); 241 free(newlib); 242 print_debug("not a mach-o file\n"); 243 return NULL; 244 } 245#else 246 // check whether we have got an ELF file. /proc/<pid>/map 247 // gives out all file mappings and not just shared objects 248 if (is_elf_file(newlib->fd) == false) { 249 close(newlib->fd); 250 free(newlib); 251 return NULL; 252 } 253#endif // __APPLE__ 254 255 newlib->symtab = build_symtab(newlib->fd); 256 if (newlib->symtab == NULL) { 257 print_debug("symbol table build failed for %s\n", newlib->name); 258 } else { 259 print_debug("built symbol table for %s\n", newlib->name); 260 } 261 262 // even if symbol table building fails, we add the lib_info. 263 // This is because we may need to read from the ELF file or MachO file for core file 264 // address read functionality. lookup_symbol checks for NULL symtab. 265 if (ph->libs) { 266 ph->lib_tail->next = newlib; 267 ph->lib_tail = newlib; 268 } else { 269 ph->libs = ph->lib_tail = newlib; 270 } 271 ph->num_libs++; 272 return newlib; 273} 274 275// lookup for a specific symbol 276uintptr_t lookup_symbol(struct ps_prochandle* ph, const char* object_name, 277 const char* sym_name) { 278 // ignore object_name. search in all libraries 279 // FIXME: what should we do with object_name?? The library names are obtained 280 // by parsing /proc/<pid>/maps, which may not be the same as object_name. 281 // What we need is a utility to map object_name to real file name, something 282 // dlopen() does by looking at LD_LIBRARY_PATH and /etc/ld.so.cache. For 283 // now, we just ignore object_name and do a global search for the symbol. 284 285 lib_info* lib = ph->libs; 286 while (lib) { 287 if (lib->symtab) { 288 uintptr_t res = search_symbol(lib->symtab, lib->base, sym_name, NULL); 289 if (res) return res; 290 } 291 lib = lib->next; 292 } 293 294 print_debug("lookup failed for symbol '%s' in obj '%s'\n", 295 sym_name, object_name); 296 return (uintptr_t) NULL; 297} 298 299const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* poffset) { 300 const char* res = NULL; 301 lib_info* lib = ph->libs; 302 while (lib) { 303 if (lib->symtab && addr >= lib->base) { 304 res = nearest_symbol(lib->symtab, addr - lib->base, poffset); 305 if (res) return res; 306 } 307 lib = lib->next; 308 } 309 return NULL; 310} 311 312// add a thread to ps_prochandle 313sa_thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) { 314 sa_thread_info* newthr; 315 if ( (newthr = (sa_thread_info*) calloc(1, sizeof(sa_thread_info))) == NULL) { 316 print_debug("can't allocate memory for thread_info\n"); 317 return NULL; 318 } 319 320 // initialize thread info 321 newthr->pthread_id = pthread_id; 322 newthr->lwp_id = lwp_id; 323 324 // add new thread to the list 325 newthr->next = ph->threads; 326 ph->threads = newthr; 327 ph->num_threads++; 328 return newthr; 329} 330 331#ifndef __APPLE__ 332// struct used for client data from thread_db callback 333struct thread_db_client_data { 334 struct ps_prochandle* ph; 335 thread_info_callback callback; 336}; 337 338// callback function for libthread_db 339static int thread_db_callback(const td_thrhandle_t *th_p, void *data) { 340 struct thread_db_client_data* ptr = (struct thread_db_client_data*) data; 341 td_thrinfo_t ti; 342 td_err_e err; 343 344 memset(&ti, 0, sizeof(ti)); 345 err = td_thr_get_info(th_p, &ti); 346 if (err != TD_OK) { 347 print_debug("libthread_db : td_thr_get_info failed, can't get thread info\n"); 348 return err; 349 } 350 351 print_debug("thread_db : pthread %d (lwp %d)\n", ti.ti_tid, ti.ti_lid); 352 353 if (ptr->callback(ptr->ph, (pthread_t)ti.ti_tid, ti.ti_lid) != true) 354 return TD_ERR; 355 356 return TD_OK; 357} 358 359// read thread_info using libthread_db 360bool read_thread_info(struct ps_prochandle* ph, thread_info_callback cb) { 361 struct thread_db_client_data mydata; 362 td_thragent_t* thread_agent = NULL; 363 if (td_ta_new(ph, &thread_agent) != TD_OK) { 364 print_debug("can't create libthread_db agent\n"); 365 return false; 366 } 367 368 mydata.ph = ph; 369 mydata.callback = cb; 370 371 // we use libthread_db iterator to iterate thru list of threads. 372 if (td_ta_thr_iter(thread_agent, thread_db_callback, &mydata, 373 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, 374 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS) != TD_OK) { 375 td_ta_delete(thread_agent); 376 return false; 377 } 378 379 // delete thread agent 380 td_ta_delete(thread_agent); 381 return true; 382} 383 384#endif // __APPLE__ 385 386// get number of threads 387int get_num_threads(struct ps_prochandle* ph) { 388 return ph->num_threads; 389} 390 391// get lwp_id of n'th thread 392lwpid_t get_lwp_id(struct ps_prochandle* ph, int index) { 393 int count = 0; 394 sa_thread_info* thr = ph->threads; 395 while (thr) { 396 if (count == index) { 397 return thr->lwp_id; 398 } 399 count++; 400 thr = thr->next; 401 } 402 return 0; 403} 404 405#ifdef __APPLE__ 406// set lwp_id of n'th thread 407bool set_lwp_id(struct ps_prochandle* ph, int index, lwpid_t lwpid) { 408 int count = 0; 409 sa_thread_info* thr = ph->threads; 410 while (thr) { 411 if (count == index) { 412 thr->lwp_id = lwpid; 413 return true; 414 } 415 count++; 416 thr = thr->next; 417 } 418 return false; 419} 420 421// get regs of n-th thread, only used in fillThreads the first time called 422bool get_nth_lwp_regs(struct ps_prochandle* ph, int index, struct reg* regs) { 423 int count = 0; 424 sa_thread_info* thr = ph->threads; 425 while (thr) { 426 if (count == index) { 427 break; 428 } 429 count++; 430 thr = thr->next; 431 } 432 if (thr != NULL) { 433 memcpy(regs, &thr->regs, sizeof(struct reg)); 434 return true; 435 } 436 return false; 437} 438 439#endif // __APPLE__ 440 441// get regs for a given lwp 442bool get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id, struct reg* regs) { 443 return ph->ops->get_lwp_regs(ph, lwp_id, regs); 444} 445 446// get number of shared objects 447int get_num_libs(struct ps_prochandle* ph) { 448 return ph->num_libs; 449} 450 451// get name of n'th solib 452const char* get_lib_name(struct ps_prochandle* ph, int index) { 453 int count = 0; 454 lib_info* lib = ph->libs; 455 while (lib) { 456 if (count == index) { 457 return lib->name; 458 } 459 count++; 460 lib = lib->next; 461 } 462 return NULL; 463} 464 465// get base address of a lib 466uintptr_t get_lib_base(struct ps_prochandle* ph, int index) { 467 int count = 0; 468 lib_info* lib = ph->libs; 469 while (lib) { 470 if (count == index) { 471 return lib->base; 472 } 473 count++; 474 lib = lib->next; 475 } 476 return (uintptr_t)NULL; 477} 478 479bool find_lib(struct ps_prochandle* ph, const char *lib_name) { 480 lib_info *p = ph->libs; 481 while (p) { 482 if (strcmp(p->name, lib_name) == 0) { 483 return true; 484 } 485 p = p->next; 486 } 487 return false; 488} 489 490//-------------------------------------------------------------------------- 491// proc service functions 492 493// ps_pglobal_lookup() looks up the symbol sym_name in the symbol table 494// of the load object object_name in the target process identified by ph. 495// It returns the symbol's value as an address in the target process in 496// *sym_addr. 497 498ps_err_e ps_pglobal_lookup(struct ps_prochandle *ph, const char *object_name, 499 const char *sym_name, psaddr_t *sym_addr) { 500 *sym_addr = (psaddr_t) lookup_symbol(ph, object_name, sym_name); 501 return (*sym_addr ? PS_OK : PS_NOSYM); 502} 503 504// read "size" bytes info "buf" from address "addr" 505ps_err_e ps_pread(struct ps_prochandle *ph, psaddr_t addr, 506 void *buf, size_t size) { 507 return ph->ops->p_pread(ph, (uintptr_t) addr, buf, size)? PS_OK: PS_ERR; 508} 509 510// write "size" bytes of data to debuggee at address "addr" 511ps_err_e ps_pwrite(struct ps_prochandle *ph, psaddr_t addr, 512 const void *buf, size_t size) { 513 return ph->ops->p_pwrite(ph, (uintptr_t)addr, buf, size)? PS_OK: PS_ERR; 514} 515 516// fill in ptrace_lwpinfo for lid 517ps_err_e ps_linfo(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo) { 518 return ph->ops->get_lwp_info(ph, lwp_id, linfo)? PS_OK: PS_ERR; 519} 520 521// needed for when libthread_db is compiled with TD_DEBUG defined 522void 523ps_plog (const char *format, ...) 524{ 525 va_list alist; 526 527 va_start(alist, format); 528 vfprintf(stderr, format, alist); 529 va_end(alist); 530} 531 532#ifndef __APPLE__ 533// ------------------------------------------------------------------------ 534// Functions below this point are not yet implemented. They are here only 535// to make the linker happy. 536 537ps_err_e ps_lsetfpregs(struct ps_prochandle *ph, lwpid_t lid, const prfpregset_t *fpregs) { 538 print_debug("ps_lsetfpregs not implemented\n"); 539 return PS_OK; 540} 541 542ps_err_e ps_lsetregs(struct ps_prochandle *ph, lwpid_t lid, const prgregset_t gregset) { 543 print_debug("ps_lsetregs not implemented\n"); 544 return PS_OK; 545} 546 547ps_err_e ps_lgetfpregs(struct ps_prochandle *ph, lwpid_t lid, prfpregset_t *fpregs) { 548 print_debug("ps_lgetfpregs not implemented\n"); 549 return PS_OK; 550} 551 552ps_err_e ps_lgetregs(struct ps_prochandle *ph, lwpid_t lid, prgregset_t gregset) { 553 print_debug("ps_lgetfpregs not implemented\n"); 554 return PS_OK; 555} 556 557ps_err_e ps_lstop(struct ps_prochandle *ph, lwpid_t lid) { 558 print_debug("ps_lstop not implemented\n"); 559 return PS_OK; 560} 561 562ps_err_e ps_pcontinue(struct ps_prochandle *ph) { 563 print_debug("ps_pcontinue not implemented\n"); 564 return PS_OK; 565} 566#endif // __APPLE__ 567