memprof 0.2.7 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +15 -6
- data/ext/bin_api.h +1 -9
- data/ext/elf.c +398 -81
- data/ext/extconf.rb +2 -0
- data/ext/mach.c +97 -86
- data/ext/memprof.c +267 -167
- data/ext/tramp.c +143 -0
- data/ext/tramp.h +23 -0
- data/ext/util.c +72 -0
- data/ext/util.h +40 -0
- data/ext/x86_64.c +2 -2
- data/lib/memprof/usr2.rb +1 -0
- data/memprof.gemspec +3 -3
- metadata +17 -5
data/ext/tramp.c
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
#ifndef _GNU_SOURCE
|
4
|
+
#define _GNU_SOURCE
|
5
|
+
#endif
|
6
|
+
|
7
|
+
#include <sysexits.h>
|
8
|
+
#include <sys/mman.h>
|
9
|
+
#include <err.h>
|
10
|
+
#include <assert.h>
|
11
|
+
|
12
|
+
#include "arch.h"
|
13
|
+
#include "bin_api.h"
|
14
|
+
#include "util.h"
|
15
|
+
|
16
|
+
#define FREELIST_INLINES 3
|
17
|
+
|
18
|
+
/*
|
19
|
+
* trampoline specific stuff
|
20
|
+
*/
|
21
|
+
static struct tramp_st2_entry *tramp_table;
|
22
|
+
static size_t tramp_size;
|
23
|
+
|
24
|
+
/*
|
25
|
+
* inline trampoline specific stuff
|
26
|
+
*/
|
27
|
+
static size_t inline_tramp_size;
|
28
|
+
static struct inline_tramp_st2_entry *inline_tramp_table;
|
29
|
+
|
30
|
+
extern struct memprof_config memprof_config;
|
31
|
+
|
32
|
+
void
|
33
|
+
create_tramp_table()
|
34
|
+
{
|
35
|
+
size_t i;
|
36
|
+
void *region, *ent, *inline_ent;
|
37
|
+
size_t tramp_sz = 0, inline_tramp_sz = 0;
|
38
|
+
|
39
|
+
ent = arch_get_st2_tramp(&tramp_sz);
|
40
|
+
inline_ent = arch_get_inline_st2_tramp(&inline_tramp_sz);
|
41
|
+
assert(ent && inline_ent);
|
42
|
+
|
43
|
+
region = bin_allocate_page();
|
44
|
+
if (region == MAP_FAILED)
|
45
|
+
errx(EX_SOFTWARE, "Failed to allocate memory for stage 1 trampolines.");
|
46
|
+
|
47
|
+
tramp_table = region;
|
48
|
+
inline_tramp_table = region + memprof_config.pagesize / 2;
|
49
|
+
|
50
|
+
for (i = 0; i < (memprof_config.pagesize / 2) / tramp_sz; i++) {
|
51
|
+
memcpy(tramp_table + i, ent, tramp_sz);
|
52
|
+
}
|
53
|
+
|
54
|
+
for (i = 0; i < (memprof_config.pagesize / 2) / inline_tramp_sz; i++) {
|
55
|
+
memcpy(inline_tramp_table + i, inline_ent, inline_tramp_sz);
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
static void
|
60
|
+
hook_freelist(int entry, void *tramp)
|
61
|
+
{
|
62
|
+
size_t sizes[FREELIST_INLINES];
|
63
|
+
void *freelist_inliners[FREELIST_INLINES];
|
64
|
+
void *freelist = NULL;
|
65
|
+
unsigned char *byte = NULL;
|
66
|
+
int i = 0, tramps_completed = 0;
|
67
|
+
|
68
|
+
assert(memprof_config.gc_sweep != NULL);
|
69
|
+
assert(memprof_config.finalize_list != NULL);
|
70
|
+
assert(memprof_config.rb_gc_force_recycle != NULL);
|
71
|
+
assert(memprof_config.freelist != NULL);
|
72
|
+
assert(memprof_config.gc_sweep_size > 0);
|
73
|
+
assert(memprof_config.finalize_list_size > 0);
|
74
|
+
assert(memprof_config.rb_gc_force_recycle_size > 0);
|
75
|
+
|
76
|
+
freelist_inliners[0] = memprof_config.gc_sweep;
|
77
|
+
freelist_inliners[1] = memprof_config.finalize_list;
|
78
|
+
freelist_inliners[2] = memprof_config.rb_gc_force_recycle;
|
79
|
+
sizes[0] = memprof_config.gc_sweep_size;
|
80
|
+
sizes[1] = memprof_config.finalize_list_size;
|
81
|
+
sizes[2] = memprof_config.rb_gc_force_recycle_size;
|
82
|
+
|
83
|
+
freelist = memprof_config.freelist;
|
84
|
+
|
85
|
+
/* start the search for places to insert the inline tramp */
|
86
|
+
byte = freelist_inliners[i];
|
87
|
+
|
88
|
+
while (i < FREELIST_INLINES) {
|
89
|
+
if (arch_insert_inline_st2_tramp(byte, freelist, tramp,
|
90
|
+
&inline_tramp_table[entry]) == 0) {
|
91
|
+
/* insert occurred, so increment internal counters for the tramp table */
|
92
|
+
entry++;
|
93
|
+
inline_tramp_size++;
|
94
|
+
|
95
|
+
/*
|
96
|
+
* add_freelist() only gets inlined *ONCE* into any of the 3 functions
|
97
|
+
* that we're scanning, so move on to the next 'inliner' after we
|
98
|
+
* tramp the first instruction we find. REE's gc_sweep has 2 calls,
|
99
|
+
* but this gets optimized into a single inlining and a jmp to it.
|
100
|
+
* older patchlevels of 1.8.7 don't have an add_freelist(), but the
|
101
|
+
* instruction should be the same.
|
102
|
+
*/
|
103
|
+
tramps_completed++;
|
104
|
+
i++;
|
105
|
+
byte = freelist_inliners[i];
|
106
|
+
continue;
|
107
|
+
}
|
108
|
+
|
109
|
+
/* if we've looked at all the bytes in this function... */
|
110
|
+
if (((void *)byte - freelist_inliners[i]) >= sizes[i]) {
|
111
|
+
/* move on to the next function */
|
112
|
+
i++;
|
113
|
+
byte = freelist_inliners[i];
|
114
|
+
}
|
115
|
+
byte++;
|
116
|
+
}
|
117
|
+
|
118
|
+
if (tramps_completed != 3)
|
119
|
+
errx(EX_SOFTWARE, "Inline add_freelist tramp insertion failed! "
|
120
|
+
"Only inserted %d tramps.", tramps_completed);
|
121
|
+
}
|
122
|
+
|
123
|
+
void
|
124
|
+
insert_tramp(const char *trampee, void *tramp)
|
125
|
+
{
|
126
|
+
void *trampee_addr = bin_find_symbol(trampee, NULL);
|
127
|
+
int inline_ent = inline_tramp_size;
|
128
|
+
|
129
|
+
if (trampee_addr == NULL) {
|
130
|
+
if (strcmp("add_freelist", trampee) == 0) {
|
131
|
+
/* XXX super hack */
|
132
|
+
inline_tramp_size++;
|
133
|
+
hook_freelist(inline_ent, tramp /* freelist_tramp() */);
|
134
|
+
} else {
|
135
|
+
errx(EX_SOFTWARE, "Failed to locate required symbol %s", trampee);
|
136
|
+
}
|
137
|
+
} else {
|
138
|
+
tramp_table[tramp_size].addr = tramp;
|
139
|
+
if (bin_update_image(trampee, &tramp_table[tramp_size]) != 0)
|
140
|
+
errx(EX_SOFTWARE, "Failed to insert tramp for %s", trampee);
|
141
|
+
tramp_size++;
|
142
|
+
}
|
143
|
+
}
|
data/ext/tramp.h
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#if !defined(TRAMP__)
|
2
|
+
#define TRAMP__
|
3
|
+
|
4
|
+
/*
|
5
|
+
* create_tramp_table - create the trampoline tables.
|
6
|
+
*/
|
7
|
+
void
|
8
|
+
create_tramp_table();
|
9
|
+
|
10
|
+
/*
|
11
|
+
* insert_tramp - insert a trampoline.
|
12
|
+
*
|
13
|
+
* Given:
|
14
|
+
* - trampee: function in which we want to install the trampoline.
|
15
|
+
* - tramp: pointer to the function to be called from the trampoline.
|
16
|
+
*
|
17
|
+
* This function is responsible for installing the requested trampoline
|
18
|
+
* at the location of "trampee". This results in tramp() being called
|
19
|
+
* whenever trampee() is executed.
|
20
|
+
*/
|
21
|
+
void
|
22
|
+
insert_tramp(const char *trampee, void *tramp);
|
23
|
+
#endif
|
data/ext/util.c
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
/* This is the CRC function used by GNU. Stripped executables may contain a
|
2
|
+
* section .gnu_debuglink which holds the name of an elf object with debug
|
3
|
+
* information and a checksum.
|
4
|
+
*/
|
5
|
+
#include <stdlib.h>
|
6
|
+
/* !!!! DO NOT MODIFY THIS FUNCTION !!!!
|
7
|
+
* TODO create specs for this!
|
8
|
+
*/
|
9
|
+
unsigned long
|
10
|
+
gnu_debuglink_crc32(unsigned long crc, unsigned char *buf, size_t len)
|
11
|
+
{
|
12
|
+
static const unsigned int crc32_table[256] = {
|
13
|
+
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
|
14
|
+
0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
|
15
|
+
0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
|
16
|
+
0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
|
17
|
+
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
|
18
|
+
0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
19
|
+
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
|
20
|
+
0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
21
|
+
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
|
22
|
+
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
|
23
|
+
0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
|
24
|
+
0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
25
|
+
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
|
26
|
+
0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
|
27
|
+
0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
|
28
|
+
0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
29
|
+
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
|
30
|
+
0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
31
|
+
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
|
32
|
+
0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
|
33
|
+
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
|
34
|
+
0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
|
35
|
+
0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
|
36
|
+
0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
37
|
+
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
|
38
|
+
0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
|
39
|
+
0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
|
40
|
+
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
41
|
+
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
|
42
|
+
0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
43
|
+
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
|
44
|
+
0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
45
|
+
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
|
46
|
+
0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
|
47
|
+
0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
|
48
|
+
0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
49
|
+
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
|
50
|
+
0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
|
51
|
+
0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
|
52
|
+
0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
53
|
+
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
|
54
|
+
0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
55
|
+
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
|
56
|
+
0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
|
57
|
+
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
|
58
|
+
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
|
59
|
+
0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
|
60
|
+
0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
61
|
+
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
|
62
|
+
0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
|
63
|
+
0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
|
64
|
+
0x2d02ef8d
|
65
|
+
};
|
66
|
+
unsigned char *end;
|
67
|
+
|
68
|
+
crc = ~crc & 0xffffffff;
|
69
|
+
for (end = buf + len; buf < end; ++buf)
|
70
|
+
crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
|
71
|
+
return ~crc & 0xffffffff;
|
72
|
+
}
|
data/ext/util.h
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#if !defined(__util_h__)
|
2
|
+
#define __util_h__
|
3
|
+
|
4
|
+
#if defined(_MEMPROF_DEBUG)
|
5
|
+
#define dbg_printf(...) fprintf(stderr, __VA_ARGS__)
|
6
|
+
#else
|
7
|
+
#define dbg_printf(...)
|
8
|
+
#endif
|
9
|
+
|
10
|
+
#define ASSERT_ON_COMPILE(pred) \
|
11
|
+
switch(0){case 0:case pred:;}
|
12
|
+
|
13
|
+
struct memprof_config {
|
14
|
+
void *gc_sweep;
|
15
|
+
size_t gc_sweep_size;
|
16
|
+
void *finalize_list;
|
17
|
+
size_t finalize_list_size;
|
18
|
+
void *rb_gc_force_recycle;
|
19
|
+
size_t rb_gc_force_recycle_size;
|
20
|
+
void *freelist;
|
21
|
+
void *classname;
|
22
|
+
void *add_freelist;
|
23
|
+
void *rb_mark_table_add_filename;
|
24
|
+
void *heaps;
|
25
|
+
void *heaps_used;
|
26
|
+
size_t sizeof_RVALUE;
|
27
|
+
size_t sizeof_heaps_slot;
|
28
|
+
int offset_heaps_slot_limit;
|
29
|
+
int offset_heaps_slot_slot;
|
30
|
+
size_t pagesize;
|
31
|
+
};
|
32
|
+
|
33
|
+
/* This is the CRC function used by GNU. Stripped executables may contain a
|
34
|
+
* section .gnu_debuglink which holds the name of an elf object with debug
|
35
|
+
* information and a checksum.
|
36
|
+
*/
|
37
|
+
unsigned long
|
38
|
+
gnu_debuglink_crc32 (unsigned long crc, unsigned char *buf, size_t len);
|
39
|
+
|
40
|
+
#endif
|
data/ext/x86_64.c
CHANGED
@@ -6,6 +6,7 @@
|
|
6
6
|
|
7
7
|
#include "arch.h"
|
8
8
|
#include "x86_gen.h"
|
9
|
+
#include "util.h"
|
9
10
|
|
10
11
|
/*
|
11
12
|
* inline_st1_tramp - inline stage 1 trampoline
|
@@ -124,8 +125,7 @@ arch_insert_inline_st2_tramp(void *addr, void *marker, void *trampoline, void *t
|
|
124
125
|
struct inline_st1_base *base = addr;
|
125
126
|
struct inline_tramp_st2_entry *entry = table_entry;
|
126
127
|
|
127
|
-
|
128
|
-
assert(sizeof(struct inline_st1_base) ==
|
128
|
+
ASSERT_ON_COMPILE(sizeof(struct inline_st1_base) ==
|
129
129
|
sizeof(struct inline_st1_tramp));
|
130
130
|
|
131
131
|
if (!arch_check_ins(base))
|
data/lib/memprof/usr2.rb
CHANGED
data/memprof.gemspec
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
spec = Gem::Specification.new do |s|
|
2
2
|
s.name = 'memprof'
|
3
|
-
s.version = '0.2.
|
4
|
-
s.date = '2010-03-
|
3
|
+
s.version = '0.2.9'
|
4
|
+
s.date = '2010-03-15'
|
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.homepage = "http://github.com/ice799/memprof"
|
8
8
|
s.has_rdoc = false
|
9
|
-
s.authors = ["Joe Damato", "Aman Gupta", "Jake Douglas"]
|
9
|
+
s.authors = ["Joe Damato", "Aman Gupta", "Jake Douglas", "Rob Benson"]
|
10
10
|
s.email = ["joe@memprof.com", "aman@memprof.com", "jake@memprof.com"]
|
11
11
|
s.extensions = "ext/extconf.rb"
|
12
12
|
s.files = `git ls-files`.split
|
metadata
CHANGED
@@ -1,17 +1,23 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: memprof
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 9
|
9
|
+
version: 0.2.9
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Joe Damato
|
8
13
|
- Aman Gupta
|
9
14
|
- Jake Douglas
|
15
|
+
- Rob Benson
|
10
16
|
autorequire:
|
11
17
|
bindir: bin
|
12
18
|
cert_chain: []
|
13
19
|
|
14
|
-
date: 2010-03-
|
20
|
+
date: 2010-03-15 00:00:00 -07:00
|
15
21
|
default_executable:
|
16
22
|
dependencies: []
|
17
23
|
|
@@ -41,6 +47,10 @@ files:
|
|
41
47
|
- ext/src/libdwarf-20091118.tar.gz
|
42
48
|
- ext/src/libelf-0.8.13.tar.gz
|
43
49
|
- ext/src/yajl-1.0.9.tar.gz
|
50
|
+
- ext/tramp.c
|
51
|
+
- ext/tramp.h
|
52
|
+
- ext/util.c
|
53
|
+
- ext/util.h
|
44
54
|
- ext/x86_64.c
|
45
55
|
- ext/x86_64.h
|
46
56
|
- ext/x86_gen.h
|
@@ -61,18 +71,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
61
71
|
requirements:
|
62
72
|
- - ">="
|
63
73
|
- !ruby/object:Gem::Version
|
74
|
+
segments:
|
75
|
+
- 0
|
64
76
|
version: "0"
|
65
|
-
version:
|
66
77
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
78
|
requirements:
|
68
79
|
- - ">="
|
69
80
|
- !ruby/object:Gem::Version
|
81
|
+
segments:
|
82
|
+
- 0
|
70
83
|
version: "0"
|
71
|
-
version:
|
72
84
|
requirements: []
|
73
85
|
|
74
86
|
rubyforge_project:
|
75
|
-
rubygems_version: 1.3.
|
87
|
+
rubygems_version: 1.3.6
|
76
88
|
signing_key:
|
77
89
|
specification_version: 3
|
78
90
|
summary: Ruby Memory Profiler
|