-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuiltin-object.c
More file actions
132 lines (110 loc) · 3.7 KB
/
builtin-object.c
File metadata and controls
132 lines (110 loc) · 3.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
Copyright (C) 2013
Baptiste Lepers <baptiste.lepers@gmail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2, as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "parse.h"
#include "builtin-object.h"
#define SPACES 5
static int uid, nb_tids;
static int total_calls;
static rbtree tids, timeline, top;
void obj_set(int _uid) {
uid = _uid;
}
void obj_init() {
tids = rbtree_create();
timeline = rbtree_create();
top = rbtree_create();
assert(uid != 0);
}
int callchain_printed = 0;
void print_callchain(struct s* s) {
if(callchain_printed)
return;
callchain_printed = 1;
struct symbol *ss = sample_to_variable2(s);
int i;
printf("Object was allocated from the following path:\n");
printf("\t%s [%p]\n", ss->object_name, (void*)s->rip);
for(i = 0; i < ss->callchain_size; i++) {
printf("\t%*.*s%s [%p]\n", (i+1)*2,(i+1)*2, "", sample_to_callchain(s, ss, i)->function_name, (void*)ss->callchain[i]);
}
printf("Object is here: %lx-%lx\n",
(long unsigned) ss->ip,
(long unsigned) &(((char*)ss->ip)[ss->size]));
}
void obj_parse(struct s* s) {
struct symbol *ob2 = sample_to_variable2(s);
if(!ob2 || ob2->uid != uid)
return;
print_callchain(s);
struct s *ss = malloc(sizeof(*ss));
memcpy(ss, s, sizeof(*ss));
rbtree_insert(timeline, (void*)(long)s->rdt, ss, pointer_cmp);
int *value = rbtree_lookup(tids, (void*)(long)get_tid(s), int_cmp);
if(!value) {
value = calloc(2, sizeof(*value));
value[0] = nb_tids;
nb_tids++;
rbtree_insert(tids, (void*)(long)get_tid(s), value, int_cmp);
}
value[1] = value[1] + 1;
}
int print_timeline(void *key, void *value) {
int tid = get_tid(value);
int *v = rbtree_lookup(tids, (void*)(long)tid, int_cmp);
assert(v);
char *func = get_function(value)->function_name;
int i;
for(i = 0; i < v[0]; i++) {
printf("%*.*s", SPACES, SPACES, "");
}
if(is_load(value))
printf(" x ");
else
printf(" * ");
for(i = v[0]; i < nb_tids; i++) {
printf("%*.*s", SPACES, SPACES, "");
}
printf("%s\n", func);
int *nb_calls = rbtree_lookup(top, func, (compare_func)strcmp);
if(!nb_calls) {
nb_calls = calloc(1, sizeof(*nb_calls));
rbtree_insert(top, func, nb_calls, (compare_func)strcmp);
}
(*nb_calls)++;
total_calls++;
return 0;
}
static __unused int top_cmp(const void *a, const void* b) {
const rbtree_node _a = *(const rbtree_node*) a;
const rbtree_node _b = *(const rbtree_node*) b;
return *(int*)_b->value - *(int*)_a->value;
}
void obj_show() {
int i;
printf("Timeline of memory access (x = load, * = write, one column per tid) - you may need to use left/right arrows to see the function names:\n"),
rbtree_print(timeline, print_timeline);
printf("\n\n\n");
printf("Top functions accessing the object (#access, function):\n");
rbtree_key_val_arr_t *sorted = rbtree_sort(top, top_cmp);
for(i = 0; i < sorted->nb_elements; i++) {
int *vals = (int*)sorted->vals[i]->value;
printf("%8d %5.2f%% %s\n",
vals[0],
100.*((float)vals[0])/((float)total_calls),
(char*)sorted->vals[i]->key);
}
}
void obj_modifier(int m) {
}