| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| var lastModuleError = ''; |
| var crashed = false; |
| |
| function domContentLoaded(name, tc, config, width, height) { |
| common.attachDefaultListeners(); |
| common.createNaClModule(name, tc, config, width, height); |
| |
| updateStatus('Page Loaded'); |
| } |
| |
| // Indicate success when the NaCl module has loaded. |
| function moduleDidLoad() { |
| updateStatus('LOADED'); |
| setTimeout(boom, 2000); |
| } |
| |
| function findAddress(addr, map) { |
| if (map.length < 1) { |
| return 'MAP Unavailable'; |
| } |
| if (addr < map[0].offs) { |
| return 'Invalid Address'; |
| } |
| |
| for (var i = 1; i < map.length; i++) { |
| if (addr < map[i].offs) { |
| var offs = addr - map[i - 1].offs; |
| var filename = map[i - 1].file; |
| |
| // Force filename to 50 chars |
| if (filename) { |
| if (filename.length > 50) { |
| filename = '...' + filename.substr(filename.length - 47); |
| } |
| } else { |
| filename = 'Unknown'; |
| } |
| while (filename.length < 50) { |
| filename = ' ' + filename; |
| } |
| return filename + ' ' + map[i - 1].name + ' + 0x' + offs.toString(16); |
| } |
| } |
| |
| var last = map.length - 1; |
| return filename + ' ' + map[last].name + ' + 0x' + offs.toString(16); |
| } |
| |
| function buildTextMap(map) { |
| // The expected format of the map file is this: |
| // ... |
| // .text 0x00000000000201e0 0x10e0 newlib/Debug/debugging_x86_64.o |
| // 0x0000000000020280 layer5 |
| // 0x00000000000202e0 layer4 |
| // 0x0000000000020320 layer3 |
| // 0x0000000000020380 layer2 |
| // 0x00000000000203e0 layer1 |
| // 0x0000000000020460 NexeMain |
| // ... |
| var lines = map.split('\n'); |
| var orderedMap = []; |
| var inTextSection = false; |
| var fileName = ''; |
| |
| for (var i = 0; i < lines.length; i++) { |
| var line = lines[i]; |
| |
| if (inTextSection) { |
| // <hex address> <symbol name> |
| var vals = line.trim().split(/\s+/); |
| if (vals.length != 2) { |
| inTextSection = false; |
| continue; |
| } |
| |
| var obj = { |
| offs: parseInt(vals[0], 16), |
| name: vals[1], |
| file: fileName |
| }; |
| |
| orderedMap.push(obj); |
| } else { |
| // If line starts with .text: |
| if (line.lastIndexOf(' .text', 0) === 0) { |
| inTextSection = true; |
| // .text <hex address> <size> <filename> |
| var vals = line.trim().split(/\s+/); |
| fileName = vals[3]; |
| } |
| } |
| } |
| |
| orderedMap.sort(function(a, b) { return a.offs - b.offs; }); |
| return orderedMap; |
| } |
| |
| function updateStack(traceinfo, map) { |
| map = buildTextMap(map); |
| var text = 'Stack Trace\n'; |
| for (var i = 0; i < traceinfo.frames.length; i++) { |
| var frame = traceinfo.frames[i]; |
| var addr = findAddress(frame.prog_ctr, map); |
| text += '[' + i.toString(10) + '] ' + addr + '\n'; |
| } |
| document.getElementById('trace').value = text; |
| } |
| |
| function fetchMap(url, traceinfo) { |
| var xmlhttp = new XMLHttpRequest(); |
| xmlhttp.open('GET', url, true); |
| xmlhttp.onload = function() { |
| updateStack(traceinfo, this.responseText); |
| }; |
| xmlhttp.traceinfo = traceinfo; |
| xmlhttp.send(); |
| } |
| |
| // Handle a message coming from the NaCl module. |
| function handleMessage(message_event) { |
| msg_type = message_event.data.substring(0, 4); |
| msg_data = message_event.data.substring(5, message_event.data.length); |
| if (msg_type == 'LOG:') { |
| document.getElementById('log').value += msg_data + '\n'; |
| return; |
| } |
| if (msg_type == 'TRC:') { |
| crashed = true; |
| document.getElementById('json').value = msg_data; |
| crash_info = JSON.parse(msg_data); |
| updateStatus('Crash Reported'); |
| src = common.naclModule.getAttribute('path'); |
| fetchMap(src + '/debugging_' + crash_info['arch'] + '.map', crash_info); |
| return; |
| } |
| } |
| |
| function updateStatus(message) { |
| common.updateStatus(message); |
| |
| if (message) |
| document.getElementById('log').value += message + '\n'; |
| } |
| |
| function boom() { |
| if (!crashed) { |
| updateStatus('Send BOOM'); |
| common.naclModule.postMessage('BOOM'); |
| } |
| } |