memprof 0.3.2 → 0.3.3
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/bin/memprof +16 -0
- data/ext/elf.c +31 -29
- data/ext/extconf.rb +11 -5
- data/ext/i386.h +2 -2
- data/ext/json.c +53 -0
- data/ext/json.h +48 -0
- data/ext/mach.c +442 -159
- data/ext/memprof.c +565 -459
- data/ext/mmap.h +73 -0
- data/ext/tracer.c +20 -2
- data/ext/tracer.h +14 -1
- data/ext/tracers/fd.c +204 -0
- data/ext/tracers/gc.c +79 -0
- data/ext/tracers/memcache.c +136 -0
- data/ext/tracers/memory.c +202 -0
- data/ext/tracers/mysql.c +82 -0
- data/ext/tracers/objects.c +160 -0
- data/ext/tramp.c +2 -2
- data/ext/util.c +22 -4
- data/ext/util.h +5 -0
- data/ext/x86_gen.c +3 -3
- data/ext/x86_gen.h +0 -13
- data/lib/memprof/tracer.rb +34 -0
- data/memprof.gemspec +1 -1
- data/spec/memprof_spec.rb +12 -4
- data/spec/tracing_spec.rb +135 -0
- metadata +14 -4
- data/ext/tracers/malloc.c +0 -163
data/ext/util.c
CHANGED
@@ -1,10 +1,13 @@
|
|
1
|
+
#include <stdlib.h>
|
2
|
+
#include <time.h>
|
3
|
+
#include <util.h>
|
4
|
+
|
5
|
+
#include <sys/time.h>
|
6
|
+
|
1
7
|
/* This is the CRC function used by GNU. Stripped executables may contain a
|
2
8
|
* section .gnu_debuglink which holds the name of an elf object with debug
|
3
9
|
* information and a checksum.
|
4
|
-
|
5
|
-
#include <stdlib.h>
|
6
|
-
#include <util.h>
|
7
|
-
/* !!!! DO NOT MODIFY THIS FUNCTION !!!!
|
10
|
+
* !!!! DO NOT MODIFY THIS FUNCTION !!!!
|
8
11
|
* TODO create specs for this!
|
9
12
|
*/
|
10
13
|
unsigned long
|
@@ -71,3 +74,18 @@ gnu_debuglink_crc32(unsigned long crc, unsigned char *buf, size_t len)
|
|
71
74
|
crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
|
72
75
|
return ~crc & 0xffffffff;
|
73
76
|
}
|
77
|
+
|
78
|
+
double
|
79
|
+
timeofday()
|
80
|
+
{
|
81
|
+
struct timeval tv;
|
82
|
+
#ifdef CLOCK_MONOTONIC
|
83
|
+
struct timespec tp;
|
84
|
+
|
85
|
+
if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
|
86
|
+
return (double)tp.tv_sec + (double)tp.tv_nsec * 1e-9;
|
87
|
+
}
|
88
|
+
#endif
|
89
|
+
gettimeofday(&tv, NULL);
|
90
|
+
return (double)tv.tv_sec + (double)tv.tv_usec * 1e-6;
|
91
|
+
}
|
data/ext/util.h
CHANGED
@@ -73,4 +73,9 @@ struct memprof_config {
|
|
73
73
|
unsigned long
|
74
74
|
gnu_debuglink_crc32 (unsigned long crc, unsigned char *buf, size_t len);
|
75
75
|
|
76
|
+
/* Use this function for time tracking. It will (interally) try to use an
|
77
|
+
* appropriately granual timing function.
|
78
|
+
*/
|
79
|
+
double
|
80
|
+
timeofday();
|
76
81
|
#endif
|
data/ext/x86_gen.c
CHANGED
@@ -27,14 +27,14 @@ arch_insert_st1_tramp(void *start, void *trampee, void *tramp)
|
|
27
27
|
assert(tramp != NULL);
|
28
28
|
|
29
29
|
int32_t fn_addr = 0;
|
30
|
+
int32_t offset = 0;
|
30
31
|
struct st1_base *check = start;
|
31
32
|
|
32
33
|
if (check->call == 0xe8) {
|
33
34
|
fn_addr = check->displacement;
|
34
35
|
if ((trampee - (void *)(check + 1)) == fn_addr) {
|
35
|
-
|
36
|
-
|
37
|
-
(check->displacement = (tramp - (void *)(check + 1))));
|
36
|
+
offset = tramp - (void *)(check + 1);
|
37
|
+
copy_instructions(&check->displacement, &offset, sizeof(offset));
|
38
38
|
return 0;
|
39
39
|
}
|
40
40
|
}
|
data/ext/x86_gen.h
CHANGED
@@ -75,17 +75,4 @@ copy_instructions(void *dest, void *src, size_t count)
|
|
75
75
|
*/
|
76
76
|
return;
|
77
77
|
}
|
78
|
-
|
79
|
-
/*
|
80
|
-
* WRITE_INSTRUCTIONS - page align start, recalculate len to take into account
|
81
|
-
* alignment, set the read/write permissions and execute the code stmt.
|
82
|
-
*/
|
83
|
-
#define WRITE_INSTRUCTIONS(start, len, stmt) do { \
|
84
|
-
void *aligned_addr = page_align((void *)start); \
|
85
|
-
int count = ((void *)start) - aligned_addr + len; \
|
86
|
-
mprotect(aligned_addr, count, PROT_READ | PROT_WRITE | PROT_EXEC); \
|
87
|
-
stmt; \
|
88
|
-
mprotect(aligned_addr, count, PROT_READ | PROT_EXEC); \
|
89
|
-
} while (0)
|
90
|
-
|
91
78
|
#endif
|
@@ -0,0 +1,34 @@
|
|
1
|
+
begin
|
2
|
+
require File.expand_path('../../memprof', __FILE__)
|
3
|
+
rescue LoadError
|
4
|
+
require File.expand_path('../../../ext/memprof', __FILE__)
|
5
|
+
end
|
6
|
+
|
7
|
+
module Memprof
|
8
|
+
# Middleware for tracing requests
|
9
|
+
#
|
10
|
+
# require 'memprof/tracer'
|
11
|
+
# config.middleware.use(Memprof::Tracer)
|
12
|
+
class Tracer
|
13
|
+
def initialize(app)
|
14
|
+
@app=app
|
15
|
+
end
|
16
|
+
def call(env)
|
17
|
+
Memprof.trace_filename ||= "/tmp/memprof_tracer-#{Process.pid}.json"
|
18
|
+
Memprof.trace_request(env){ @app.call(env) }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Legacy filter for tracing requests on Rails 2.2
|
23
|
+
#
|
24
|
+
# require 'memprof/tracer'
|
25
|
+
# around_filter(Memprof::Filter)
|
26
|
+
module Filter
|
27
|
+
def self.filter(controller)
|
28
|
+
env = controller.request.env
|
29
|
+
info = controller.request.path_parameters
|
30
|
+
Memprof.trace_filename ||= "/tmp/memprof_tracer-#{Process.pid}.json"
|
31
|
+
Memprof.trace_request(env.merge('action_controller.request.path_parameters' => info)){ yield }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/memprof.gemspec
CHANGED
data/spec/memprof_spec.rb
CHANGED
@@ -61,10 +61,10 @@ describe Memprof do
|
|
61
61
|
1.23+1
|
62
62
|
Memprof.dump(filename)
|
63
63
|
|
64
|
-
filedata.should =~ /"file":
|
65
|
-
filedata.should =~ /"line"
|
66
|
-
filedata.should =~ /"type":
|
67
|
-
filedata.should =~ /"data":
|
64
|
+
filedata.should =~ /"file":"#{__FILE__}"/
|
65
|
+
filedata.should =~ /"line":#{__LINE__-4}/
|
66
|
+
filedata.should =~ /"type":"float"/
|
67
|
+
filedata.should =~ /"data":2\.23/
|
68
68
|
end
|
69
69
|
|
70
70
|
should 'raise error when calling ::stats or ::dump without ::start' do
|
@@ -72,6 +72,14 @@ describe Memprof do
|
|
72
72
|
lambda{ Memprof.dump }.should.raise(RuntimeError).message.should =~ /Memprof.start/
|
73
73
|
end
|
74
74
|
|
75
|
+
should 'dump objects created for block' do
|
76
|
+
Memprof.dump(filename) do
|
77
|
+
2.45+1
|
78
|
+
end
|
79
|
+
|
80
|
+
filedata.should =~ /"data":3\.45/
|
81
|
+
end
|
82
|
+
|
75
83
|
should 'dump out the entire heap' do
|
76
84
|
Memprof.stop
|
77
85
|
Memprof.dump_all(filename)
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../ext/memprof"
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bacon'
|
5
|
+
Bacon.summary_on_exit
|
6
|
+
|
7
|
+
require 'tempfile'
|
8
|
+
|
9
|
+
# XXX must require upfront before tracers are installed
|
10
|
+
require 'socket'
|
11
|
+
require 'open-uri'
|
12
|
+
begin; require 'mysql'; rescue LoadError; end
|
13
|
+
begin; require 'memcached'; rescue LoadError; end
|
14
|
+
|
15
|
+
describe 'Memprof tracers' do
|
16
|
+
@tempfile = Tempfile.new('tracing_spec')
|
17
|
+
|
18
|
+
def filename
|
19
|
+
@tempfile.path
|
20
|
+
end
|
21
|
+
|
22
|
+
def filedata
|
23
|
+
File.read(filename)
|
24
|
+
end
|
25
|
+
|
26
|
+
should 'trace i/o for block' do
|
27
|
+
Memprof.trace(filename) do
|
28
|
+
open("http://google.com").read
|
29
|
+
end
|
30
|
+
|
31
|
+
filedata.should =~ /"read":\{"calls":\d+/
|
32
|
+
filedata.should =~ /"write":\{"calls":\d+/
|
33
|
+
filedata.should =~ /"connect":\{"calls":\d+/
|
34
|
+
end
|
35
|
+
|
36
|
+
should 'trace select for block' do
|
37
|
+
Memprof.trace(filename) do
|
38
|
+
select(nil, nil, nil, 0.15)
|
39
|
+
end
|
40
|
+
|
41
|
+
filedata.should =~ /"select":\{"calls":1,"time":0\.1[567]/
|
42
|
+
time = filedata[/"select":\{"calls":\d+,"time":([\d.]+)/, 1].to_f
|
43
|
+
time.should.be.close(0.15, 0.1)
|
44
|
+
end
|
45
|
+
|
46
|
+
should 'trace objects created for block' do
|
47
|
+
Memprof.trace(filename) do
|
48
|
+
10.times{1.1+1.2}
|
49
|
+
end
|
50
|
+
|
51
|
+
filedata.should =~ /"float":10/
|
52
|
+
end
|
53
|
+
|
54
|
+
should 'trace gc runs for block' do
|
55
|
+
Memprof.trace(filename) do
|
56
|
+
10.times{GC.start}
|
57
|
+
end
|
58
|
+
|
59
|
+
filedata.should =~ /"gc":\{"calls":10,"time":[\d.]+/
|
60
|
+
end
|
61
|
+
|
62
|
+
should 'trace memory allocation for block' do
|
63
|
+
Memprof.trace(filename) do
|
64
|
+
10.times{ "abc" << "def" }
|
65
|
+
end
|
66
|
+
|
67
|
+
filedata.should =~ /"malloc":\{"calls":10/
|
68
|
+
filedata.should =~ /"realloc":\{"calls":10/
|
69
|
+
end
|
70
|
+
|
71
|
+
if defined? Mysql
|
72
|
+
begin
|
73
|
+
conn = Mysql.connect('localhost', 'root')
|
74
|
+
|
75
|
+
should 'trace mysql calls for block' do
|
76
|
+
Memprof.trace(filename) do
|
77
|
+
5.times{ conn.query("select sleep(0.05)") }
|
78
|
+
end
|
79
|
+
|
80
|
+
filedata.should =~ /"mysql":\{"queries":5,"time":([\d.]+)/
|
81
|
+
time = filedata[/"mysql":\{"queries":5,"time":([\d.]+)/, 1].to_f
|
82
|
+
time.should.be.close(0.25, 0.1)
|
83
|
+
end
|
84
|
+
rescue Mysql::Error => e
|
85
|
+
raise unless e.message =~ /connect/
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
if defined? Memcached
|
90
|
+
begin
|
91
|
+
conn = Memcached.new("localhost:11211", :show_backtraces => true)
|
92
|
+
conn.stats
|
93
|
+
|
94
|
+
should 'trace memcached calls for block' do
|
95
|
+
Memprof.trace(filename) do
|
96
|
+
conn.delete("memprof") rescue nil
|
97
|
+
conn.get("memprof") rescue nil
|
98
|
+
conn.set("memprof", "is cool")
|
99
|
+
conn.get("memprof")
|
100
|
+
end
|
101
|
+
|
102
|
+
filedata.should =~ /"memcache":\{"get":\{"calls":2,"responses":\{"success":1,"notfound":1/
|
103
|
+
filedata.should =~ /"set":\{"calls":1,"responses":\{"success":1/
|
104
|
+
end
|
105
|
+
rescue Memcached::SomeErrorsWereReported
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe 'Memprof request tracing' do
|
111
|
+
@tempfile = Tempfile.new('tracing_spec')
|
112
|
+
|
113
|
+
def filename
|
114
|
+
@tempfile.path
|
115
|
+
end
|
116
|
+
|
117
|
+
def filedata
|
118
|
+
File.read(filename)
|
119
|
+
end
|
120
|
+
|
121
|
+
should 'trace request env' do
|
122
|
+
env = {"REQUEST_PATH" => "value"}
|
123
|
+
|
124
|
+
Memprof.trace_filename = filename
|
125
|
+
Memprof.trace_filename.should == filename
|
126
|
+
|
127
|
+
Memprof.trace_request(env) do
|
128
|
+
end
|
129
|
+
|
130
|
+
Memprof.trace_filename = nil
|
131
|
+
Memprof.trace_filename.should.be.nil
|
132
|
+
|
133
|
+
filedata.should =~ /"REQUEST_PATH":"value"/
|
134
|
+
end
|
135
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 3
|
8
|
-
-
|
9
|
-
version: 0.3.
|
8
|
+
- 3
|
9
|
+
version: 0.3.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Joe Damato
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2010-04-13 00:00:00 -
|
20
|
+
date: 2010-04-13 00:00:00 -07:00
|
21
21
|
default_executable:
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|
@@ -68,14 +68,22 @@ files:
|
|
68
68
|
- ext/extconf.rb
|
69
69
|
- ext/i386.c
|
70
70
|
- ext/i386.h
|
71
|
+
- ext/json.c
|
72
|
+
- ext/json.h
|
71
73
|
- ext/mach.c
|
72
74
|
- ext/memprof.c
|
75
|
+
- ext/mmap.h
|
73
76
|
- ext/src/libdwarf-20091118.tar.gz
|
74
77
|
- ext/src/libelf-0.8.13.tar.gz
|
75
78
|
- ext/src/yajl-1.0.9.tar.gz
|
76
79
|
- ext/tracer.c
|
77
80
|
- ext/tracer.h
|
78
|
-
- ext/tracers/
|
81
|
+
- ext/tracers/fd.c
|
82
|
+
- ext/tracers/gc.c
|
83
|
+
- ext/tracers/memcache.c
|
84
|
+
- ext/tracers/memory.c
|
85
|
+
- ext/tracers/mysql.c
|
86
|
+
- ext/tracers/objects.c
|
79
87
|
- ext/tramp.c
|
80
88
|
- ext/tramp.h
|
81
89
|
- ext/util.c
|
@@ -86,9 +94,11 @@ files:
|
|
86
94
|
- ext/x86_gen.h
|
87
95
|
- lib/memprof/middleware.rb
|
88
96
|
- lib/memprof/signal.rb
|
97
|
+
- lib/memprof/tracer.rb
|
89
98
|
- memprof.gemspec
|
90
99
|
- spec/memprof_spec.rb
|
91
100
|
- spec/memprof_uploader_spec.rb
|
101
|
+
- spec/tracing_spec.rb
|
92
102
|
has_rdoc: true
|
93
103
|
homepage: http://github.com/ice799/memprof
|
94
104
|
licenses: []
|
data/ext/tracers/malloc.c
DELETED
@@ -1,163 +0,0 @@
|
|
1
|
-
#include <assert.h>
|
2
|
-
#include <stdio.h>
|
3
|
-
#include <stdlib.h>
|
4
|
-
#include <string.h>
|
5
|
-
|
6
|
-
#include "arch.h"
|
7
|
-
#include "bin_api.h"
|
8
|
-
#include "tracer.h"
|
9
|
-
#include "util.h"
|
10
|
-
|
11
|
-
struct memprof_malloc_stats {
|
12
|
-
size_t malloc_bytes_requested;
|
13
|
-
size_t calloc_bytes_requested;
|
14
|
-
size_t realloc_bytes_requested;
|
15
|
-
|
16
|
-
size_t malloc_bytes_actual;
|
17
|
-
size_t calloc_bytes_actual;
|
18
|
-
size_t realloc_bytes_actual;
|
19
|
-
size_t free_bytes_actual;
|
20
|
-
|
21
|
-
size_t malloc_calls;
|
22
|
-
size_t calloc_calls;
|
23
|
-
size_t realloc_calls;
|
24
|
-
size_t free_calls;
|
25
|
-
};
|
26
|
-
|
27
|
-
static struct tracer tracer;
|
28
|
-
static struct memprof_malloc_stats memprof_malloc_stats;
|
29
|
-
static void *(*orig_malloc)(size_t), *(*orig_realloc)(void *, size_t),
|
30
|
-
*(*orig_calloc)(size_t, size_t), (*orig_free)(void *);
|
31
|
-
static size_t (*malloc_usable_size)(void *ptr);
|
32
|
-
|
33
|
-
static void *
|
34
|
-
malloc_tramp(size_t size)
|
35
|
-
{
|
36
|
-
void *ret = NULL;
|
37
|
-
memprof_malloc_stats.malloc_bytes_requested += size;
|
38
|
-
memprof_malloc_stats.malloc_calls++;
|
39
|
-
ret = orig_malloc(size);
|
40
|
-
memprof_malloc_stats.malloc_bytes_actual += malloc_usable_size(ret);
|
41
|
-
return ret;
|
42
|
-
}
|
43
|
-
|
44
|
-
static void *
|
45
|
-
calloc_tramp(size_t nmemb, size_t size)
|
46
|
-
{
|
47
|
-
void *ret = NULL;
|
48
|
-
memprof_malloc_stats.calloc_bytes_requested += (nmemb * size);
|
49
|
-
memprof_malloc_stats.calloc_calls++;
|
50
|
-
ret = (*orig_calloc)(nmemb, size);
|
51
|
-
memprof_malloc_stats.calloc_bytes_actual += malloc_usable_size(ret);
|
52
|
-
return ret;
|
53
|
-
}
|
54
|
-
|
55
|
-
static void *
|
56
|
-
realloc_tramp(void *ptr, size_t size)
|
57
|
-
{
|
58
|
-
/* TODO need to check malloc_usable_size of before/after i guess? */
|
59
|
-
void *ret = NULL;
|
60
|
-
memprof_malloc_stats.realloc_bytes_requested += size;
|
61
|
-
memprof_malloc_stats.realloc_calls++;
|
62
|
-
ret = orig_realloc(ptr, size);
|
63
|
-
memprof_malloc_stats.realloc_bytes_actual += malloc_usable_size(ptr);
|
64
|
-
return ret;
|
65
|
-
}
|
66
|
-
|
67
|
-
static void
|
68
|
-
free_tramp(void *ptr)
|
69
|
-
{
|
70
|
-
memprof_malloc_stats.free_bytes_actual += malloc_usable_size(ptr);
|
71
|
-
memprof_malloc_stats.free_calls++;
|
72
|
-
orig_free(ptr);
|
73
|
-
}
|
74
|
-
|
75
|
-
static void
|
76
|
-
malloc_trace_stop()
|
77
|
-
{
|
78
|
-
struct tramp_st2_entry tmp;
|
79
|
-
|
80
|
-
tmp.addr = orig_malloc;
|
81
|
-
bin_update_image("malloc", &tmp, NULL);
|
82
|
-
|
83
|
-
tmp.addr = orig_realloc;
|
84
|
-
bin_update_image("realloc", &tmp, NULL);
|
85
|
-
|
86
|
-
if (orig_calloc) {
|
87
|
-
tmp.addr = orig_calloc;
|
88
|
-
bin_update_image("calloc", &tmp, NULL);
|
89
|
-
}
|
90
|
-
|
91
|
-
tmp.addr = orig_free;
|
92
|
-
bin_update_image("free", &tmp, NULL);
|
93
|
-
}
|
94
|
-
|
95
|
-
static void
|
96
|
-
malloc_trace_reset()
|
97
|
-
{
|
98
|
-
memset(&memprof_malloc_stats, 0, sizeof(memprof_malloc_stats));
|
99
|
-
}
|
100
|
-
|
101
|
-
static void
|
102
|
-
malloc_trace_dump()
|
103
|
-
{
|
104
|
-
fprintf(stderr, "================ Requested ====================\n");
|
105
|
-
fprintf(stderr, "Malloced: %zd, Realloced: %zd, Calloced: %zd\n",
|
106
|
-
memprof_malloc_stats.malloc_bytes_requested, memprof_malloc_stats.realloc_bytes_requested,
|
107
|
-
memprof_malloc_stats.calloc_bytes_requested);
|
108
|
-
fprintf(stderr, "================ Actual ====================\n");
|
109
|
-
fprintf(stderr, "Malloced: %zd, Realloced: %zd, Calloced: %zd, Freed: %zd\n",
|
110
|
-
memprof_malloc_stats.malloc_bytes_actual, memprof_malloc_stats.realloc_bytes_actual,
|
111
|
-
memprof_malloc_stats.calloc_bytes_actual, memprof_malloc_stats.free_bytes_actual);
|
112
|
-
fprintf(stderr, "================ Call count ====================\n");
|
113
|
-
fprintf(stderr, "Calls to malloc: %zd, realloc: %zd, calloc: %zd, free: %zd\n",
|
114
|
-
memprof_malloc_stats.malloc_calls,
|
115
|
-
memprof_malloc_stats.realloc_calls,
|
116
|
-
memprof_malloc_stats.calloc_calls,
|
117
|
-
memprof_malloc_stats.free_calls);
|
118
|
-
}
|
119
|
-
|
120
|
-
static void
|
121
|
-
malloc_trace_start()
|
122
|
-
{
|
123
|
-
struct tramp_st2_entry tmp;
|
124
|
-
|
125
|
-
if (!malloc_usable_size) {
|
126
|
-
if ((malloc_usable_size =
|
127
|
-
bin_find_symbol("MallocExtension_GetAllocatedSize", NULL, 1)) == NULL) {
|
128
|
-
malloc_usable_size = bin_find_symbol("malloc_usable_size", NULL, 1);
|
129
|
-
dbg_printf("tcmalloc was not found...\n");
|
130
|
-
}
|
131
|
-
assert(malloc_usable_size != NULL);
|
132
|
-
dbg_printf("malloc_usable_size: %p\n", malloc_usable_size);
|
133
|
-
}
|
134
|
-
|
135
|
-
tmp.addr = malloc_tramp;
|
136
|
-
bin_update_image("malloc", &tmp, (void **)(&orig_malloc));
|
137
|
-
assert(orig_malloc != NULL);
|
138
|
-
dbg_printf("orig_malloc: %p\n", orig_malloc);
|
139
|
-
|
140
|
-
tmp.addr = realloc_tramp;
|
141
|
-
bin_update_image("realloc", &tmp,(void **)(&orig_realloc));
|
142
|
-
dbg_printf("orig_realloc: %p\n", orig_realloc);
|
143
|
-
|
144
|
-
tmp.addr = calloc_tramp;
|
145
|
-
bin_update_image("calloc", &tmp, (void **)(&orig_calloc));
|
146
|
-
dbg_printf("orig_calloc: %p\n", orig_calloc);
|
147
|
-
|
148
|
-
tmp.addr = free_tramp;
|
149
|
-
bin_update_image("free", &tmp, (void **)(&orig_free));
|
150
|
-
assert(orig_free != NULL);
|
151
|
-
dbg_printf("orig_free: %p\n", orig_free);
|
152
|
-
}
|
153
|
-
|
154
|
-
void install_malloc_tracer()
|
155
|
-
{
|
156
|
-
tracer.start = malloc_trace_start;
|
157
|
-
tracer.stop = malloc_trace_stop;
|
158
|
-
tracer.reset = malloc_trace_reset;
|
159
|
-
tracer.dump = malloc_trace_dump;
|
160
|
-
tracer.id = strdup("malloc_tracer");
|
161
|
-
|
162
|
-
trace_insert(&tracer);
|
163
|
-
}
|