tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

wasmDwarfExpressions.js (5914B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
      4 
      5 /* eslint camelcase: 0*/
      6 /* eslint-disable no-inline-comments */
      7 
      8 "use strict";
      9 
     10 class Value {
     11  val;
     12 
     13  constructor(val) {
     14    this.val = val;
     15  }
     16  toString() {
     17    return `${this.val}`;
     18  }
     19 }
     20 
     21 const Int32Formatter = {
     22  fromAddr(addr) {
     23    return `(new DataView(memory0.buffer).getInt32(${addr}, true))`;
     24  },
     25  fromValue(value) {
     26    return `${value.val}`;
     27  },
     28 };
     29 
     30 const Uint32Formatter = {
     31  fromAddr(addr) {
     32    return `(new DataView(memory0.buffer).getUint32(${addr}, true))`;
     33  },
     34  fromValue(value) {
     35    return `(${value.val} >>> 0)`;
     36  },
     37 };
     38 
     39 function createPieceFormatter(bytes) {
     40  let getter;
     41  switch (bytes) {
     42    case 0:
     43    case 1:
     44      getter = "getUint8";
     45      break;
     46    case 2:
     47      getter = "getUint16";
     48      break;
     49    case 3:
     50    case 4:
     51    default:
     52      // FIXME 64-bit
     53      getter = "getUint32";
     54      break;
     55  }
     56  const mask = (1 << (8 * bytes)) - 1;
     57  return {
     58    fromAddr(addr) {
     59      return `(new DataView(memory0.buffer).${getter}(${addr}, true))`;
     60    },
     61    fromValue(value) {
     62      return `((${value.val} & ${mask}) >>> 0)`;
     63    },
     64  };
     65 }
     66 
     67 // eslint-disable-next-line complexity
     68 function toJS(buf, typeFormatter, frame_base = "fp()") {
     69  const readU8 = function () {
     70    return buf[i++];
     71  };
     72  const readS8 = function () {
     73    return (readU8() << 24) >> 24;
     74  };
     75  const readU16 = function () {
     76    const w = buf[i] | (buf[i + 1] << 8);
     77    i += 2;
     78    return w;
     79  };
     80  const readS16 = function () {
     81    return (readU16() << 16) >> 16;
     82  };
     83  const readS32 = function () {
     84    const w =
     85      buf[i] | (buf[i + 1] << 8) | (buf[i + 2] << 16) | (buf[i + 3] << 24);
     86    i += 4;
     87    return w;
     88  };
     89  const readU32 = function () {
     90    return readS32() >>> 0;
     91  };
     92  const readU = function () {
     93    let n = 0,
     94      shift = 0,
     95      b;
     96    while ((b = readU8()) & 0x80) {
     97      n |= (b & 0x7f) << shift;
     98      shift += 7;
     99    }
    100    return n | (b << shift);
    101  };
    102  const readS = function () {
    103    let n = 0,
    104      shift = 0,
    105      b;
    106    while ((b = readU8()) & 0x80) {
    107      n |= (b & 0x7f) << shift;
    108      shift += 7;
    109    }
    110    n |= b << shift;
    111    shift += 7;
    112    return shift > 32 ? (n << (32 - shift)) >> (32 - shift) : n;
    113  };
    114  const popValue = function (formatter) {
    115    const loc = stack.pop();
    116    if (loc instanceof Value) {
    117      return formatter.fromValue(loc);
    118    }
    119    return formatter.fromAddr(loc);
    120  };
    121  let i = 0,
    122    a,
    123    b;
    124  const stack = [frame_base];
    125  while (i < buf.length) {
    126    const code = buf[i++];
    127    switch (code) {
    128      case 0x03 /* DW_OP_addr */:
    129        stack.push(Uint32Formatter.fromAddr(readU32()));
    130        break;
    131      case 0x08 /* DW_OP_const1u 0x08 1 1-byte constant */:
    132        stack.push(readU8());
    133        break;
    134      case 0x09 /* DW_OP_const1s 0x09 1 1-byte constant */:
    135        stack.push(readS8());
    136        break;
    137      case 0x0a /* DW_OP_const2u 0x0a 1 2-byte constant */:
    138        stack.push(readU16());
    139        break;
    140      case 0x0b /* DW_OP_const2s 0x0b 1 2-byte constant */:
    141        stack.push(readS16());
    142        break;
    143      case 0x0c /* DW_OP_const2u 0x0a 1 2-byte constant */:
    144        stack.push(readU32());
    145        break;
    146      case 0x0d /* DW_OP_const2s 0x0b 1 2-byte constant */:
    147        stack.push(readS32());
    148        break;
    149      case 0x10 /* DW_OP_constu 0x10 1 ULEB128 constant */:
    150        stack.push(readU());
    151        break;
    152      case 0x11 /* DW_OP_const2s 0x0b 1 2-byte constant */:
    153        stack.push(readS());
    154        break;
    155 
    156      case 0x1c /* DW_OP_minus */:
    157        b = stack.pop();
    158        a = stack.pop();
    159        stack.push(`${a} - ${b}`);
    160        break;
    161 
    162      case 0x22 /* DW_OP_plus */:
    163        b = stack.pop();
    164        a = stack.pop();
    165        stack.push(`${a} + ${b}`);
    166        break;
    167 
    168      case 0x23 /* DW_OP_plus_uconst */:
    169        b = readU();
    170        a = stack.pop();
    171        stack.push(`${a} + ${b}`);
    172        break;
    173 
    174      case 0x30 /* DW_OP_lit0 */:
    175      case 0x31:
    176      case 0x32:
    177      case 0x33:
    178      case 0x34:
    179      case 0x35:
    180      case 0x36:
    181      case 0x37:
    182      case 0x38:
    183      case 0x39:
    184      case 0x3a:
    185      case 0x3b:
    186      case 0x3c:
    187      case 0x3d:
    188      case 0x3e:
    189      case 0x3f:
    190      case 0x40:
    191      case 0x41:
    192      case 0x42:
    193      case 0x43:
    194      case 0x44:
    195      case 0x45:
    196      case 0x46:
    197      case 0x47:
    198      case 0x48:
    199      case 0x49:
    200      case 0x4a:
    201      case 0x4b:
    202      case 0x4c:
    203      case 0x4d:
    204      case 0x4e:
    205      case 0x4f:
    206        stack.push(`${code - 0x30}`);
    207        break;
    208 
    209      case 0x93 /* DW_OP_piece */: {
    210        a = readU();
    211        const formatter = createPieceFormatter(a);
    212        stack.push(popValue(formatter));
    213        break;
    214      }
    215 
    216      case 0x9f /* DW_OP_stack_value */:
    217        stack.push(new Value(stack.pop()));
    218        break;
    219 
    220      case 0xf6 /* WASM ext (old, FIXME phase out) */:
    221      case 0xed /* WASM ext */:
    222        b = readU();
    223        a = readS();
    224        switch (b) {
    225          case 0:
    226            stack.push(`var${a}`);
    227            break;
    228          case 1:
    229            stack.push(`global${a}`);
    230            break;
    231          default:
    232            stack.push(`ti${b}(${a})`);
    233            break;
    234        }
    235        break;
    236 
    237      default:
    238        // Unknown encoding, baling out
    239        return null;
    240    }
    241  }
    242  // FIXME use real DWARF type information
    243  return popValue(typeFormatter);
    244 }
    245 
    246 function decodeExpr(expr) {
    247  if (expr.includes("//")) {
    248    expr = expr.slice(0, expr.indexOf("//")).trim();
    249  }
    250  const code = new Uint8Array(expr.length >> 1);
    251  for (let i = 0; i < code.length; i++) {
    252    code[i] = parseInt(expr.substr(i << 1, 2), 16);
    253  }
    254  const typeFormatter = Int32Formatter;
    255  return toJS(code, typeFormatter) || `dwarf("${expr}")`;
    256 }
    257 
    258 module.exports = {
    259  decodeExpr,
    260 };