agent/src/os/bsd/libproc_impl.c

Tue, 08 Aug 2017 15:57:29 +0800

author
aoqi
date
Tue, 08 Aug 2017 15:57:29 +0800
changeset 6876
710a3c8b516e
parent 4750
39432a1cefdd
parent 0
f90c822e73f8
child 9931
fd44df5e3bc3
permissions
-rw-r--r--

merge

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

mercurial