1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)var lastModuleError = '';
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)var crashed = false;
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)function domContentLoaded(name, tc, config, width, height) {
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  common.attachDefaultListeners();
101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  common.createNaClModule(name, tc, config, width, height);
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  updateStatus('Page Loaded');
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Indicate success when the NaCl module has loaded.
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)function moduleDidLoad() {
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  updateStatus('LOADED');
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  setTimeout(boom, 2000);
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)function findAddress(addr, map) {
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (map.length < 1) {
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return 'MAP Unavailable';
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (addr < map[0].offs) {
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return 'Invalid Address';
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (var i = 1; i < map.length; i++) {
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (addr < map[i].offs) {
314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      var offs = addr - map[i - 1].offs;
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      var filename = map[i - 1].file;
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Force filename to 50 chars
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (filename) {
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (filename.length > 50) {
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            filename = '...' + filename.substr(filename.length - 47);
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else {
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        filename = 'Unknown';
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      while (filename.length < 50) {
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        filename = ' ' + filename;
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return filename + ' ' + map[i - 1].name + ' + 0x' + offs.toString(16);
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  var last = map.length - 1;
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return filename + ' ' + map[last].name + ' + 0x' + offs.toString(16);
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)function buildTextMap(map) {
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // The expected format of the map file is this:
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // ...
564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // .text     0x00000000000201e0     0x10e0 newlib/Debug/debugging_x86_64.o
574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  //           0x0000000000020280                layer5
584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  //           0x00000000000202e0                layer4
594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  //           0x0000000000020320                layer3
604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  //           0x0000000000020380                layer2
614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  //           0x00000000000203e0                layer1
624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  //           0x0000000000020460                NexeMain
634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // ...
644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  var lines = map.split('\n');
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  var orderedMap = [];
664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  var inTextSection = false;
674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  var fileName = '';
684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (var i = 0; i < lines.length; i++) {
704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    var line = lines[i];
714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (inTextSection) {
734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      //   <hex address>   <symbol name>
744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      var vals = line.trim().split(/\s+/);
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (vals.length != 2) {
764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        inTextSection = false;
774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        continue;
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      var obj = {
814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        offs: parseInt(vals[0], 16),
824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        name: vals[1],
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        file: fileName
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      };
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      orderedMap.push(obj);
874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    } else {
884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // If line starts with .text:
894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (line.lastIndexOf(' .text', 0) === 0) {
904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        inTextSection = true;
914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        // .text    <hex address>   <size>  <filename>
924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        var vals = line.trim().split(/\s+/);
934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        fileName = vals[3];
944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  orderedMap.sort(function(a, b) { return a.offs - b.offs; });
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return orderedMap;
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)function updateStack(traceinfo, map) {
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  map = buildTextMap(map);
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  var text = 'Stack Trace\n';
1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (var i = 0; i < traceinfo.frames.length; i++) {
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    var frame = traceinfo.frames[i];
1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    var addr = findAddress(frame.prog_ctr, map);
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    text += '[' + i.toString(10) + '] ' + addr + '\n';
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  document.getElementById('trace').value = text;
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)function fetchMap(url, traceinfo) {
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  var xmlhttp = new XMLHttpRequest();
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  xmlhttp.open('GET', url, true);
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  xmlhttp.onload = function() {
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    updateStack(traceinfo, this.responseText);
1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  };
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  xmlhttp.traceinfo = traceinfo;
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  xmlhttp.send();
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Handle a message coming from the NaCl module.
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)function handleMessage(message_event) {
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  msg_type = message_event.data.substring(0, 4);
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  msg_data = message_event.data.substring(5, message_event.data.length);
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (msg_type == 'LOG:') {
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    document.getElementById('log').value += msg_data + '\n';
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (msg_type == 'TRC:') {
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    crashed = true;
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    document.getElementById('json').value = msg_data;
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    crash_info = JSON.parse(msg_data);
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    updateStatus('Crash Reported');
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    src = common.naclModule.getAttribute('path');
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    fetchMap(src + '/debugging_' + crash_info['arch'] + '.map', crash_info);
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)function updateStatus(message) {
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  common.updateStatus(message);
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (message)
1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    document.getElementById('log').value += message + '\n';
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)function boom() {
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!crashed) {
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    updateStatus('Send BOOM');
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    common.naclModule.postMessage('BOOM');
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
155