Example #1
0
static void
malloc_trace_start()
{
  static int inserted = 0;

  if (!inserted)
    inserted = 1;
  else
    return;

  if (!malloc_usable_size) {
    malloc_usable_size = bin_find_symbol("MallocExtension_GetAllocatedSize", NULL, 1);
    if (!malloc_usable_size) {
      dbg_printf("tcmalloc was not found...\n");
      malloc_usable_size = bin_find_symbol("malloc_usable_size", NULL, 1);
    }
    if (!malloc_usable_size) {
      dbg_printf("malloc_usable_size was not found...\n");
      malloc_usable_size = bin_find_symbol("malloc_size", NULL, 1);
    }
    assert(malloc_usable_size != NULL);
    dbg_printf("malloc_usable_size: %p\n", malloc_usable_size);
  }

  insert_tramp("malloc", malloc_tramp);
  insert_tramp("realloc", realloc_tramp);
  insert_tramp("calloc", calloc_tramp);
  insert_tramp("free", free_tramp);
}
Example #2
0
static void
mysql_trace_start() {
  static int inserted = 0;

  if (!inserted)
    inserted = 1;
  else
    return;

  orig_real_query = bin_find_symbol("mysql_real_query", NULL, 1);
  if (orig_real_query)
    insert_tramp("mysql_real_query", real_query_tramp);

  orig_send_query = bin_find_symbol("mysql_send_query", NULL, 1);
  if (orig_send_query)
    insert_tramp("mysql_send_query", send_query_tramp);
}
Example #3
0
static void init_cpyprof(void)
{
    if (!Original_PyEval_EvalFrameEx) {
        Original_PyEval_EvalFrameEx = PyEval_EvalFrameEx;
        // monkey-patch PyEval_EvalFrameEx
        init_memprof_config_base();
        bin_init();
        create_tramp_table();
        size_t tramp_size;
        tramp_start = insert_tramp("PyEval_EvalFrameEx",
                                   &cpyprof_PyEval_EvalFrameEx,
                                   &tramp_size);
        tramp_end = tramp_start + tramp_size;
    }
    if (!Original_code_dealloc) {
        Original_code_dealloc = PyCode_Type.tp_dealloc;
        PyCode_Type.tp_dealloc = &cpyprof_code_dealloc;
    }
}
Example #4
0
static VALUE
memprof_dump(int argc, VALUE *argv, VALUE self)
{
  VALUE str;
  FILE *out = NULL;

  if (!track_objs)
    rb_raise(rb_eRuntimeError, "object tracking disabled, call Memprof.start first");

  rb_scan_args(argc, argv, "01", &str);

  if (RTEST(str)) {
    out = fopen(StringValueCStr(str), "w");
    if (!out)
      rb_raise(rb_eArgError, "unable to open output file");
  }

  yajl_gen_config conf = { .beautify = 1, .indentString = "  " };
  yajl_gen gen = yajl_gen_alloc2((yajl_print_t)&json_print, &conf, NULL, (void*)out);

  track_objs = 0;

  yajl_gen_array_open(gen);
  st_foreach(objs, objs_each_dump, (st_data_t)gen);
  yajl_gen_array_close(gen);
  yajl_gen_free(gen);

  if (out)
    fclose(out);

  track_objs = 1;

  return Qnil;
}

static VALUE
memprof_dump_all(int argc, VALUE *argv, VALUE self)
{
  char *heaps = *(char**)bin_find_symbol("heaps",0);
  int heaps_used = *(int*)bin_find_symbol("heaps_used",0);

#ifndef sizeof__RVALUE
  size_t sizeof__RVALUE = bin_type_size("RVALUE");
#endif
#ifndef sizeof__heaps_slot
  size_t sizeof__heaps_slot = bin_type_size("heaps_slot");
#endif
#ifndef offset__heaps_slot__limit
  int offset__heaps_slot__limit = bin_type_member_offset("heaps_slot", "limit");
#endif
#ifndef offset__heaps_slot__slot
  int offset__heaps_slot__slot = bin_type_member_offset("heaps_slot", "slot");
#endif

  char *p, *pend;
  int i, limit;

  if (sizeof__RVALUE == 0 || sizeof__heaps_slot == 0)
    rb_raise(eUnsupported, "could not find internal heap");

  VALUE str;
  FILE *out = NULL;

  rb_scan_args(argc, argv, "01", &str);

  if (RTEST(str)) {
    out = fopen(StringValueCStr(str), "w");
    if (!out)
      rb_raise(rb_eArgError, "unable to open output file");
  }

  yajl_gen_config conf = { .beautify = 0, .indentString = "  " };
  yajl_gen gen = yajl_gen_alloc2((yajl_print_t)&json_print, &conf, NULL, (void*)out);

  track_objs = 0;

  //yajl_gen_array_open(gen);

  for (i=0; i < heaps_used; i++) {
    p = *(char**)(heaps + (i * sizeof__heaps_slot) + offset__heaps_slot__slot);
    limit = *(int*)(heaps + (i * sizeof__heaps_slot) + offset__heaps_slot__limit);
    pend = p + (sizeof__RVALUE * limit);

    while (p < pend) {
      if (RBASIC(p)->flags) {
        obj_dump((VALUE)p, gen);
        // XXX ugh
        yajl_gen_clear(gen);
        yajl_gen_free(gen);
        gen = yajl_gen_alloc2((yajl_print_t)&json_print, &conf, NULL, (void*)out);
        while(fputc('\n', out ? out : stdout) == EOF);
      }

      p += sizeof__RVALUE;
    }
  }

  //yajl_gen_array_close(gen);
  yajl_gen_clear(gen);
  yajl_gen_free(gen);

  if (out)
    fclose(out);

  track_objs = 1;

  return Qnil;
}

void
Init_memprof()
{
  VALUE memprof = rb_define_module("Memprof");
  eUnsupported = rb_define_class_under(memprof, "Unsupported", rb_eStandardError);
  rb_define_singleton_method(memprof, "start", memprof_start, 0);
  rb_define_singleton_method(memprof, "stop", memprof_stop, 0);
  rb_define_singleton_method(memprof, "stats", memprof_stats, -1);
  rb_define_singleton_method(memprof, "stats!", memprof_stats_bang, -1);
  rb_define_singleton_method(memprof, "track", memprof_track, -1);
  rb_define_singleton_method(memprof, "dump", memprof_dump, -1);
  rb_define_singleton_method(memprof, "dump_all", memprof_dump_all, -1);

  pagesize = getpagesize();
  objs = st_init_numtable();
  bin_init();
  create_tramp_table();

  gc_hook = Data_Wrap_Struct(rb_cObject, sourcefile_marker, NULL, NULL);
  rb_global_variable(&gc_hook);
  ptr_to_rb_mark_table_add_filename = bin_find_symbol("rb_mark_table_add_filename", NULL);

  rb_classname = bin_find_symbol("classname", 0);
  rb_add_freelist = bin_find_symbol("add_freelist", 0);

  insert_tramp("rb_newobj", newobj_tramp);
  insert_tramp("add_freelist", freelist_tramp);

  if (getenv("MEMPROF"))
    track_objs = 1;

  return;
}