< prev index next >

src/hotspot/os/linux/decoder_linux.cpp

Print this page




   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 
  25 #include "jvm.h"



  26 #include "utilities/decoder_elf.hpp"
  27 #include "utilities/elfFile.hpp"
  28 
  29 #include <cxxabi.h>
  30 
  31 bool ElfDecoder::demangle(const char* symbol, char *buf, int buflen) {
  32   int   status;
  33   char* result;
  34   size_t size = (size_t)buflen;
  35 
  36 #ifdef PPC64
  37   // On PPC64 ElfDecoder::decode() may return a dot (.) prefixed name
  38   // (see elfFuncDescTable.hpp for details)
  39   if (symbol && *symbol == '.') symbol += 1;
  40 #endif
  41 
  42   // Don't pass buf to __cxa_demangle. In case of the 'buf' is too small,
  43   // __cxa_demangle will call system "realloc" for additional memory, which
  44   // may use different malloc/realloc mechanism that allocates 'buf'.
  45   if ((result = abi::__cxa_demangle(symbol, NULL, NULL, &status)) != NULL) {
  46     jio_snprintf(buf, buflen, "%s", result);
  47       // call c library's free
  48       ::free(result);


  68   Elf_Ehdr head;
  69   if (fread(&head, sizeof(Elf_Ehdr), 1, file) == 1 &&
  70       is_elf_file(head) &&
  71       fseek(file, head.e_phoff, SEEK_SET) == 0) {
  72 
  73     // Read program header table
  74     Elf_Phdr phdr;
  75     for (int index = 0; index < head.e_phnum; index ++) {
  76       if (fread((void*)&phdr, sizeof(Elf_Phdr), 1, file) != 1) {
  77         result = false;
  78         break;
  79       }
  80       if (phdr.p_type == PT_GNU_STACK) {
  81         result = (phdr.p_flags == (PF_R | PF_W));
  82         break;
  83       }
  84     }
  85   }
  86   fclose(file);
  87   return result;




















































































































































































































































  88 }


   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 
  25 #include "jvm.h"
  26 #include "logging/log.hpp"
  27 #include "memory/allocation.hpp"
  28 #include "memory/resourceArea.hpp"
  29 #include "utilities/decoder_elf.hpp"
  30 #include "utilities/elfFile.hpp"

  31 #include <cxxabi.h>
  32 
  33 bool ElfDecoder::demangle(const char* symbol, char *buf, int buflen) {
  34   int   status;
  35   char* result;
  36   size_t size = (size_t)buflen;
  37 
  38 #ifdef PPC64
  39   // On PPC64 ElfDecoder::decode() may return a dot (.) prefixed name
  40   // (see elfFuncDescTable.hpp for details)
  41   if (symbol && *symbol == '.') symbol += 1;
  42 #endif
  43 
  44   // Don't pass buf to __cxa_demangle. In case of the 'buf' is too small,
  45   // __cxa_demangle will call system "realloc" for additional memory, which
  46   // may use different malloc/realloc mechanism that allocates 'buf'.
  47   if ((result = abi::__cxa_demangle(symbol, NULL, NULL, &status)) != NULL) {
  48     jio_snprintf(buf, buflen, "%s", result);
  49       // call c library's free
  50       ::free(result);


  70   Elf_Ehdr head;
  71   if (fread(&head, sizeof(Elf_Ehdr), 1, file) == 1 &&
  72       is_elf_file(head) &&
  73       fseek(file, head.e_phoff, SEEK_SET) == 0) {
  74 
  75     // Read program header table
  76     Elf_Phdr phdr;
  77     for (int index = 0; index < head.e_phnum; index ++) {
  78       if (fread((void*)&phdr, sizeof(Elf_Phdr), 1, file) != 1) {
  79         result = false;
  80         break;
  81       }
  82       if (phdr.p_type == PT_GNU_STACK) {
  83         result = (phdr.p_flags == (PF_R | PF_W));
  84         break;
  85       }
  86     }
  87   }
  88   fclose(file);
  89   return result;
  90 }
  91 
  92 class LinuxElfDebugInfo : public ElfDebugInfo {
  93 private:
  94   ElfFile* _elf_file;
  95 
  96 public:
  97   LinuxElfDebugInfo(const char* filepath);
  98   ~LinuxElfDebugInfo() {
  99     if (_elf_file != NULL) delete _elf_file;
 100   }
 101 
 102   static LinuxElfDebugInfo* by_debug_link(const char* filepath, const char* debug_info_name, unsigned int crc);
 103   static LinuxElfDebugInfo* by_build_id(const char* filepath, unsigned char* build_id, size_t size);
 104  
 105   bool decode(address addr, char* const buf, size_t buflen, int* offset) {
 106     assert(_elf_file != NULL, "Debug info file not opened");
 107     return _elf_file->decode(addr, buf, buflen, offset);
 108   }
 109 
 110   bool has_error() const {
 111     return NullDecoder::is_error(_elf_file->get_status()); 
 112   }
 113 };
 114 
 115 static const char* debug_link_section_name   = ".gnu_debuglink";
 116 static const char* gnu_build_id_section_name = ".note.gnu.build-id";
 117 
 118 // Directory that contains global debuginfo files.  In theory it
 119 // should be possible to change this, but in a Java environment there
 120 // is no obvious place to put a user interface to do it.  Maybe this
 121 // could be set with an environment variable.
 122 static const char* debug_file_directory = "/usr/lib/debug";
 123 
 124 static unsigned int gnu_debuglink_crc32 (unsigned int crc,
 125                                          unsigned char *buf, size_t len) {
 126   static const unsigned int crc32_table[256] = {
 127       0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
 128       0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
 129       0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
 130       0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
 131       0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
 132       0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
 133       0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
 134       0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
 135       0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
 136       0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
 137       0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
 138       0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
 139       0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
 140       0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
 141       0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
 142       0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
 143       0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
 144       0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
 145       0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
 146       0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
 147       0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
 148       0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
 149       0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
 150       0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
 151       0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
 152       0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
 153       0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
 154       0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
 155       0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
 156       0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
 157       0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
 158       0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
 159       0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
 160       0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
 161       0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
 162       0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
 163       0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
 164       0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
 165       0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
 166       0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
 167       0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
 168       0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
 169       0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
 170       0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
 171       0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
 172       0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
 173       0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
 174       0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
 175       0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
 176       0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
 177       0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
 178       0x2d02ef8d
 179   };
 180 
 181   unsigned char *end;
 182 
 183   crc = ~crc & 0xffffffff;
 184   for (end = buf + len; buf < end; ++buf)
 185     crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
 186   return ~crc & 0xffffffff;
 187 }
 188 
 189 static bool verify_file_crc(const char* filepath, unsigned int crc) {
 190   unsigned int file_crc = 0;
 191   unsigned char buf[4 * K];
 192 
 193   FILE* fd = fopen(filepath, "r");
 194   if (fd == NULL) {
 195     return false;
 196   }
 197   
 198   FileReader reader(fd);
 199   int len;
 200   unsigned char *end;
 201 
 202   while (true) {
 203     len = reader.read_buffer(buf, sizeof(buf));
 204     if (len <= 0) break;
 205     file_crc = gnu_debuglink_crc32(file_crc, buf, len);
 206   }
 207  
 208   fclose(fd);
 209   return (crc == file_crc);
 210 } 
 211 
 212 LinuxElfDebugInfo::LinuxElfDebugInfo(const char* filepath) {
 213   _elf_file = new ElfFile(filepath, false /* load debug info */);
 214 }
 215 
 216 LinuxElfDebugInfo* LinuxElfDebugInfo::by_debug_link(const char* filepath, const char* debug_info_name, unsigned int crc) {
 217   size_t size = strlen(filepath) + strlen(debug_info_name) + 2;
 218 
 219   ResourceMark rm;
 220   char* debuginfo_pathname = NEW_RESOURCE_ARRAY(char, size);
 221   if (debuginfo_pathname == NULL) return NULL;
 222 
 223   strcpy(debuginfo_pathname, filepath);
 224   char *last_slash = strrchr(debuginfo_pathname, '/');
 225   if (last_slash == NULL) {
 226     return NULL;
 227   }
 228 
 229   /* Look in the same directory as the object.  */
 230   strcpy(last_slash + 1, debug_info_name);
 231   
 232   if (!verify_file_crc(debuginfo_pathname, crc)) {
 233     return NULL;
 234   }
 235 
 236   LinuxElfDebugInfo* debug_info = new LinuxElfDebugInfo(debuginfo_pathname);
 237   if (debug_info->has_error()) {
 238     delete debug_info;
 239     return NULL;
 240   }
 241 
 242   log_debug(decoder)("Use %s for decoding symbols in %s", debuginfo_pathname, filepath);
 243   return debug_info;
 244 }
 245 
 246 LinuxElfDebugInfo* LinuxElfDebugInfo::by_build_id(const char* filepath,
 247   unsigned char* build_id, size_t size) {
 248   size_t filename_size = strlen(debug_file_directory) + (sizeof "/.build-id/" - 1) + 1
 249                     + 2 * size + (sizeof ".debug" - 1) + 1;
 250   ResourceMark rm;
 251   char* filename = NEW_RESOURCE_ARRAY(char, size);
 252   if (filename == NULL) return NULL;
 253 
 254   char* s = filename + sprintf(filename, "%s/.build-id/", debug_file_directory);
 255   if (size > 0) {
 256     size --;
 257     s += sprintf(s, "%02x", *build_id++);
 258   }
 259   if (size > 0) *s++ = '/';      
 260   while (size -- > 0) {
 261     s += sprintf(s, "%02x", *build_id++);
 262   }
 263   strcpy (s, ".debug");
 264 
 265   LinuxElfDebugInfo* debug_info = new LinuxElfDebugInfo(filename);
 266   if (debug_info->has_error()) {
 267     delete debug_info;
 268     return NULL;
 269   }
 270 
 271   log_debug(decoder)("Use %s for decoding symbols in %s", filename, filepath);
 272   return debug_info;
 273 }
 274 
 275 ElfDebugInfo* ElfFile::load_debuginfo() {
 276   const char* file_path = filepath();
 277   Elf_Shdr build_id_hdr;
 278   ElfDebugInfo* debuginfo = NULL;
 279 
 280   // try build id first
 281   Elf_Nhdr* nhdr;
 282   if (section_by_name(gnu_build_id_section_name, build_id_hdr) != -1) {
 283     ElfSection build_id_section(_file, build_id_hdr);
 284     nhdr = (Elf_Nhdr*)build_id_section.section_data();
 285     if (nhdr != NULL) {
 286       debuginfo = LinuxElfDebugInfo::by_build_id(file_path, (unsigned char*)(nhdr + 1) + nhdr->n_namesz,
 287                                                  nhdr->n_descsz);
 288     } else {
 289       Elf_Nhdr note_hdr;
 290       MarkedFileReader mfd(fd());
 291       if (mfd.has_mark() &&
 292           mfd.set_position(build_id_section.section_header()->sh_offset) &&
 293           mfd.read((void*)&note_hdr, sizeof(note_hdr))) {
 294         nhdr = &note_hdr;
 295         debuginfo = LinuxElfDebugInfo::by_build_id(file_path, (unsigned char*)(nhdr + 1) + nhdr->n_namesz,
 296                                                    nhdr->n_descsz);
 297       }
 298     }
 299   }
 300   if (debuginfo != NULL) return debuginfo;
 301  
 302   // try debug link
 303   Elf_Shdr debug_link_hdr;
 304   if (section_by_name(debug_link_section_name, debug_link_hdr) != -1) {
 305     ElfSection debug_link_section(_file, debug_link_hdr);
 306     char* debug_info_file = (char* const)debug_link_section.section_data();
 307     unsigned int crc = 0;
 308 
 309     if (debug_info_file != NULL) {
 310       int offset = (strlen(debug_info_file) + 4) >> 2;
 311       crc = ((unsigned int*)debug_link_section.section_data())[offset];
 312       debuginfo = LinuxElfDebugInfo::by_debug_link(file_path, debug_info_file, crc);
 313     } else {
 314       size_t size = debug_link_section.section_header()->sh_size;
 315       ResourceMark rm;
 316       debug_info_file = NEW_RESOURCE_ARRAY(char, size);
 317       if (debug_info_file != NULL) {
 318         MarkedFileReader mfd(fd());
 319         size_t sect_offset = debug_link_section.section_header()->sh_offset;
 320         if (mfd.has_mark() &&
 321             mfd.set_position(sect_offset) &&
 322             mfd.read(debug_info_file, size)) {
 323           int offset = ((strlen(debug_info_file) + 4) >> 2) * sizeof(unsigned int);
 324           if (mfd.set_position(sect_offset + size_t(offset)) &&
 325               mfd.read((void*)&crc, sizeof(crc))) {
 326             debuginfo = LinuxElfDebugInfo::by_debug_link(file_path, debug_info_file, crc);
 327           }
 328         }
 329       }
 330     }
 331   }
 332 
 333   return debuginfo;
 334 }
< prev index next >