Skip to content

Commit 1d98b28

Browse files
committed
mmap_cache: do not activate unless requested
Do not call mmap_cache functions until mmap_cache_enable is invoked. Change struct mmap_cache_t into a proxy structure, move all mmap_cache data from struct tcb inside this new structure. * Makefile.am (strace_SOURCES): Move mmap_cache.c and mmap_cache.h to libstrace_a_SOURCES. * defs.h (struct tcb): Remove mmap_cache_size and mmap_cache_generation * fields. * mmap_cache.h (struct mmap_cache_t): Rename to struct mmap_cache_entry_t, create a new struct mmap_cache_t, all users updated. (mmap_cache_delete): Remove. * mmap_cache.c (mmap_cache_delete): Rename to delete_mmap_cache, add static qualifier. (build_mmap_cache): Merge into mmap_cache_rebuild_if_invalid. * strace.c (droptcb): Replace mmap_cache_delete invocation with tcp->mmap_cache->free_fn.
1 parent a1ecb2a commit 1d98b28

File tree

6 files changed

+93
-91
lines changed

6 files changed

+93
-91
lines changed

Makefile.am

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ libstrace_a_SOURCES = \
7575
fstatfs64.c \
7676
getpagesize.c \
7777
ipc.c \
78+
mmap_cache.c \
79+
mmap_cache.h \
7880
sigreturn.c \
7981
socketcall.c \
8082
statfs.c \
@@ -190,8 +192,6 @@ strace_SOURCES = \
190192
membarrier.c \
191193
memfd_create.c \
192194
mknod.c \
193-
mmap_cache.c \
194-
mmap_cache.h \
195195
mmap_notify.c \
196196
mmap_notify.h \
197197
mmsghdr.c \

defs.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,6 @@ struct tcb {
219219
struct timespec delay_expiration_time; /* When does the delay end */
220220

221221
struct mmap_cache_t *mmap_cache;
222-
unsigned int mmap_cache_size;
223-
unsigned int mmap_cache_generation;
224222

225223
#ifdef ENABLE_STACKTRACE
226224
void *unwind_ctx;

mmap_cache.c

Lines changed: 73 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ mmap_cache_invalidate(struct tcb *tcp, void *unused)
4646
#endif
4747
mmap_cache_generation++;
4848
debug_func_msg("tgen=%u, ggen=%u, tcp=%p, cache=%p",
49-
tcp->mmap_cache_generation,
50-
mmap_cache_generation,
51-
tcp, tcp->mmap_cache);
49+
tcp->mmap_cache ? tcp->mmap_cache->generation : 0,
50+
mmap_cache_generation, tcp,
51+
tcp->mmap_cache ? tcp->mmap_cache->entry : 0);
5252
}
5353

5454
void
@@ -62,33 +62,66 @@ mmap_cache_enable(void)
6262
}
6363
}
6464

65+
/* deleting the cache */
66+
static void
67+
delete_mmap_cache(struct tcb *tcp, const char *caller)
68+
{
69+
debug_func_msg("tgen=%u, ggen=%u, tcp=%p, cache=%p, caller=%s",
70+
tcp->mmap_cache ? tcp->mmap_cache->generation : 0,
71+
mmap_cache_generation, tcp,
72+
tcp->mmap_cache ? tcp->mmap_cache->entry : 0, caller);
73+
74+
if (!tcp->mmap_cache)
75+
return;
76+
77+
while (tcp->mmap_cache->size) {
78+
unsigned int i = --tcp->mmap_cache->size;
79+
free(tcp->mmap_cache->entry[i].binary_filename);
80+
tcp->mmap_cache->entry[i].binary_filename = NULL;
81+
}
82+
83+
free(tcp->mmap_cache->entry);
84+
tcp->mmap_cache->entry = NULL;
85+
86+
free(tcp->mmap_cache);
87+
tcp->mmap_cache = NULL;
88+
}
89+
6590
/*
6691
* caching of /proc/ID/maps for each process to speed up stack tracing
6792
*
6893
* The cache must be refreshed after syscalls that affect memory mappings,
6994
* e.g. mmap, mprotect, munmap, execve.
7095
*/
71-
static void
72-
build_mmap_cache(struct tcb *tcp)
96+
extern enum mmap_cache_rebuild_result
97+
mmap_cache_rebuild_if_invalid(struct tcb *tcp, const char *caller)
7398
{
74-
FILE *fp;
75-
struct mmap_cache_t *cache_head = tcp->mmap_cache;
76-
/* start with a small dynamically-allocated array and then expand it */
77-
size_t cur_array_size = 0;
78-
char filename[sizeof("/proc/4294967296/maps")];
79-
char buffer[PATH_MAX + 80];
99+
if (tcp->mmap_cache
100+
&& tcp->mmap_cache->generation != mmap_cache_generation)
101+
delete_mmap_cache(tcp, caller);
80102

103+
if (tcp->mmap_cache)
104+
return MMAP_CACHE_REBUILD_READY;
105+
106+
char filename[sizeof("/proc/4294967296/maps")];
81107
xsprintf(filename, "/proc/%u/maps", tcp->pid);
82-
fp = fopen_stream(filename, "r");
108+
109+
FILE *fp = fopen_stream(filename, "r");
83110
if (!fp) {
84111
perror_msg("fopen: %s", filename);
85-
return;
112+
return MMAP_CACHE_REBUILD_NOCACHE;
86113
}
87114

88-
tcp->mmap_cache_size = 0;
115+
struct mmap_cache_t cache = {
116+
.free_fn = delete_mmap_cache,
117+
.generation = mmap_cache_generation
118+
};
119+
120+
/* start with a small dynamically-allocated array and then expand it */
121+
size_t allocated = 0;
122+
char buffer[PATH_MAX + 80];
89123

90124
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
91-
struct mmap_cache_t *entry;
92125
unsigned long start_addr, end_addr, mmap_offset;
93126
char read_bit;
94127
char write_bit;
@@ -120,12 +153,13 @@ build_mmap_cache(struct tcb *tcp)
120153
break;
121154
}
122155

