1 /* 2 * Copyright (c) 1997, 2018, 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 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); 51 return true; 52 } 53 return false; 54 } 55 56 // Returns true if the elf file is marked NOT to require an executable stack, 57 // or if the file could not be opened. 58 // Returns false if the elf file requires an executable stack, the stack flag 59 // is not set at all, or if the file can not be read. 60 bool ElfFile::specifies_noexecstack(const char* filepath) { 61 if (filepath == NULL) return true; 62 63 FILE* file = fopen(filepath, "r"); 64 if (file == NULL) return true; 65 66 // AARCH64 defaults to noexecstack. All others default to execstack. 67 bool result = AARCH64_ONLY(true) NOT_AARCH64(false); 68 69 // Read file header 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*)¬e_hdr, sizeof(note_hdr))) { 294 nhdr = ¬e_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 }