src/os/bsd/vm/decoder_machO.cpp

changeset 0
f90c822e73f8
child 6876
710a3c8b516e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/os/bsd/vm/decoder_machO.cpp	Wed Apr 27 01:25:04 2016 +0800
     1.3 @@ -0,0 +1,164 @@
     1.4 +/*
     1.5 + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.23 + * or visit www.oracle.com if you need additional information or have any
    1.24 + * questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +#include "precompiled.hpp"
    1.29 +
    1.30 +#ifdef __APPLE__
    1.31 +#include "decoder_machO.hpp"
    1.32 +
    1.33 +#include <cxxabi.h>
    1.34 +#include <mach-o/loader.h>
    1.35 +#include <mach-o/nlist.h>
    1.36 +
    1.37 +
    1.38 +bool MachODecoder::demangle(const char* symbol, char *buf, int buflen) {
    1.39 +  int   status;
    1.40 +  char* result;
    1.41 +  size_t size = (size_t)buflen;
    1.42 +  // Don't pass buf to __cxa_demangle. In case of the 'buf' is too small,
    1.43 +  // __cxa_demangle will call system "realloc" for additional memory, which
    1.44 +  // may use different malloc/realloc mechanism that allocates 'buf'.
    1.45 +  if ((result = abi::__cxa_demangle(symbol, NULL, NULL, &status)) != NULL) {
    1.46 +    jio_snprintf(buf, buflen, "%s", result);
    1.47 +      // call c library's free
    1.48 +      ::free(result);
    1.49 +      return true;
    1.50 +  }
    1.51 +  return false;
    1.52 +}
    1.53 +
    1.54 +bool MachODecoder::decode(address addr, char *buf,
    1.55 +      int buflen, int *offset, const void *mach_base) {
    1.56 +  struct symtab_command * symt = (struct symtab_command *)
    1.57 +    mach_find_command((struct mach_header_64 *)mach_base, LC_SYMTAB);
    1.58 +  if (symt == NULL) {
    1.59 +    DEBUG_ONLY(tty->print_cr("no symtab in mach file at 0x%lx", p2i(mach_base)));
    1.60 +    return false;
    1.61 +  }
    1.62 +  uint32_t off = symt->symoff;          /* symbol table offset (within this mach file) */
    1.63 +  uint32_t nsyms = symt->nsyms;         /* number of symbol table entries */
    1.64 +  uint32_t stroff = symt->stroff;       /* string table offset */
    1.65 +  uint32_t strsize = symt->strsize;     /* string table size in bytes */
    1.66 +
    1.67 +  // iterate through symbol table trying to match our offset
    1.68 +
    1.69 +  uint32_t addr_relative = (uintptr_t) mach_base - (uintptr_t) addr; // offset we seek in the symtab
    1.70 +  void * symtab_addr = (void*) ((uintptr_t) mach_base + off);
    1.71 +  struct nlist_64 *cur_nlist = (struct nlist_64 *) symtab_addr;
    1.72 +  struct nlist_64 *last_nlist = cur_nlist;  // no size stored in an entry, so keep previously seen nlist
    1.73 +
    1.74 +  int32_t found_strx = 0;
    1.75 +  int32_t found_symval = 0;
    1.76 +
    1.77 +  for (uint32_t i=0; i < nsyms; i++) {
    1.78 +    uint32_t this_value = cur_nlist->n_value;
    1.79 +
    1.80 +    if (addr_relative == this_value) {
    1.81 +      found_strx =  cur_nlist->n_un.n_strx;
    1.82 +      found_symval = this_value;
    1.83 +      break;
    1.84 +    } else if (addr_relative > this_value) {
    1.85 +      // gone past it, use previously seen nlist:
    1.86 +      found_strx = last_nlist->n_un.n_strx;
    1.87 +      found_symval = last_nlist->n_value;
    1.88 +      break;
    1.89 +    }
    1.90 +    last_nlist = cur_nlist;
    1.91 +    cur_nlist = cur_nlist + sizeof(struct nlist_64);
    1.92 +  }
    1.93 +  if (found_strx == 0) {
    1.94 +    return false;
    1.95 +  }
    1.96 +  // write the offset:
    1.97 +  *offset = addr_relative - found_symval;
    1.98 +
    1.99 +  // lookup found_strx in the string table
   1.100 +  char * symname = mach_find_in_stringtable((char*) ((uintptr_t)mach_base + stroff), strsize, found_strx);
   1.101 +  if (symname) {
   1.102 +      strncpy(buf, symname, buflen);
   1.103 +      return true;
   1.104 +  }
   1.105 +  DEBUG_ONLY(tty->print_cr("no string or null string found."));
   1.106 +  return false;
   1.107 +}
   1.108 +
   1.109 +void* MachODecoder::mach_find_command(struct mach_header_64 * mach_base, uint32_t command_wanted) {
   1.110 +  // possibly verify it is a mach_header, use magic number.
   1.111 +  // commands begin immediately after the header.
   1.112 +  struct load_command *pos = (struct load_command *) mach_base + sizeof(struct mach_header_64);
   1.113 +  for (uint32_t i = 0; i < mach_base->ncmds; i++) {
   1.114 +    struct load_command *this_cmd = (struct load_command *) pos;
   1.115 +    if (this_cmd->cmd == command_wanted) {
   1.116 +       return pos;
   1.117 +    }
   1.118 +    int cmdsize = this_cmd->cmdsize;
   1.119 +    pos += cmdsize;
   1.120 +  }
   1.121 +  return NULL;
   1.122 +}
   1.123 +
   1.124 +char* MachODecoder::mach_find_in_stringtable(char *strtab, uint32_t tablesize, int strx_wanted) {
   1.125 +
   1.126 +  if (strx_wanted == 0) {
   1.127 +    return NULL;
   1.128 +  }
   1.129 +  char *strtab_end = strtab + tablesize;
   1.130 +
   1.131 +  // find the first string, skip over the space char
   1.132 +  // (or the four zero bytes we see e.g. in libclient)
   1.133 +  if (*strtab == ' ') {
   1.134 +      strtab++;
   1.135 +      if (*strtab != 0) {
   1.136 +          DEBUG_ONLY(tty->print_cr("string table has leading space but no following zero."));
   1.137 +          return NULL;
   1.138 +      }
   1.139 +      strtab++;
   1.140 +  } else {
   1.141 +      if ((uint32_t) *strtab != 0) {
   1.142 +          DEBUG_ONLY(tty->print_cr("string table without leading space or leading int of zero."));
   1.143 +          return NULL;
   1.144 +      }
   1.145 +      strtab+=4;
   1.146 +  }
   1.147 +  // read the real strings starting at index 1
   1.148 +  int cur_strx = 1;
   1.149 +  while (strtab < strtab_end) {
   1.150 +    if (cur_strx == strx_wanted) {
   1.151 +        return strtab;
   1.152 +    }
   1.153 +    // find start of next string
   1.154 +    while (*strtab != 0) {
   1.155 +        strtab++;
   1.156 +    }
   1.157 +    strtab++; // skip the terminating zero
   1.158 +    cur_strx++;
   1.159 +  }
   1.160 +  DEBUG_ONLY(tty->print_cr("string number %d not found.", strx_wanted));
   1.161 +  return NULL;
   1.162 +}
   1.163 +
   1.164 +
   1.165 +#endif
   1.166 +
   1.167 +

mercurial