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