Anonymous avatar Anonymous committed 1ec32f8

fix compilation on darwin

Comments (0)

Files changed (8)

 static int target_pid;
 static int got_task = 0;
 static task_t targetTask;
-static void *sigtramp = NULL;
+static gimli_addr_t sigtramp = 0;
+
+void gimli_object_file_destroy(gimli_object_file_t obj)
+{
+}
 
 /* Given a path to an image file, open it, find the correct architecture
  * portion for the header, populate rethdr with it and return the file
  * Attempt to load such a beast and process the dwarf info from
  * it.
  */
-static void find_dwarf_dSYM(struct gimli_object_file *of)
+static void find_dwarf_dSYM(gimli_mapped_object_t file)
 {
   char dsym[PATH_MAX];
   char *base;
   int fd;
   gimli_segment_command scmd;
   char sectname[16];
-  gimli_object_file_t *container;
+  gimli_object_file_t container;
   
-  strcpy(basepath, of->objname);
+  strcpy(basepath, file->objname);
   base = basename(basepath);
 
   snprintf(dsym, sizeof(dsym)-1,
-    "%s.dSYM/Contents/Resources/DWARF/%s", of->objname, base);
+    "%s.dSYM/Contents/Resources/DWARF/%s", file->objname, base);
 
   if (debug) {
     fprintf(stderr, "dsym: trying %s\n", dsym);
   if (fd == -1) return;
 
   container = calloc(1, sizeof(*container));
-  container->gobject = of;
+  container->gobject = file;
   container->objname = strdup(dsym);
   container->is_exec = 1;
 
-  of->aux_elf = container;
+  file->aux_elf = container;
 
   /* we're looking for an LC_SEGMENT with a segname of __DWARF */
   cmd_offset = hdr_offset + sizeof(hdr);
           s->name[0] = '.';
           s->addr = sec.addr;
           if (debug) {
-            fprintf(stderr, "%s %s s->addr=%p base_addr=%p\n",
-              of->objname, sectname, s->addr, of->base_addr);
+            fprintf(stderr, "%s %s s->addr=" PTRFMT " base_addr=" PTRFMT "\n",
+              file->objname, sectname, s->addr, file->base_addr);
           }
           s->size = sec.size;
           s->data = malloc(s->size);
           s->container = container;
           pread(fd, s->data, s->size, s->offset);
 
-          gimli_hash_insert(of->sections, s->name, s);
+          gimli_hash_insert(file->sections, s->name, s);
         }
       }
     }
 }
 
 struct gimli_section_data *gimli_get_section_by_name(
-  gimli_object_file_t *elf, const char *name)
+  gimli_object_file_t elf, const char *name)
 {
   struct gimli_section_data *s = NULL;
 
 static int add_symbol(gimli_mach_header *mhdr, void *context,
   const char *strtab, gimli_nlist *nsym)
 {
-  struct gimli_object_file *of = context;
+  gimli_mapped_object_t file = context;
 
   if (nsym->n_value != 0 && nsym->n_type != N_UNDF &&
       strtab[nsym->n_un.n_strx] != '\0') {
         case N_FNAME:
         case N_FUN: /* may have line numbers */
         case N_LSYM:
+        case N_STSYM:
           want_symbol = 1;
           break;
         default:
           want_symbol = 0;
-          //printf("        stab:%x\n", nsym->n_type);
+#if 0
+          printf("%02x %s sect=%d desc=%d val=%" PRIu64 "\n",
+              nsym->n_type,
+              strtab + nsym->n_un.n_strx,
+              nsym->n_sect, nsym->n_desc, nsym->n_value);
+#endif
+
       }
     } else if (nsym->n_type & N_PEXT) {
       want_symbol = 0;
 #endif
     }
     if (want_symbol) {
-      void *value = (void*)(intptr_t)nsym->n_value;
+      gimli_addr_t value = nsym->n_value;
 
       if (mhdr->filetype != MH_EXECUTE) {
-        value += of->base_addr;
+        value += file->base_addr;
       }
       //          printf("sym: %s %p\n", strtab + nsym->n_un.n_strx, (char*)value);
-      gimli_add_symbol(of, strtab + nsym->n_un.n_strx, value, 0);
+      gimli_add_symbol(file, strtab + nsym->n_un.n_strx, value, 0);
 
-      if (sigtramp == NULL &&
+      if (sigtramp == 0 &&
           !strcmp(strtab + nsym->n_un.n_strx, "__sigtramp")) {
         sigtramp = value;
       }
   return 1;
 }
 
-static void read_symtab(struct gimli_object_file *of,
+static void read_symtab(gimli_mapped_object_t file,
   int fd, uint32_t cmd_offset, uint32_t file_off,
   gimli_mach_header *mhdr)
 {
-  walk_symtab(of, add_symbol, fd, cmd_offset, file_off, mhdr);
+  walk_symtab(file, add_symbol, fd, cmd_offset, file_off, mhdr);
 }
 
 /* dyld bootstrap.
  * the nlist() library routine, so we need to manually grub around in dyld
  * to find the dyld symbols we need for discover_maps. */
 struct gimli_dyld_bootstrap {
-  void *info;
-  void *cache;
+  gimli_addr_t info;
+  gimli_addr_t cache;
 };
 
 static int find_dyld_symbols(gimli_mach_header *mhdr, void *context,
 
   if (!dyld->info) {
     if (!strcmp(name, "_dyld_all_image_infos")) {
-      dyld->info = (void*)nsym->n_value;
+      dyld->info = nsym->n_value;
       return 1;
     }
   }
   if (dyld->cache) {
     if (!strcmp(name, "_dyld_shared_region_ranges")) {
-      dyld->cache = (void*)nsym->n_value;
+      dyld->cache = nsym->n_value;
       return 1;
     }
   }
  * target (which should always be true) and read the info out of the target
  * from that address.  This interface is documented in <mach-o/dyld_images.h>
  */
-static void discover_maps(void)
+static void discover_maps(gimli_proc_t proc)
 {
   int i;
   char *symoff = NULL;
     /* adjust the cache information by the same slide that we observe
      * for the difference between the symbol for _dyld_all_image_infos
      * and the value we got from the task_info above */
-    dyld.cache -= (void*)tinfo.all_image_info_addr - dyld.info;
+    dyld.cache -= tinfo.all_image_info_addr - dyld.info;
   }
   dyld.info = tinfo.all_image_info_addr;
 
   if (dyld.info) {
-    if (gimli_read_mem(dyld.info, &infos, sizeof(infos)) != sizeof(infos)) {
-      fprintf(stderr, "DYLD: failed to read _dyld_all_image_infos from %p\n"
+    if (gimli_read_mem(proc, dyld.info, &infos, sizeof(infos)) != sizeof(infos)) {
+      fprintf(stderr, "DYLD: failed to read _dyld_all_image_infos from " PTRFMT "\n"
           "DYLD: no maps, symbols or DWARF info will be available\n",
           dyld.info);
       return;
    * addresses match against the shared cache, then we need to perform
    * an additional computation to obtain the relocated address in the target */
   have_shared_cache = 0;
-  if (dyld.cache && gimli_read_mem(dyld.cache, &shared_cache,
+  if (dyld.cache && gimli_read_mem(proc, dyld.cache, &shared_cache,
         sizeof(shared_cache)) == sizeof(shared_cache)) {
     have_shared_cache = 1;
   }
     struct dyld_image_info im;
     char name[PATH_MAX];
     char rname[PATH_MAX];
-    struct gimli_object_file *of = NULL;
+    gimli_mapped_object_t file = NULL;
     gimli_mach_header mhdr;
     int n, fd;
     char *addr = NULL;
     char sectname[16];
     uint32_t hdr_offset, cmd_offset;
 
-    gimli_read_mem((char*)infos.infoArray + (i * sizeof(im)),
+    gimli_read_mem(proc, (gimli_addr_t)infos.infoArray + (i * sizeof(im)),
         &im, sizeof(im));
 
     if (im.imageLoadAddress == 0) {
     }
 
     memset(name, 0, sizeof(name));
-    gimli_read_mem((void*)im.imageFilePath, name, sizeof(name));
+    gimli_read_mem(proc, (gimli_addr_t)im.imageFilePath, name, sizeof(name));
     if (!realpath(name, rname)) strcpy(rname, name);
 
     if (debug) {
           im.imageLoadAddress, im.imageFilePath, rname);
     }
 
-    of = gimli_add_object(rname, 0);
-    of->elf = calloc(1, sizeof(*of->elf));
-    of->elf->gobject = of;
-    of->elf->is_exec = 1;
-    of->elf->objname = of->objname;
+    file = gimli_add_object(proc, rname, 0);
+    file->elf = calloc(1, sizeof(*file->elf));
+    file->elf->gobject = file;
+    file->elf->is_exec = 1;
+    file->elf->objname = file->objname;
 
     /* now, from the mach header, find each segment and its
      * address range and record the mapping */
-    gimli_read_mem((void*)im.imageLoadAddress, &mhdr, sizeof(mhdr));
+    gimli_read_mem(proc, (gimli_addr_t)im.imageLoadAddress, &mhdr, sizeof(mhdr));
 
     in_shared_cache = 0;
     if (have_shared_cache) {
     for (n = 0; n < hdr.ncmds; n++, cmd_offset += seg.cmdsize) {
       pread(fd, &seg, sizeof(struct load_command), cmd_offset);
       if (seg.cmd == LC_SYMTAB) {
-        read_symtab(of, fd, cmd_offset, hdr_offset, &mhdr);
+        read_symtab(file, fd, cmd_offset, hdr_offset, &mhdr);
         continue;
       }
       if (seg.cmd != GIMLI_LC_SEGMENT) {
         /* ignore zero page mapping */
         continue;
       }
-      if (!strcmp(seg.segname, SEG_TEXT) && of->base_addr == 0) {
+      if (!strcmp(seg.segname, SEG_TEXT) && file->base_addr == 0) {
         /* compute the slide */
-        of->base_addr = (intptr_t)im.imageLoadAddress - seg.vmaddr;
+        file->base_addr = (intptr_t)im.imageLoadAddress - seg.vmaddr;
       }
-      gimli_add_mapping(of->objname,
-        (void*)(intptr_t)(seg.vmaddr + of->base_addr), seg.vmsize, seg.fileoff);
+      gimli_add_mapping(proc, file->objname,
+        (gimli_addr_t)(seg.vmaddr + file->base_addr), seg.vmsize, seg.fileoff);
 
       if (!strcmp(seg.segname, "__TEXT")) {
         /* look for an __eh_frame section */
             s->size = sec.size;
             s->data = malloc(s->size);
             s->offset = sec.offset + hdr_offset;
-            s->container = of->elf;
+            s->container = file->elf;
             pread(fd, s->data, s->size, s->offset);
 
-            gimli_hash_insert(of->sections, s->name, s);
+            gimli_hash_insert(file->sections, s->name, s);
           }
         }
       }
 
     }
-    find_dwarf_dSYM(of);
+    find_dwarf_dSYM(file);
   }
 }
 
   }
 }
 
-int gimli_attach(int pid)
+gimli_err_t gimli_attach(gimli_proc_t proc)
 {
   kern_return_t rc;
   mach_msg_type_number_t n;
-  struct gimli_thread_state *threads;
+  struct gimli_thread_state *thr;
   thread_act_port_array_t threadlist;
   int i;
 
    * See also taskgated(8)
    */
   make_authz_request();
-  target_pid = pid;
-  rc = task_for_pid(mach_task_self(), pid, &targetTask);
+  target_pid = proc->pid;
+  rc = task_for_pid(mach_task_self(), proc->pid, &targetTask);
   if (rc != KERN_SUCCESS) {
     /* this will usually fail unless you call this from the
      * parent of the faulting process, or have root */
 "http://sourceware.org/gdb/wiki/BuildingOnDarwin\n"
 "http://developer.apple.com/library/mac/#documentation/Security/Conceptual/CodeSigningGuide/Procedures/Procedures.html#//apple_ref/doc/uid/TP40005929-CH4-SW1\n"
 , rc);
-    return 0;
+    return GIMLI_ERR_PERM;
   }
   got_task = 1;
   task_suspend(targetTask);
 
-  discover_maps();
+  discover_maps(proc);
 
   rc = task_threads(targetTask, &threadlist, &n);
 
   if (rc == KERN_SUCCESS) {
-    threads = calloc(n, sizeof(*threads));
-
     for (i = 0; i < n; i++) {
 #ifdef __x86_64__
       x86_thread_state64_t ts;
       mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
 
+      thr = gimli_proc_thread_by_lwpid(proc, i, 1);
       memset(&ts, 0, sizeof(ts));
       rc = thread_get_state(threadlist[i], x86_THREAD_STATE64,
           (thread_state_t)&ts, &count);
       if (rc == KERN_SUCCESS) {
-        memcpy(&threads[i].regs, &ts, sizeof(ts));
-        threads[i].pc = (void*)ts.GIMLI_DARWIN_REGNAME(rip);
-        threads[i].fp = (void*)ts.GIMLI_DARWIN_REGNAME(rbp);
-        threads[i].sp = (void*)ts.GIMLI_DARWIN_REGNAME(rsp);
+        memcpy(&thr->regs, &ts, sizeof(ts));
+        thr->pc = (void*)ts.GIMLI_DARWIN_REGNAME(rip);
+        thr->fp = (void*)ts.GIMLI_DARWIN_REGNAME(rbp);
+        thr->sp = (void*)ts.GIMLI_DARWIN_REGNAME(rsp);
       }
 #elif defined(__i386__)
       x86_thread_state32_t ts;
       mach_msg_type_number_t count = x86_THREAD_STATE32_COUNT;
 
+      thr = gimli_proc_thread_by_lwpid(proc, i, 1);
       memset(&ts, 0, sizeof(ts));
       rc = thread_get_state(threadlist[i], x86_THREAD_STATE32,
           (thread_state_t)&ts, &count);
       if (rc == KERN_SUCCESS) {
-        memcpy(&threads[i].regs, &ts, sizeof(ts));
-        threads[i].pc = (void*)ts.GIMLI_DARWIN_REGNAME(eip);
-        threads[i].fp = (void*)ts.GIMLI_DARWIN_REGNAME(ebp);
-        threads[i].sp = (void*)ts.GIMLI_DARWIN_REGNAME(esp);
+        memcpy(&thr->regs, &ts, sizeof(ts));
+        thr->pc = (void*)ts.GIMLI_DARWIN_REGNAME(eip);
+        thr->fp = (void*)ts.GIMLI_DARWIN_REGNAME(ebp);
+        thr->sp = (void*)ts.GIMLI_DARWIN_REGNAME(esp);
       }
 #else
 # error unknown architecture
 #endif
     }
-    gimli_nthreads = n;
-    gimli_threads = threads;
   }
-  return 1;
+  return GIMLI_ERR_OK;
 }
 
 int gimli_init_unwind(struct gimli_unwind_cursor *cur,
 #if defined(__x86_64__)
     _STRUCT_MCONTEXT64 mctx;
     
-    if (gimli_read_mem(cur->st.fp + GIMLI_KERNEL_MCTX64, &mctx,
+    if (gimli_read_mem(cur->proc, (gimli_addr_t)cur->st.fp + GIMLI_KERNEL_MCTX64, &mctx,
         sizeof(mctx)) != sizeof(mctx)) {
       fprintf(stderr, "unable to read old context\n");
       return 0;
   }
 
   if (c.st.fp) {
-    if (gimli_read_mem(c.st.fp, &frame, sizeof(frame)) != sizeof(frame)) {
+    if (gimli_read_mem(cur->proc, (gimli_addr_t)c.st.fp,
+          &frame, sizeof(frame)) != sizeof(frame)) {
       memset(&frame, 0, sizeof(frame));
     }
     if (debug) {
   return 0;
 }
 
-int gimli_detach(void)
+gimli_err_t gimli_detach(gimli_proc_t proc)
 {
   if (got_task) {
     task_resume(targetTask);
   return 0;
 }
 
-int gimli_read_mem(void *src, void *dest, int len)
+int gimli_read_mem(gimli_proc_t proc, gimli_addr_t src, void *dest, int len)
 {
   kern_return_t rc;
   vm_size_t dataCnt = len;
     memset(&cur->si, 0, sizeof(cur->si));
     return 1;
   }
-  if (sigtramp && cur->st.pc >= sigtramp && cur->st.pc <= sigtramp + 0xff) {
+  if (sigtramp && (gimli_addr_t)cur->st.pc >= sigtramp &&
+      (gimli_addr_t)cur->st.pc <= sigtramp + 0xff) {
 #if defined(__x86_64__)
-    if (gimli_read_mem(cur->st.fp + GIMLI_KERNEL_SIGINFO64,
+    if (gimli_read_mem(cur->proc, (gimli_addr_t)cur->st.fp + GIMLI_KERNEL_SIGINFO64,
         &cur->si, sizeof(cur->si)) != sizeof(cur->si)) {
       memset(&cur->si, 0, sizeof(cur->si));
     }
     return 1;
 #elif defined(__i386__)
     struct gimli_kernel_sigframe32 *f = cur->st.fp;
-    if (gimli_read_mem(&f->si, &cur->si, sizeof(cur->si)) != sizeof(cur->si)) {
+    if (gimli_read_mem(cur->proc, (gimli_addr_t)&f->si,
+          &cur->si, sizeof(cur->si)) != sizeof(cur->si)) {
       memset(&cur->si, 0, sizeof(cur->si));
     }
     return 1;
 int gimli_demangle(const char *mangled, char *out, int out_size)
 {
   State state;
+
+#ifdef __MACH__
+  /* skip leading '_' that is present on this platform */
+  mangled++;
+#endif
   InitState(&state, mangled, out, out_size);
   return (ParseMangledName(&state) &&
           state.overflowed == false &&
 
 struct gimli_macho_object {
   char *objname;
-  struct gimli_object_file *gobject;
+  gimli_mapped_object_t gobject;
   int is_exec;
 };
 
   /** for efficient memory accesses, this is a descriptor
    * for /proc/pid/mem. */
   int proc_mem;
-  /** whether mmap works on proc_mem */
-  int proc_mem_supports_mmap;
 #endif
 
   /** list of threads */
   struct gimli_dwarf_die *die, uint64_t attrcode);
 gimli_err_t gimli_proc_service_init(gimli_proc_t proc);
 int gimli_render_siginfo(gimli_proc_t proc, siginfo_t *si, char *buf, size_t bufsize);
+#ifndef __MACH__
 void gimli_user_regs_to_thread(prgregset_t *ur,
   struct gimli_thread_state *thr);
+#endif
 struct gimli_thread_state *gimli_proc_thread_by_lwpid(gimli_proc_t proc, int lwpid, int create);
 int gimli_stack_trace(gimli_proc_t proc, struct gimli_thread_state *thr, struct gimli_unwind_cursor *frames, int nframes);
 int gimli_dwarf_load_frame_var_info(gimli_stack_frame_t frame);
   gimli_object_file_t elf, int *is_stack);
 void gimli_dwarf_load_all_types(gimli_mapped_object_t file);
 
-void gimli_object_file_destroy(struct gimli_elf_ehdr *elf);
+void gimli_object_file_destroy(gimli_object_file_t obj);
 void gimli_hash_diagnose(gimli_hash_t h);
 void gimli_dw_fde_destroy(gimli_mapped_object_t file);
 
 
   *proc = p;
   p->refcnt = 1;
+#ifndef __MACH__
   p->proc_mem = -1;
+#endif
   p->pid = pid;
   STAILQ_INIT(&p->threads);
   p->files = gimli_hash_new(gimli_destroy_mapped_object_hash);
     gimli_addr_t addr, size_t size, gimli_mem_ref_t *refp)
 {
   gimli_mem_ref_t ref;
+  int actual;
 
   /* TODO: maintain a cache of page sized mappings for efficiency */
 
   ref->proc = p;
   gimli_proc_addref(p);
 
-  if (p->proc_mem_supports_mmap == -1) {
-    /* TODO: try mmap, as that would be ideal.
-     * Linux 2.6 doesn't support this.
-     * When we try this for Solaris and FreeBSD, we need to remember
-     * that mmap wants things page aligned and with page offsets, so
-     * we'll need to rebase addr against the page size and then provide
-     * an offset relative to the page, recording the offset in the
-     * map that we're going to return.  We'll also need to record
-     * the actual mmap size that we produced.
-     * Another way to deal with this is to make the page aligned mapping
-     * the relative of this one, and keep the "complex" adjustments
-     * as part of the ->relative handling. */
-
-    /* our "probing" determined that we don't do mmap */
-    p->proc_mem_supports_mmap = 0;
+  ref->base = malloc(size);
+  if (!ref->base) {
+    gimli_mem_ref_delete(ref);
+    return GIMLI_ERR_OOM;
   }
-
-  if (!p->proc_mem_supports_mmap) {
-    /* Poor-mans approach, which is to allocate a buffer and copy
-     * data into it */
-    int actual;
-
-    ref->base = malloc(size);
-    if (!ref->base) {
-      gimli_mem_ref_delete(ref);
-      return GIMLI_ERR_OOM;
-    }
-    ref->map_type = gimli_mem_ref_is_malloc;
-    actual = gimli_read_mem(p, ref->target, ref->base, ref->size);
-    if (actual == 0) {
-      gimli_mem_ref_delete(ref);
-      return GIMLI_ERR_BAD_ADDR;
-    }
-    /* may not have obtained full size */
-    ref->size = actual;
+  ref->map_type = gimli_mem_ref_is_malloc;
+  actual = gimli_read_mem(p, ref->target, ref->base, ref->size);
+  if (actual == 0) {
+    gimli_mem_ref_delete(ref);
+    return GIMLI_ERR_BAD_ADDR;
   }
+  /* may not have obtained full size */
+  ref->size = actual;
 
   *refp = ref;
   return GIMLI_ERR_OK;
 #define _GNU_SOURCE 1
 #endif
 
+#ifndef __MACH__
+
 #include "impl.h"
 
 #ifdef __linux__
   va_end(ap);
 }
 
-
+#endif
 
 /* vim:ts=2:sw=2:et:
  */
     s->size = 8; /* start with something lame */
     for (j = i + 1; j < f->symcount; j++) {
       if (f->symtab[j].addr > s->addr) {
-        f->size = f->symtab[j].addr - s->addr;
+        s->size = f->symtab[j].addr - s->addr;
         break;
       }
     }
     { "_thr_setup", 1 },
     { "_lwp_start", 1 },
 #endif
+#ifdef __MACH__
+    { "_main", 0 },
+    { "__pthread_work_internal_init", 1 },
+#endif
   };
   int i;
   int stop;
     stop = 0;
 
     for (i = 0; i < sizeof(stopsyms)/sizeof(stopsyms[0]); i++) {
-      if (!stopsyms[i].before) continue;
+      if (!stopsyms[i].before || !stopsyms[i].sym) continue;
       if ((gimli_addr_t)cur.st.pc >= stopsyms[i].sym->addr &&
           (gimli_addr_t)cur.st.pc <= stopsyms[i].sym->addr + stopsyms[i].sym->size) {
         stop = 1;
     STAILQ_INSERT_TAIL(&trace->frames, frame, frames);
 
     for (i = 0; i < sizeof(stopsyms)/sizeof(stopsyms[0]); i++) {
-      if (stopsyms[i].before) continue;
+      if (stopsyms[i].before || !stopsyms[i].sym) continue;
       if ((gimli_addr_t)cur.st.pc >= stopsyms[i].sym->addr &&
           (gimli_addr_t)cur.st.pc <= stopsyms[i].sym->addr + stopsyms[i].sym->size) {
         stop = 1;
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.