156+
struct mmap_cache_entry_t *entry;
123157
/*
124158
* sanity check to make sure that we're storing
125159
* non-overlapping regions in ascending order
126160
*/
127-
if (tcp->mmap_cache_size > 0) {
128-
entry = &cache_head[tcp->mmap_cache_size - 1];
161+
if (cache.size > 0) {
162+
entry = &cache.entry[cache.size - 1];
129163
if (entry->start_addr == start_addr &&
130164
entry->end_addr == end_addr) {
131165
/* duplicate entry, e.g. [vsyscall] */
@@ -143,11 +177,11 @@ build_mmap_cache(struct tcb *tcp)
143177
}
144178
}
145179

146-
if (tcp->mmap_cache_size >= cur_array_size)
147-
cache_head = xgrowarray(cache_head, &cur_array_size,
148-
sizeof(*cache_head));
180+
if (cache.size >= allocated)
181+
cache.entry = xgrowarray(cache.entry, &allocated,
182+
sizeof(*cache.entry));
149183

150-
entry = &cache_head[tcp->mmap_cache_size];
184+
entry = &cache.entry[cache.size];
151185
entry->start_addr = start_addr;
152186
entry->end_addr = end_addr;
153187
entry->mmap_offset = mmap_offset;
@@ -161,73 +195,40 @@ build_mmap_cache(struct tcb *tcp)
161195
entry->major = major;
162196
entry->minor = minor;
163197
entry->binary_filename = xstrdup(binary_path);
164-
tcp->mmap_cache_size++;
198+
cache.size++;
165199
}
166200
fclose(fp);
167-
tcp->mmap_cache = cache_head;
168-
tcp->mmap_cache_generation = mmap_cache_generation;
169201

170-
debug_func_msg("tgen=%u, ggen=%u, tcp=%p, cache=%p",
171-
tcp->mmap_cache_generation,
172-
mmap_cache_generation,
173-
tcp, tcp->mmap_cache);
174-
}
202+
if (!cache.size)
203+
return MMAP_CACHE_REBUILD_NOCACHE;
175204

176-
/* deleting the cache */
177-
extern void
178-
mmap_cache_delete(struct tcb *tcp, const char *caller)
179-
{
180-
unsigned int i;
205+
tcp->mmap_cache = xmalloc(sizeof(*tcp->mmap_cache));
206+
memcpy(tcp->mmap_cache, &cache, sizeof(cache));
181207

182208
debug_func_msg("tgen=%u, ggen=%u, tcp=%p, cache=%p, caller=%s",
183-
tcp->mmap_cache_generation,
184-
mmap_cache_generation,
185-
tcp, tcp->mmap_cache, caller);
186-
187-
for (i = 0; i < tcp->mmap_cache_size; i++) {
188-
free(tcp->mmap_cache[i].binary_filename);
189-
tcp->mmap_cache[i].binary_filename = NULL;
190-
}
191-
free(tcp->mmap_cache);
192-
tcp->mmap_cache = NULL;
193-
tcp->mmap_cache_size = 0;
194-
}
209+
tcp->mmap_cache->generation, mmap_cache_generation,
210+
tcp, tcp->mmap_cache->entry, caller);
195211

196-
extern enum mmap_cache_rebuild_result
197-
mmap_cache_rebuild_if_invalid(struct tcb *tcp, const char *caller)
198-
{
199-
enum mmap_cache_rebuild_result r = MMAP_CACHE_REBUILD_READY;
200-
if ((tcp->mmap_cache_generation != mmap_cache_generation)
201-
&& tcp->mmap_cache)
202-
mmap_cache_delete(tcp, caller);
203-
204-
if (!tcp->mmap_cache) {
205-
r = MMAP_CACHE_REBUILD_RENEWED;
206-
build_mmap_cache(tcp);
207-
}
208-
209-
if (!(tcp->mmap_cache && tcp->mmap_cache_size))
210-
r = MMAP_CACHE_REBUILD_NOCACHE;
211-
212-
return r;
212+
return MMAP_CACHE_REBUILD_RENEWED;
213213
}
214214

