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*)¬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 }
|