agent/src/os/bsd/libproc_impl.c

changeset 4750
39432a1cefdd
parent 4599
2394a89e89f4
child 6876
710a3c8b516e
child 9920
3a3803a0c789
     1.1 --- a/agent/src/os/bsd/libproc_impl.c	Wed Mar 13 17:34:29 2013 -0400
     1.2 +++ b/agent/src/os/bsd/libproc_impl.c	Thu Mar 14 00:33:08 2013 -0700
     1.3 @@ -21,12 +21,6 @@
     1.4   * questions.
     1.5   *
     1.6   */
     1.7 -#include <stdarg.h>
     1.8 -#include <stdio.h>
     1.9 -#include <stdlib.h>
    1.10 -#include <string.h>
    1.11 -#include <fcntl.h>
    1.12 -#include <thread_db.h>
    1.13  #include "libproc_impl.h"
    1.14  
    1.15  static const char* alt_root = NULL;
    1.16 @@ -34,61 +28,65 @@
    1.17  
    1.18  #define SA_ALTROOT "SA_ALTROOT"
    1.19  
    1.20 +off_t ltell(int fd) {
    1.21 +  return lseek(fd, 0, SEEK_CUR);
    1.22 +}
    1.23 +
    1.24  static void init_alt_root() {
    1.25 -   if (alt_root_len == -1) {
    1.26 -      alt_root = getenv(SA_ALTROOT);
    1.27 -      if (alt_root) {
    1.28 -         alt_root_len = strlen(alt_root);
    1.29 -      } else {
    1.30 -         alt_root_len = 0;
    1.31 -      }
    1.32 -   }
    1.33 +  if (alt_root_len == -1) {
    1.34 +    alt_root = getenv(SA_ALTROOT);
    1.35 +    if (alt_root) {
    1.36 +      alt_root_len = strlen(alt_root);
    1.37 +    } else {
    1.38 +      alt_root_len = 0;
    1.39 +    }
    1.40 +  }
    1.41  }
    1.42  
    1.43  int pathmap_open(const char* name) {
    1.44 -   int fd;
    1.45 -   char alt_path[PATH_MAX + 1];
    1.46 +  int fd;
    1.47 +  char alt_path[PATH_MAX + 1];
    1.48  
    1.49 -   init_alt_root();
    1.50 -   fd = open(name, O_RDONLY);
    1.51 -   if (fd >= 0) {
    1.52 +  init_alt_root();
    1.53 +
    1.54 +  if (alt_root_len > 0) {
    1.55 +    strcpy(alt_path, alt_root);
    1.56 +    strcat(alt_path, name);
    1.57 +    fd = open(alt_path, O_RDONLY);
    1.58 +    if (fd >= 0) {
    1.59 +      print_debug("path %s substituted for %s\n", alt_path, name);
    1.60        return fd;
    1.61 -   }
    1.62 +    }
    1.63  
    1.64 -   if (alt_root_len > 0) {
    1.65 +    if (strrchr(name, '/')) {
    1.66        strcpy(alt_path, alt_root);
    1.67 -      strcat(alt_path, name);
    1.68 +      strcat(alt_path, strrchr(name, '/'));
    1.69        fd = open(alt_path, O_RDONLY);
    1.70        if (fd >= 0) {
    1.71 -         print_debug("path %s substituted for %s\n", alt_path, name);
    1.72 -         return fd;
    1.73 +        print_debug("path %s substituted for %s\n", alt_path, name);
    1.74 +        return fd;
    1.75        }
    1.76 -
    1.77 -      if (strrchr(name, '/')) {
    1.78 -         strcpy(alt_path, alt_root);
    1.79 -         strcat(alt_path, strrchr(name, '/'));
    1.80 -         fd = open(alt_path, O_RDONLY);
    1.81 -         if (fd >= 0) {
    1.82 -            print_debug("path %s substituted for %s\n", alt_path, name);
    1.83 -            return fd;
    1.84 -         }
    1.85 -      }
    1.86 -   }
    1.87 -
    1.88 -   return -1;
    1.89 +    }
    1.90 +  } else {
    1.91 +    fd = open(name, O_RDONLY);
    1.92 +    if (fd >= 0) {
    1.93 +      return fd;
    1.94 +    }
    1.95 +  }
    1.96 +  return -1;
    1.97  }
    1.98  
    1.99  static bool _libsaproc_debug;
   1.100  
   1.101  void print_debug(const char* format,...) {
   1.102 -   if (_libsaproc_debug) {
   1.103 -     va_list alist;
   1.104 +  if (_libsaproc_debug) {
   1.105 +    va_list alist;
   1.106  
   1.107 -     va_start(alist, format);
   1.108 -     fputs("libsaproc DEBUG: ", stderr);
   1.109 -     vfprintf(stderr, format, alist);
   1.110 -     va_end(alist);
   1.111 -   }
   1.112 +    va_start(alist, format);
   1.113 +    fputs("libsaproc DEBUG: ", stderr);
   1.114 +    vfprintf(stderr, format, alist);
   1.115 +    va_end(alist);
   1.116 +  }
   1.117  }
   1.118  
   1.119  void print_error(const char* format,...) {
   1.120 @@ -100,172 +98,235 @@
   1.121  }
   1.122  
   1.123  bool is_debug() {
   1.124 -   return _libsaproc_debug;
   1.125 +  return _libsaproc_debug;
   1.126  }
   1.127  
   1.128 +#ifdef __APPLE__
   1.129 +// get arch offset in file
   1.130 +bool get_arch_off(int fd, cpu_type_t cputype, off_t *offset) {
   1.131 +  struct fat_header fatheader;
   1.132 +  struct fat_arch fatarch;
   1.133 +  off_t img_start = 0;
   1.134 +
   1.135 +  off_t pos = ltell(fd);
   1.136 +  if (read(fd, (void *)&fatheader, sizeof(struct fat_header)) != sizeof(struct fat_header)) {
   1.137 +    return false;
   1.138 +  }
   1.139 +  if (fatheader.magic == FAT_CIGAM) {
   1.140 +    int i;
   1.141 +    for (i = 0; i < ntohl(fatheader.nfat_arch); i++) {
   1.142 +      if (read(fd, (void *)&fatarch, sizeof(struct fat_arch)) != sizeof(struct fat_arch)) {
   1.143 +        return false;
   1.144 +      }
   1.145 +      if (ntohl(fatarch.cputype) == cputype) {
   1.146 +        print_debug("fat offset=%x\n", ntohl(fatarch.offset));
   1.147 +        img_start = ntohl(fatarch.offset);
   1.148 +        break;
   1.149 +      }
   1.150 +    }
   1.151 +    if (img_start == 0) {
   1.152 +      return false;
   1.153 +    }
   1.154 +  }
   1.155 +  lseek(fd, pos, SEEK_SET);
   1.156 +  *offset = img_start;
   1.157 +  return true;
   1.158 +}
   1.159 +
   1.160 +bool is_macho_file(int fd) {
   1.161 +  mach_header_64 fhdr;
   1.162 +  off_t x86_64_off;
   1.163 +
   1.164 +  if (fd < 0) {
   1.165 +    print_debug("Invalid file handle passed to is_macho_file\n");
   1.166 +    return false;
   1.167 +  }
   1.168 +
   1.169 +  off_t pos = ltell(fd);
   1.170 +  // check fat header
   1.171 +  if (!get_arch_off(fd, CPU_TYPE_X86_64, &x86_64_off)) {
   1.172 +    print_debug("failed to get fat header\n");
   1.173 +    return false;
   1.174 +  }
   1.175 +  lseek(fd, x86_64_off, SEEK_SET);
   1.176 +  if (read(fd, (void *)&fhdr, sizeof(mach_header_64)) != sizeof(mach_header_64)) {
   1.177 +     return false;
   1.178 +  }
   1.179 +  lseek(fd, pos, SEEK_SET);               // restore
   1.180 +  print_debug("fhdr.magic %x\n", fhdr.magic);
   1.181 +  return (fhdr.magic == MH_MAGIC_64 || fhdr.magic == MH_CIGAM_64);
   1.182 +}
   1.183 +
   1.184 +#endif //__APPLE__
   1.185 +
   1.186  // initialize libproc
   1.187  bool init_libproc(bool debug) {
   1.188 -   // init debug mode
   1.189     _libsaproc_debug = debug;
   1.190 -
   1.191 +#ifndef __APPLE__
   1.192     // initialize the thread_db library
   1.193     if (td_init() != TD_OK) {
   1.194       print_debug("libthread_db's td_init failed\n");
   1.195       return false;
   1.196     }
   1.197 -
   1.198 +#endif // __APPLE__
   1.199     return true;
   1.200  }
   1.201  
   1.202 -static void destroy_lib_info(struct ps_prochandle* ph) {
   1.203 -   lib_info* lib = ph->libs;
   1.204 -   while (lib) {
   1.205 -     lib_info *next = lib->next;
   1.206 -     if (lib->symtab) {
   1.207 -        destroy_symtab(lib->symtab);
   1.208 -     }
   1.209 -     free(lib);
   1.210 -     lib = next;
   1.211 -   }
   1.212 +void destroy_lib_info(struct ps_prochandle* ph) {
   1.213 +  lib_info* lib = ph->libs;
   1.214 +  while (lib) {
   1.215 +    lib_info* next = lib->next;
   1.216 +    if (lib->symtab) {
   1.217 +      destroy_symtab(lib->symtab);
   1.218 +    }
   1.219 +    free(lib);
   1.220 +    lib = next;
   1.221 +  }
   1.222  }
   1.223  
   1.224 -static void destroy_thread_info(struct ps_prochandle* ph) {
   1.225 -   thread_info* thr = ph->threads;
   1.226 -   while (thr) {
   1.227 -     thread_info *next = thr->next;
   1.228 -     free(thr);
   1.229 -     thr = next;
   1.230 -   }
   1.231 +void destroy_thread_info(struct ps_prochandle* ph) {
   1.232 +  sa_thread_info* thr = ph->threads;
   1.233 +  while (thr) {
   1.234 +    sa_thread_info* n = thr->next;
   1.235 +    free(thr);
   1.236 +    thr = n;
   1.237 +  }
   1.238  }
   1.239  
   1.240  // ps_prochandle cleanup
   1.241 -
   1.242 -// ps_prochandle cleanup
   1.243  void Prelease(struct ps_prochandle* ph) {
   1.244 -   // do the "derived class" clean-up first
   1.245 -   ph->ops->release(ph);
   1.246 -   destroy_lib_info(ph);
   1.247 -   destroy_thread_info(ph);
   1.248 -   free(ph);
   1.249 +  // do the "derived class" clean-up first
   1.250 +  ph->ops->release(ph);
   1.251 +  destroy_lib_info(ph);
   1.252 +  destroy_thread_info(ph);
   1.253 +  free(ph);
   1.254  }
   1.255  
   1.256  lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base) {
   1.257 -   return add_lib_info_fd(ph, libname, -1, base);
   1.258 +  return add_lib_info_fd(ph, libname, -1, base);
   1.259  }
   1.260  
   1.261  lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, uintptr_t base) {
   1.262     lib_info* newlib;
   1.263 +  print_debug("add_lib_info_fd %s\n", libname);
   1.264  
   1.265 -   if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) {
   1.266 -      print_debug("can't allocate memory for lib_info\n");
   1.267 -      return NULL;
   1.268 -   }
   1.269 +  if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) {
   1.270 +    print_debug("can't allocate memory for lib_info\n");
   1.271 +    return NULL;
   1.272 +  }
   1.273  
   1.274 -   strncpy(newlib->name, libname, sizeof(newlib->name));
   1.275 -   newlib->base = base;
   1.276 +  strncpy(newlib->name, libname, sizeof(newlib->name));
   1.277 +  newlib->base = base;
   1.278  
   1.279 -   if (fd == -1) {
   1.280 -      if ( (newlib->fd = pathmap_open(newlib->name)) < 0) {
   1.281 -         print_debug("can't open shared object %s\n", newlib->name);
   1.282 -         free(newlib);
   1.283 -         return NULL;
   1.284 -      }
   1.285 -   } else {
   1.286 -      newlib->fd = fd;
   1.287 -   }
   1.288 -
   1.289 -   // check whether we have got an ELF file. /proc/<pid>/map
   1.290 -   // gives out all file mappings and not just shared objects
   1.291 -   if (is_elf_file(newlib->fd) == false) {
   1.292 -      close(newlib->fd);
   1.293 +  if (fd == -1) {
   1.294 +    if ( (newlib->fd = pathmap_open(newlib->name)) < 0) {
   1.295 +      print_debug("can't open shared object %s\n", newlib->name);
   1.296        free(newlib);
   1.297        return NULL;
   1.298 -   }
   1.299 +    }
   1.300 +  } else {
   1.301 +    newlib->fd = fd;
   1.302 +  }
   1.303  
   1.304 -   newlib->symtab = build_symtab(newlib->fd);
   1.305 -   if (newlib->symtab == NULL) {
   1.306 -      print_debug("symbol table build failed for %s\n", newlib->name);
   1.307 -   }
   1.308 -   else {
   1.309 -      print_debug("built symbol table for %s\n", newlib->name);
   1.310 -   }
   1.311 +#ifdef __APPLE__
   1.312 +  // check whether we have got an Macho file.
   1.313 +  if (is_macho_file(newlib->fd) == false) {
   1.314 +    close(newlib->fd);
   1.315 +    free(newlib);
   1.316 +    print_debug("not a mach-o file\n");
   1.317 +    return NULL;
   1.318 +  }
   1.319 +#else
   1.320 +  // check whether we have got an ELF file. /proc/<pid>/map
   1.321 +  // gives out all file mappings and not just shared objects
   1.322 +  if (is_elf_file(newlib->fd) == false) {
   1.323 +    close(newlib->fd);
   1.324 +    free(newlib);
   1.325 +    return NULL;
   1.326 +  }
   1.327 +#endif // __APPLE__
   1.328  
   1.329 -   // even if symbol table building fails, we add the lib_info.
   1.330 -   // This is because we may need to read from the ELF file for core file
   1.331 -   // address read functionality. lookup_symbol checks for NULL symtab.
   1.332 -   if (ph->libs) {
   1.333 -      ph->lib_tail->next = newlib;
   1.334 -      ph->lib_tail = newlib;
   1.335 -   }  else {
   1.336 -      ph->libs = ph->lib_tail = newlib;
   1.337 -   }
   1.338 -   ph->num_libs++;
   1.339 +  newlib->symtab = build_symtab(newlib->fd);
   1.340 +  if (newlib->symtab == NULL) {
   1.341 +    print_debug("symbol table build failed for %s\n", newlib->name);
   1.342 +  } else {
   1.343 +    print_debug("built symbol table for %s\n", newlib->name);
   1.344 +  }
   1.345  
   1.346 -   return newlib;
   1.347 +  // even if symbol table building fails, we add the lib_info.
   1.348 +  // This is because we may need to read from the ELF file or MachO file for core file
   1.349 +  // address read functionality. lookup_symbol checks for NULL symtab.
   1.350 +  if (ph->libs) {
   1.351 +    ph->lib_tail->next = newlib;
   1.352 +    ph->lib_tail = newlib;
   1.353 +  }  else {
   1.354 +    ph->libs = ph->lib_tail = newlib;
   1.355 +  }
   1.356 +  ph->num_libs++;
   1.357 +  return newlib;
   1.358  }
   1.359  
   1.360  // lookup for a specific symbol
   1.361  uintptr_t lookup_symbol(struct ps_prochandle* ph,  const char* object_name,
   1.362                         const char* sym_name) {
   1.363 -   // ignore object_name. search in all libraries
   1.364 -   // FIXME: what should we do with object_name?? The library names are obtained
   1.365 -   // by parsing /proc/<pid>/maps, which may not be the same as object_name.
   1.366 -   // What we need is a utility to map object_name to real file name, something
   1.367 -   // dlopen() does by looking at LD_LIBRARY_PATH and /etc/ld.so.cache. For
   1.368 -   // now, we just ignore object_name and do a global search for the symbol.
   1.369 +  // ignore object_name. search in all libraries
   1.370 +  // FIXME: what should we do with object_name?? The library names are obtained
   1.371 +  // by parsing /proc/<pid>/maps, which may not be the same as object_name.
   1.372 +  // What we need is a utility to map object_name to real file name, something
   1.373 +  // dlopen() does by looking at LD_LIBRARY_PATH and /etc/ld.so.cache. For
   1.374 +  // now, we just ignore object_name and do a global search for the symbol.
   1.375  
   1.376 -   lib_info* lib = ph->libs;
   1.377 -   while (lib) {
   1.378 -      if (lib->symtab) {
   1.379 -         uintptr_t res = search_symbol(lib->symtab, lib->base, sym_name, NULL);
   1.380 -         if (res) return res;
   1.381 -      }
   1.382 -      lib = lib->next;
   1.383 -   }
   1.384 +  lib_info* lib = ph->libs;
   1.385 +  while (lib) {
   1.386 +    if (lib->symtab) {
   1.387 +      uintptr_t res = search_symbol(lib->symtab, lib->base, sym_name, NULL);
   1.388 +      if (res) return res;
   1.389 +    }
   1.390 +    lib = lib->next;
   1.391 +  }
   1.392  
   1.393 -   print_debug("lookup failed for symbol '%s' in obj '%s'\n",
   1.394 +  print_debug("lookup failed for symbol '%s' in obj '%s'\n",
   1.395                            sym_name, object_name);
   1.396 -   return (uintptr_t) NULL;
   1.397 +  return (uintptr_t) NULL;
   1.398  }
   1.399  
   1.400 -
   1.401  const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* poffset) {
   1.402 -   const char* res = NULL;
   1.403 -   lib_info* lib = ph->libs;
   1.404 -   while (lib) {
   1.405 -      if (lib->symtab && addr >= lib->base) {
   1.406 -         res = nearest_symbol(lib->symtab, addr - lib->base, poffset);
   1.407 -         if (res) return res;
   1.408 -      }
   1.409 -      lib = lib->next;
   1.410 -   }
   1.411 -   return NULL;
   1.412 +  const char* res = NULL;
   1.413 +  lib_info* lib = ph->libs;
   1.414 +  while (lib) {
   1.415 +    if (lib->symtab && addr >= lib->base) {
   1.416 +      res = nearest_symbol(lib->symtab, addr - lib->base, poffset);
   1.417 +      if (res) return res;
   1.418 +    }
   1.419 +    lib = lib->next;
   1.420 +  }
   1.421 +  return NULL;
   1.422  }
   1.423  
   1.424  // add a thread to ps_prochandle
   1.425 -thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
   1.426 -   thread_info* newthr;
   1.427 -   if ( (newthr = (thread_info*) calloc(1, sizeof(thread_info))) == NULL) {
   1.428 -      print_debug("can't allocate memory for thread_info\n");
   1.429 -      return NULL;
   1.430 -   }
   1.431 +sa_thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
   1.432 +  sa_thread_info* newthr;
   1.433 +  if ( (newthr = (sa_thread_info*) calloc(1, sizeof(sa_thread_info))) == NULL) {
   1.434 +    print_debug("can't allocate memory for thread_info\n");
   1.435 +    return NULL;
   1.436 +  }
   1.437  
   1.438 -   // initialize thread info
   1.439 -   newthr->pthread_id = pthread_id;
   1.440 -   newthr->lwp_id = lwp_id;
   1.441 +  // initialize thread info
   1.442 +  newthr->pthread_id = pthread_id;
   1.443 +  newthr->lwp_id = lwp_id;
   1.444  
   1.445 -   // add new thread to the list
   1.446 -   newthr->next = ph->threads;
   1.447 -   ph->threads = newthr;
   1.448 -   ph->num_threads++;
   1.449 -   return newthr;
   1.450 +  // add new thread to the list
   1.451 +  newthr->next = ph->threads;
   1.452 +  ph->threads = newthr;
   1.453 +  ph->num_threads++;
   1.454 +  return newthr;
   1.455  }
   1.456  
   1.457 -
   1.458 +#ifndef __APPLE__
   1.459  // struct used for client data from thread_db callback
   1.460  struct thread_db_client_data {
   1.461 -   struct ps_prochandle* ph;
   1.462 -   thread_info_callback callback;
   1.463 +  struct ps_prochandle* ph;
   1.464 +  thread_info_callback callback;
   1.465  };
   1.466  
   1.467  // callback function for libthread_db
   1.468 @@ -314,6 +375,7 @@
   1.469    return true;
   1.470  }
   1.471  
   1.472 +#endif // __APPLE__
   1.473  
   1.474  // get number of threads
   1.475  int get_num_threads(struct ps_prochandle* ph) {
   1.476 @@ -322,18 +384,54 @@
   1.477  
   1.478  // get lwp_id of n'th thread
   1.479  lwpid_t get_lwp_id(struct ps_prochandle* ph, int index) {
   1.480 -   int count = 0;
   1.481 -   thread_info* thr = ph->threads;
   1.482 -   while (thr) {
   1.483 -      if (count == index) {
   1.484 -         return thr->lwp_id;
   1.485 -      }
   1.486 -      count++;
   1.487 -      thr = thr->next;
   1.488 -   }
   1.489 -   return -1;
   1.490 +  int count = 0;
   1.491 +  sa_thread_info* thr = ph->threads;
   1.492 +  while (thr) {
   1.493 +    if (count == index) {
   1.494 +      return thr->lwp_id;
   1.495 +    }
   1.496 +    count++;
   1.497 +    thr = thr->next;
   1.498 +  }
   1.499 +  return 0;
   1.500  }
   1.501  
   1.502 +#ifdef __APPLE__
   1.503 +// set lwp_id of n'th thread
   1.504 +bool set_lwp_id(struct ps_prochandle* ph, int index, lwpid_t lwpid) {
   1.505 +  int count = 0;
   1.506 +  sa_thread_info* thr = ph->threads;
   1.507 +  while (thr) {
   1.508 +    if (count == index) {
   1.509 +      thr->lwp_id = lwpid;
   1.510 +      return true;
   1.511 +    }
   1.512 +    count++;
   1.513 +    thr = thr->next;
   1.514 +  }
   1.515 +  return false;
   1.516 +}
   1.517 +
   1.518 +// get regs of n-th thread, only used in fillThreads the first time called
   1.519 +bool get_nth_lwp_regs(struct ps_prochandle* ph, int index, struct reg* regs) {
   1.520 +  int count = 0;
   1.521 +  sa_thread_info* thr = ph->threads;
   1.522 +  while (thr) {
   1.523 +    if (count == index) {
   1.524 +      break;
   1.525 +    }
   1.526 +    count++;
   1.527 +    thr = thr->next;
   1.528 +  }
   1.529 +  if (thr != NULL) {
   1.530 +    memcpy(regs, &thr->regs, sizeof(struct reg));
   1.531 +    return true;
   1.532 +  }
   1.533 +  return false;
   1.534 +}
   1.535 +
   1.536 +#endif // __APPLE__
   1.537 +
   1.538  // get regs for a given lwp
   1.539  bool get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id, struct reg* regs) {
   1.540    return ph->ops->get_lwp_regs(ph, lwp_id, regs);
   1.541 @@ -341,35 +439,35 @@
   1.542  
   1.543  // get number of shared objects
   1.544  int get_num_libs(struct ps_prochandle* ph) {
   1.545 -   return ph->num_libs;
   1.546 +  return ph->num_libs;
   1.547  }
   1.548  
   1.549  // get name of n'th solib
   1.550  const char* get_lib_name(struct ps_prochandle* ph, int index) {
   1.551 -   int count = 0;
   1.552 -   lib_info* lib = ph->libs;
   1.553 -   while (lib) {
   1.554 -      if (count == index) {
   1.555 -         return lib->name;
   1.556 -      }
   1.557 -      count++;
   1.558 -      lib = lib->next;
   1.559 -   }
   1.560 -   return NULL;
   1.561 +  int count = 0;
   1.562 +  lib_info* lib = ph->libs;
   1.563 +  while (lib) {
   1.564 +    if (count == index) {
   1.565 +      return lib->name;
   1.566 +    }
   1.567 +    count++;
   1.568 +    lib = lib->next;
   1.569 +  }
   1.570 +  return NULL;
   1.571  }
   1.572  
   1.573  // get base address of a lib
   1.574  uintptr_t get_lib_base(struct ps_prochandle* ph, int index) {
   1.575 -   int count = 0;
   1.576 -   lib_info* lib = ph->libs;
   1.577 -   while (lib) {
   1.578 -      if (count == index) {
   1.579 -         return lib->base;
   1.580 -      }
   1.581 -      count++;
   1.582 -      lib = lib->next;
   1.583 -   }
   1.584 -   return (uintptr_t)NULL;
   1.585 +  int count = 0;
   1.586 +  lib_info* lib = ph->libs;
   1.587 +  while (lib) {
   1.588 +    if (count == index) {
   1.589 +      return lib->base;
   1.590 +    }
   1.591 +    count++;
   1.592 +    lib = lib->next;
   1.593 +  }
   1.594 +  return (uintptr_t)NULL;
   1.595  }
   1.596  
   1.597  bool find_lib(struct ps_prochandle* ph, const char *lib_name) {
   1.598 @@ -425,6 +523,7 @@
   1.599    va_end(alist);
   1.600  }
   1.601  
   1.602 +#ifndef __APPLE__
   1.603  // ------------------------------------------------------------------------
   1.604  // Functions below this point are not yet implemented. They are here only
   1.605  // to make the linker happy.
   1.606 @@ -458,3 +557,4 @@
   1.607    print_debug("ps_pcontinue not implemented\n");
   1.608    return PS_OK;
   1.609  }
   1.610 +#endif // __APPLE__

mercurial