#!/usr/bin/env python3 import argparse import io import json import linecache import os import struct import subprocess import sys import tempfile import textwrap def i32(buf, off): return struct.unpack_from(" vtable + vlen: return None off = u16(buf, offpos) return None if off == 0 else table + off def vector_info(buf, field_pos): vec = field_pos + u32(buf, field_pos) return vec, u32(buf, vec), vec + 4 def indirect_table(buf, elem_pos): return elem_pos + u32(buf, elem_pos) def read_flatbuffer_string(buf, field_pos): start = field_pos + u32(buf, field_pos) size = u32(buf, start) return bytes(buf[start + 4 : start + 4 + size]).decode() MODEL_SOURCE = textwrap.dedent( """ import torch class M(torch.nn.Module): def forward(self, x: torch.Tensor, y: torch.Tensor): z = [x, y] return z[0] + z[1] """ ) def build_model_blob(): import torch fake_filename = "/tmp/pytorch_mobile_list_construct_probe_model.py" linecache.cache[fake_filename] = ( len(MODEL_SOURCE), None, MODEL_SOURCE.splitlines(True), fake_filename, ) ns = {} exec(compile(MODEL_SOURCE, fake_filename, "exec"), ns) model = torch.jit.script(ns["M"]()) return model._save_to_buffer_for_lite_interpreter(_use_flatbuffer=True) def locate_target(blob): root = u32(blob, 0) ivalues_field = table_field(blob, root, 4) if ivalues_field is None: raise RuntimeError("missing ivalues table") _, ivalues_len, ivalues_base = vector_info(blob, ivalues_field) for i in range(ivalues_len): ivalue = indirect_table(blob, ivalues_base + 4 * i) val_type_field = table_field(blob, ivalue, 0) if val_type_field is None or u8(blob, val_type_field) != 16: continue fn_tbl = indirect_table(blob, table_field(blob, ivalue, 1)) function_name = read_flatbuffer_string(blob, table_field(blob, fn_tbl, 0)) instructions_field = table_field(blob, fn_tbl, 1) if instructions_field is None: continue _, instructions_len, instructions_base = vector_info(blob, instructions_field) for j in range(instructions_len): inst_off = instructions_base + 8 * j if u8(blob, inst_off) != 26: # LIST_CONSTRUCT continue return { "function_ivalue_index": i, "function_name": function_name, "instruction_index": j, "instruction_offset": inst_off, "x_field_offset": inst_off + 4, "n_field_offset": inst_off + 2, "original_x": i32(blob, inst_off + 4), "original_n": u16(blob, inst_off + 2), } raise RuntimeError("failed to locate LIST_CONSTRUCT instruction") def mutate_list_construct_n(blob, new_n): target = locate_target(blob) out = bytearray(blob) struct.pack_into("