memprof 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/ext/elf.c CHANGED
@@ -2,10 +2,11 @@
2
2
 
3
3
  #include "bin_api.h"
4
4
 
5
- #include <stdio.h>
6
5
  #include <fcntl.h>
7
6
  #include <gelf.h>
8
7
  #include <link.h>
8
+ #include <stdio.h>
9
+ #include <string.h>
9
10
  #include <sysexits.h>
10
11
  #include <unistd.h>
11
12
 
@@ -18,7 +19,14 @@ static Elf_Data *symtab_data = NULL;
18
19
  void *
19
20
  bin_allocate_page()
20
21
  {
21
- return mmap(NULL, pagesize, PROT_WRITE|PROT_READ|PROT_EXEC, MAP_ANON|MAP_PRIVATE|MAP_32BIT, -1, 0);
22
+ void * ret = NULL;
23
+ ret = mmap(NULL, pagesize, PROT_WRITE|PROT_READ|PROT_EXEC, MAP_ANON|MAP_PRIVATE|MAP_32BIT, -1, 0);
24
+
25
+ if (ret != MAP_FAILED) {
26
+ memset(ret, 0x90, pagesize);
27
+ }
28
+
29
+ return ret;
22
30
  }
23
31
 
24
32
  void
@@ -32,15 +40,17 @@ bin_find_symbol(char *sym, size_t *size)
32
40
  {
33
41
  char *name = NULL;
34
42
 
35
- /*now print the symbols*/
36
43
  ElfW(Sym) *esym = (ElfW(Sym)*) symtab_data->d_buf;
37
44
  ElfW(Sym) *lastsym = (ElfW(Sym)*) ((char*) symtab_data->d_buf + symtab_data->d_size);
38
- /* now loop through the symbol table and print it*/
45
+
39
46
  for (; esym < lastsym; esym++){
47
+ /* ignore weak/numeric/empty symbols */
40
48
  if ((esym->st_value == 0) ||
41
49
  (ELF32_ST_BIND(esym->st_info)== STB_WEAK) ||
42
50
  (ELF32_ST_BIND(esym->st_info)== STB_NUM))
43
51
  continue;
52
+
53
+
44
54
  name = elf_strptr(elf, symtab_shdr.sh_link, (size_t)esym->st_name);
45
55
  if (strcmp(name, sym) == 0) {
46
56
  if (size) {
@@ -78,7 +88,7 @@ bin_init()
78
88
  if (elf_kind(elf) != ELF_K_ELF)
79
89
  errx(EX_DATAERR, "%s is not an ELF object.", filename);
80
90
 
81
- if (elf_getshstrndx(elf, &shstrndx) == 0)
91
+ if (elf_getshdrstrndx(elf, &shstrndx) == -1)
82
92
  errx(EX_SOFTWARE, "getshstrndx() failed: %s.",
83
93
  elf_errmsg(-1));
84
94
 
data/ext/extconf.rb CHANGED
@@ -7,12 +7,66 @@ if RUBY_VERSION >= "1.9"
7
7
  end
8
8
 
9
9
  require 'mkmf'
10
+ require 'fileutils'
11
+
12
+ CWD = File.expand_path(File.dirname(__FILE__))
13
+
14
+ def sys(cmd)
15
+ puts " -- #{cmd}"
16
+ unless ret = xsystem(cmd)
17
+ raise "#{cmd} failed, please report to http://github.com/ice799/memprof/issues with pastie.org link to #{CWD}/mkmf.log"
18
+ end
19
+ ret
20
+ end
10
21
 
11
22
  def add_define(name)
12
23
  $defs.push("-D#{name}")
13
24
  end
14
25
 
15
- if (add_define("HAVE_ELF") if have_library('elf', 'gelf_getshdr')) ||
16
- (add_define("HAVE_MACH") if have_header('mach-o/dyld.h'))
26
+ ###
27
+ # libelf
28
+
29
+ if RUBY_PLATFORM =~ /linux/
30
+ libelf = File.basename('libelf-0.8.13.tar.gz')
31
+ dir = File.basename(libelf, '.tar.gz')
32
+
33
+ unless File.exists?("#{CWD}/dst/lib/libelf_ext.so")
34
+ puts "(I'm about to compile libelf.. this will definitely take a while)"
35
+
36
+ Dir.chdir('src') do
37
+ FileUtils.rm_rf(dir) if File.exists?(dir)
38
+
39
+ sys("tar zxvf #{libelf}")
40
+ Dir.chdir(dir) do
41
+ sys("./configure --prefix=#{CWD}/dst")
42
+ sys("make")
43
+ sys("make install")
44
+ end
45
+ end
46
+
47
+ Dir.chdir('dst/lib') do
48
+ FileUtils.ln_s 'libelf.so', 'libelf_ext.so'
49
+ end
50
+ end
51
+
52
+ $LIBPATH.unshift "#{CWD}/dst/lib"
53
+ $INCFLAGS[0,0] = "-I#{CWD}/dst/include "
54
+
55
+ unless have_library('elf', 'gelf_getshdr')
56
+ raise 'libelf build failed'
57
+ end
58
+
59
+ is_elf = true
60
+ add_define 'HAVE_ELF'
61
+ end
62
+
63
+ if have_header('mach-o/dyld')
64
+ is_macho = true
65
+ add_define 'HAVE_MACH'
66
+ end
67
+
68
+ if is_elf or is_macho
17
69
  create_makefile('memprof')
70
+ else
71
+ raise 'unsupported platform'
18
72
  end
data/ext/mach.c CHANGED
@@ -3,6 +3,7 @@
3
3
  #include "bin_api.h"
4
4
 
5
5
  #include <limits.h>
6
+ #include <string.h>
6
7
  #include <sysexits.h>
7
8
  #include <sys/mman.h>
8
9
 
@@ -43,11 +44,13 @@ bin_allocate_page()
43
44
  size_t i = 0;
44
45
 
45
46
  for (i = pagesize; i < INT_MAX - pagesize; i += pagesize) {
46
- ret = mmap((void*)(NULL + i), 2*pagesize, PROT_WRITE|PROT_READ|PROT_EXEC,
47
+ ret = mmap((void*)(NULL + i), pagesize, PROT_WRITE|PROT_READ|PROT_EXEC,
47
48
  MAP_ANON|MAP_PRIVATE, -1, 0);
48
49
 
49
- if (tramp_table != MAP_FAILED)
50
+ if (tramp_table != MAP_FAILED) {
51
+ memset(tramp_table, 0x90, pagesize);
50
52
  return ret;
53
+ }
51
54
  }
52
55
  return NULL;
53
56
  }
data/ext/memprof.c CHANGED
@@ -102,6 +102,7 @@ objs_free(st_data_t key, st_data_t record, st_data_t arg)
102
102
  {
103
103
  struct obj_track *tracker = (struct obj_track *)record;
104
104
  free(tracker->source);
105
+ free(tracker);
105
106
  return ST_DELETE;
106
107
  }
107
108
 
@@ -150,7 +151,7 @@ struct results {
150
151
  };
151
152
 
152
153
  static int
153
- memprof_do_dump(st_data_t key, st_data_t record, st_data_t arg)
154
+ objs_to_array(st_data_t key, st_data_t record, st_data_t arg)
154
155
  {
155
156
  struct results *res = (struct results *)arg;
156
157
  unsigned long count = (unsigned long)record;
@@ -200,6 +201,9 @@ memprof_stats(int argc, VALUE *argv, VALUE self)
200
201
  VALUE str;
201
202
  FILE *out = NULL;
202
203
 
204
+ if (!track_objs)
205
+ rb_raise(rb_eRuntimeError, "object tracking disabled, call Memprof.start first");
206
+
203
207
  rb_scan_args(argc, argv, "01", &str);
204
208
 
205
209
  if (RTEST(str)) {
@@ -216,10 +220,11 @@ memprof_stats(int argc, VALUE *argv, VALUE self)
216
220
  res.num_entries = 0;
217
221
  res.entries = malloc(sizeof(char*) * tmp_table->num_entries);
218
222
 
219
- st_foreach(tmp_table, memprof_do_dump, (st_data_t)&res);
223
+ st_foreach(tmp_table, objs_to_array, (st_data_t)&res);
220
224
  st_free_table(tmp_table);
221
225
 
222
226
  qsort(res.entries, res.num_entries, sizeof(char*), &memprof_strcmp);
227
+
223
228
  for (i=0; i < res.num_entries; i++) {
224
229
  fprintf(out ? out : stderr, "%s\n", res.entries[i]);
225
230
  free(res.entries[i]);
@@ -254,7 +259,8 @@ memprof_track(int argc, VALUE *argv, VALUE self)
254
259
  static void
255
260
  create_tramp_table()
256
261
  {
257
- int i, j = 0;
262
+ int i = 0;
263
+ void *region = NULL;
258
264
 
259
265
  struct tramp_tbl_entry ent = {
260
266
  .rbx_save = {'\x53'}, // push rbx
@@ -291,22 +297,20 @@ create_tramp_table()
291
297
  .jmp_displacement = 0,
292
298
  };
293
299
 
294
- if ((tramp_table = bin_allocate_page()) == MAP_FAILED) {
295
- fprintf(stderr, "Failed to allocate memory for stage 1 trampoline.\n");
300
+ if ((region = bin_allocate_page()) == MAP_FAILED) {
301
+ fprintf(stderr, "Failed to allocate memory for stage 1 trampolines.\n");
296
302
  return;
297
303
  }
298
304
 
299
- if ((inline_tramp_table = bin_allocate_page()) == MAP_FAILED) {
300
- fprintf(stderr, "Faied to allocate memory for the stage 1 inline trampoline.\n");
301
- return;
302
- }
305
+ tramp_table = region;
306
+ inline_tramp_table = region + pagesize/2;
303
307
 
304
- for (j = 0; j < pagesize/sizeof(struct tramp_tbl_entry); j ++ ) {
305
- memcpy(tramp_table + j, &ent, sizeof(struct tramp_tbl_entry));
308
+ for (i = 0; i < (pagesize/2)/sizeof(struct tramp_tbl_entry); i++) {
309
+ memcpy(tramp_table + i, &ent, sizeof(struct tramp_tbl_entry));
306
310
  }
307
311
 
308
- for (j = 0; j < pagesize/sizeof(struct inline_tramp_tbl_entry); j++) {
309
- memcpy(inline_tramp_table + j, &inline_ent, sizeof(struct inline_tramp_tbl_entry));
312
+ for (i = 0; i < (pagesize/2)/sizeof(struct inline_tramp_tbl_entry); i++) {
313
+ memcpy(inline_tramp_table + i, &inline_ent, sizeof(struct inline_tramp_tbl_entry));
310
314
  }
311
315
  }
312
316
 
Binary file
data/memprof.gemspec CHANGED
@@ -1,13 +1,13 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'memprof'
3
- s.version = '0.1.2'
4
- s.date = '2009-12-10'
3
+ s.version = '0.1.3'
4
+ s.date = '2009-12-14'
5
5
  s.summary = 'Ruby Memory Profiler'
6
6
  s.description = "Ruby memory profiler similar to bleak_house, but without patches to the Ruby VM"
7
7
  s.email = "ice799@gmail.com"
8
8
  s.homepage = "http://github.com/ice799/memprof"
9
9
  s.has_rdoc = false
10
- s.authors = ["Joe Damato"]
10
+ s.authors = ["Joe Damato", "Aman Gupta", "Jake Douglas"]
11
11
  s.extensions = "ext/extconf.rb"
12
12
  s.files = %w[
13
13
  .gitignore
@@ -17,6 +17,7 @@ spec = Gem::Specification.new do |s|
17
17
  ext/extconf.rb
18
18
  ext/mach.c
19
19
  ext/memprof.c
20
+ ext/src/libelf-0.8.13.tar.gz
20
21
  memprof.gemspec
21
22
  ]
22
23
  end
metadata CHANGED
@@ -1,15 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: memprof
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe Damato
8
+ - Aman Gupta
9
+ - Jake Douglas
8
10
  autorequire:
9
11
  bindir: bin
10
12
  cert_chain: []
11
13
 
12
- date: 2009-12-10 00:00:00 -08:00
14
+ date: 2009-12-14 00:00:00 -08:00
13
15
  default_executable:
14
16
  dependencies: []
15
17
 
@@ -29,6 +31,7 @@ files:
29
31
  - ext/extconf.rb
30
32
  - ext/mach.c
31
33
  - ext/memprof.c
34
+ - ext/src/libelf-0.8.13.tar.gz
32
35
  - memprof.gemspec
33
36
  has_rdoc: true
34
37
  homepage: http://github.com/ice799/memprof