示例#1
0
static void out_segment(OutputBuffer* buf,
                        WasmSegment* segment,
                        const char* desc) {
  size_t offset = buf->size;
  ensure_output_buffer_capacity(buf, offset + segment->size);
  void* dest = buf->start + offset;
  wasm_copy_segment_data(segment->data, dest, segment->size);
  if (g_verbose)
    dump_memory(buf->start + offset, segment->size, offset, 1, desc);
  buf->size += segment->size;
}
示例#2
0
static WasmResult write_data_to_output_buffer(size_t offset,
                                              const void* data,
                                              size_t size,
                                              void* user_data) {
  WasmMemoryWriter* writer = user_data;
  size_t end = offset + size;
  ensure_output_buffer_capacity(&writer->buf, end);
  memcpy((void*)((size_t)writer->buf.start + offset), data, size);
  if (end > writer->buf.size)
    writer->buf.size = end;
  return WASM_OK;
}
示例#3
0
static size_t out_data(OutputBuffer* buf,
                       size_t offset,
                       const void* src,
                       size_t size,
                       const char* desc) {
  assert(offset <= buf->size);
  ensure_output_buffer_capacity(buf, offset + size);
  memcpy(buf->start + offset, src, size);
  if (g_verbose)
    dump_memory(buf->start + offset, size, offset, 0, desc);
  return offset + size;
}
示例#4
0
static void out_printf(OutputBuffer* buf, const char* format, ...) {
  va_list args;
  va_list args_copy;
  va_start(args, format);
  va_copy(args_copy, args);
  /* + 1 to account for the \0 that will be added automatically by vsnprintf */
  int len = vsnprintf(NULL, 0, format, args) + 1;
  va_end(args);
  ensure_output_buffer_capacity(buf, buf->size + len);
  char* buffer = buf->start + buf->size;
  vsnprintf(buffer, len, format, args_copy);
  va_end(args_copy);
  /* - 1 to remove the trailing \0 that was added by vsnprintf */
  buf->size += len - 1;
}
示例#5
0
static WasmResult move_data_in_output_buffer(size_t dst_offset,
                                             size_t src_offset,
                                             size_t size,
                                             void* user_data) {
  WasmMemoryWriter* writer = user_data;
  size_t src_end = src_offset + size;
  size_t dst_end = dst_offset + size;
  size_t end = src_end > dst_end ? src_end : dst_end;
  ensure_output_buffer_capacity(&writer->buf, end);
  void* dst = (void*)((size_t)writer->buf.start + dst_offset);
  void* src = (void*)((size_t)writer->buf.start + src_offset);
  memmove(dst, src, size);
  if (end > writer->buf.size)
    writer->buf.size = end;
  return WASM_OK;
}
示例#6
0
static void append_nullary_function(Context* ctx,
                                    const char* name,
                                    WasmType result_type,
                                    int16_t num_local_i32,
                                    int16_t num_local_i64,
                                    int16_t num_local_f32,
                                    int16_t num_local_f64) {
  /* We assume that the data for the function in ctx->buf. Add this as a
   new function to ctx->temp_buf. */
  const size_t header_size = FUNC_HEADER_SIZE(0);
  const size_t data_size = ctx->buf.size;
  const size_t name_size = strlen(name) + 1;
  const size_t total_added_size = header_size + data_size + name_size;
  const size_t new_size = ctx->temp_buf.size + total_added_size;
  const size_t old_size = ctx->temp_buf.size;

  if (g_verbose)
    printf("; after %s\n", name);

  ensure_output_buffer_capacity(&ctx->temp_buf, new_size);
  ctx->temp_buf.size = new_size;

  /* We need to add a new function header, data and name to the name table:
   OLD:                 NEW:
   module header        module header
   global headers       global headers
   function headers     function headers
                        NEW function header
   segment headers      segment headers
   function data        function data
                        NEW function data
   segment data         segment data
   name table           name table
                        NEW name
   */

  const uint16_t num_globals = read_u16_at(&ctx->temp_buf, 2);
  const uint16_t num_functions = read_u16_at(&ctx->temp_buf, 4);
  const uint16_t num_segments = read_u16_at(&ctx->temp_buf, 6);

  /* fixup the number of functions */
  out_u16_at(&ctx->temp_buf, 4, read_u16_at(&ctx->temp_buf, 4) + 1,
             "FIXUP num functions");

  /* fixup the global offsets */
  int i;
  uint32_t offset = GLOBAL_HEADERS_OFFSET;
  for (i = 0; i < num_globals; ++i) {
    add_u32_at(&ctx->temp_buf, offset + GLOBAL_HEADER_NAME_OFFSET,
               header_size + data_size, "FIXUP global name offset");
    offset += GLOBAL_HEADER_SIZE;
  }

  /* fixup the function offsets */
  for (i = 0; i < num_functions; ++i) {
    const uint8_t num_args = read_u8_at(&ctx->temp_buf, offset);
    add_u32_at(&ctx->temp_buf, offset + FUNC_HEADER_NAME_OFFSET(num_args),
               header_size + data_size, "FIXUP func name offset");
    add_u32_at(&ctx->temp_buf, offset + FUNC_HEADER_CODE_START_OFFSET(num_args),
               header_size, "FIXUP func code start offset");
    add_u32_at(&ctx->temp_buf, offset + FUNC_HEADER_CODE_END_OFFSET(num_args),
               header_size, "FIXUP func code end offset");
    offset += FUNC_HEADER_SIZE(num_args);
  }
  uint32_t old_func_header_end = offset;

  /* fixup the segment offsets */
  for (i = 0; i < num_segments; ++i) {
    add_u32_at(&ctx->temp_buf, offset + SEGMENT_HEADER_DATA_OFFSET,
               header_size + data_size, "FIXUP segment data offset");
    offset += SEGMENT_HEADER_SIZE;
  }

  /* if there are no functions, then the end of the function data is the end of
   the headers */
  uint32_t old_func_data_end = offset;
  if (num_functions) {
    /* we don't have to keep track of the number of args of the last function
     because it will be subtracted out, so we just use 0 */
    uint32_t last_func_code_end_offset = old_func_header_end -
                                         FUNC_HEADER_SIZE(0) +
                                         FUNC_HEADER_CODE_END_OFFSET(0);
    old_func_data_end =
        read_u32_at(&ctx->temp_buf, last_func_code_end_offset) - header_size;
  }

  /* move everything after the function data down, but leave room for the new
   function name */
  move_data(&ctx->temp_buf, old_func_data_end + header_size + data_size,
            old_func_data_end, old_size - old_func_data_end);

  /* write the new name */
  const uint32_t new_name_offset = new_size - name_size;
  out_data(&ctx->temp_buf, new_name_offset, name, name_size, "func name");

  /* write the new function data */
  const uint32_t new_data_offset = old_func_data_end + header_size;
  out_data(&ctx->temp_buf, new_data_offset, ctx->buf.start, ctx->buf.size,
           "func func data");

  /* move everything between the end of the function headers and the end of the
   function data down */
  move_data(&ctx->temp_buf, old_func_header_end + header_size,
            old_func_header_end, old_func_data_end - old_func_header_end);

  /* write the new header */
  const uint32_t new_header_offset = old_func_header_end;
  if (g_verbose) {
    printf("; clear [%07x,%07x)\n", new_header_offset,
           new_header_offset + FUNC_HEADER_SIZE(0));
  }
  memset(ctx->temp_buf.start + new_header_offset, 0, FUNC_HEADER_SIZE(0));
  out_u8_at(&ctx->temp_buf, new_header_offset + FUNC_HEADER_RESULT_TYPE_OFFSET,
            wasm_type_to_v8_type(result_type), "func result type");
  out_u32_at(&ctx->temp_buf, new_header_offset + FUNC_HEADER_NAME_OFFSET(0),
             new_name_offset, "func name offset");
  out_u32_at(&ctx->temp_buf,
             new_header_offset + FUNC_HEADER_CODE_START_OFFSET(0),
             new_data_offset, "func code start offset");
  out_u32_at(&ctx->temp_buf, new_header_offset + FUNC_HEADER_CODE_END_OFFSET(0),
             new_data_offset + data_size, "func code end offset");
  out_u16_at(&ctx->temp_buf,
             new_header_offset + FUNC_HEADER_NUM_LOCAL_I32_OFFSET(0),
             num_local_i32, "func num local i32");
  out_u16_at(&ctx->temp_buf,
             new_header_offset + FUNC_HEADER_NUM_LOCAL_I64_OFFSET(0),
             num_local_i64, "func num local i64");
  out_u16_at(&ctx->temp_buf,
             new_header_offset + FUNC_HEADER_NUM_LOCAL_F32_OFFSET(0),
             num_local_f32, "func num local f32");
  out_u16_at(&ctx->temp_buf,
             new_header_offset + FUNC_HEADER_NUM_LOCAL_F64_OFFSET(0),
             num_local_f64, "func num local f64");
  out_u8_at(&ctx->temp_buf, new_header_offset + FUNC_HEADER_EXPORTED_OFFSET(0),
            1, "func export");
}