215-
struct mmap_cache_t *
215+
struct mmap_cache_entry_t *
216216
mmap_cache_search(struct tcb *tcp, unsigned long ip)
217217
{
218+
if (!tcp->mmap_cache)
219+
return NULL;
220+
218221
int lower = 0;
219-
int upper = (int) tcp->mmap_cache_size - 1;
222+
int upper = (int) tcp->mmap_cache->size - 1;
220223

221224
while (lower <= upper) {
222-
struct mmap_cache_t *cur_mmap_cache;
223225
int mid = (upper + lower) / 2;
226+
struct mmap_cache_entry_t *entry = &tcp->mmap_cache->entry[mid];
224227

225-
cur_mmap_cache = &tcp->mmap_cache[mid];
226-
227-
if (ip >= cur_mmap_cache->start_addr &&
228-
ip < cur_mmap_cache->end_addr)
229-
return cur_mmap_cache;
230-
else if (ip < cur_mmap_cache->start_addr)
228+
if (ip >= entry->start_addr &&
229+
ip < entry->end_addr)
230+
return entry;
231+
else if (ip < entry->start_addr)
231232
upper = mid - 1;
232233
else
233234
lower = mid + 1;

mmap_cache.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,15 @@
3131
* Keep a sorted array of cache entries,
3232
* so that we can binary search through it.
3333
*/
34+
3435
struct mmap_cache_t {
36+
struct mmap_cache_entry_t *entry;
37+
void (*free_fn)(struct tcb *, const char *caller);
38+
unsigned int size;
39+
unsigned int generation;
40+
};
41+
42+
struct mmap_cache_entry_t {
3543
/**
3644
* example entry:
3745
* 7fabbb09b000-7fabbb09f000 r-xp 00179000 fc:00 1180246 /lib/libc-2.11.1.so
@@ -68,13 +76,10 @@ enum mmap_cache_rebuild_result {
6876
extern void
6977
mmap_cache_enable(void);
7078

71-
extern void
72-
mmap_cache_delete(struct tcb *, const char *caller);
73-
7479
extern enum mmap_cache_rebuild_result
7580
mmap_cache_rebuild_if_invalid(struct tcb *, const char *caller);
7681

77-
extern struct mmap_cache_t *
82+
extern struct mmap_cache_entry_t *
7883
mmap_cache_search(struct tcb *, unsigned long ip);
7984

8085
#endif /* !STRACE_MMAP_CACHE_H */

strace.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -819,7 +819,8 @@ droptcb(struct tcb *tcp)
819819
unwind_tcb_fin(tcp);
820820
#endif
821821

822-
mmap_cache_delete(tcp, __func__);
822+
if (tcp->mmap_cache)
823+
tcp->mmap_cache->free_fn(tcp, __func__);
823824

824825
nprocs--;
825826
debug_msg("dropped tcb for pid %d, %d remain", tcp->pid, nprocs);

unwind-libunwind.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -89,26 +89,25 @@ print_stack_frame(struct tcb *tcp,
8989
size_t *symbol_name_size)
9090
{
9191
unw_word_t ip;
92-
struct mmap_cache_t *cur_mmap_cache;
9392

9493
if (unw_get_reg(cursor, UNW_REG_IP, &ip) < 0) {
9594
perror_msg("cannot walk the stack of process %d", tcp->pid);
9695
return -1;
9796
}
9897

99-
cur_mmap_cache = mmap_cache_search(tcp, ip);
100-
if (cur_mmap_cache
98+
struct mmap_cache_entry_t *entry = mmap_cache_search(tcp, ip);
99+
100+
if (entry
101101
/* ignore mappings that have no PROT_EXEC bit set */
102-
&& (cur_mmap_cache->protections & MMAP_CACHE_PROT_EXECUTABLE)) {
103-
unsigned long true_offset;
102+
&& (entry->protections & MMAP_CACHE_PROT_EXECUTABLE)) {
104103
unw_word_t function_offset;
105104

106105
get_symbol_name(cursor, symbol_name, symbol_name_size,
107106
&function_offset);
108-
true_offset = ip - cur_mmap_cache->start_addr +
109-
cur_mmap_cache->mmap_offset;
107+
unsigned long true_offset =
108+
ip - entry->start_addr + entry->mmap_offset;
110109
call_action(data,
111-
cur_mmap_cache->binary_filename,
110+
entry->binary_filename,
112111
*symbol_name,
113112
function_offset,
114113
true_offset);
@@ -139,8 +138,6 @@ walk(struct tcb *tcp,
139138

140139
if (!tcp->mmap_cache)
141140
error_func_msg_and_die("mmap_cache is NULL");
142-
if (tcp->mmap_cache_size == 0)
143-
error_func_msg_and_die("mmap_cache is empty");
144141

145142
symbol_name = xmalloc(symbol_name_size);
146143

0 commit comments

Comments
 (0)