Skip to content

Commit

Permalink
Basic implementation of json allocations dump
Browse files Browse the repository at this point in the history
  • Loading branch information
raydudu committed Apr 27, 2016
1 parent 2efa357 commit 001f115
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 30 deletions.
60 changes: 42 additions & 18 deletions allocdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "config.h"
#include <htable.h>
#include <json2f.h>
#include "backtrace.h"
#include "allocdb.h"

Expand Down Expand Up @@ -163,26 +164,49 @@ void allocdb_release(allocdb_t *db) {
}


static void allocdb_print(htable_entry_t *e) {
allocdb_bt_t *p;
/* allocdb_alloc_t *a; */
static int allocdb_print(htable_entry_t *e, json2f_t *jd) {
allocdb_bt_t *p = (allocdb_bt_t *)e;
allocdb_alloc_t *a;
char **bt;

json2f_obj(jd);
json2f_namedarr(jd, "backtrace");
bt = get_backtrace_symbols(p->e.key, p->e.key_len);
json2f_arr_str(jd, bt, p->e.key_len);
free(bt);
json2f_arr_end(jd);
json2f_long(jd, "allocations_amount", p->allocs_num);
json2f_namedarr(jd, "allocations");
for(a = p->allocs; a != NULL; a = a->next){
json2f_arr(jd);
json2f_arr_ulong(jd, ((unsigned long *)a->e.key), 1);
json2f_arr_ulong(jd, &(a->size), 1);
json2f_arr_end(jd);
}
json2f_arr_end(jd);
json2f_obj_end(jd);

return json2f_geterr(jd);
}

p = (allocdb_bt_t *)e;
int allocdb_dump(allocdb_t *db, FILE *fd, char *subsys) {
json2f_t jd;
int ret;

print_backtrace(e->key, e->key_len);
printf(" TOTAL ALLOCS: %zu\n", p->allocs_num);
/* a = p->allocs; */
/* while (a != NULL) { */
/* printf(" ALLOC: [%p, %zd]\n", *((void **)a->e.key), a->size); */
/* a = a->next; */
/* } */
}
D(printf("++%s\n", __func__));
json2f_init(&jd, fd);

void allocdb_dump(allocdb_t *db) {
printf("++ALLOCATIONS\n");
pthread_mutex_lock(&db->mtx);
htable_foreach(db->backtraces, allocdb_print);
pthread_mutex_unlock(&db->mtx);
printf("--ALLOCATIONS\n");
json2f_obj(&jd);
json2f_str(&jd, "subsystem", subsys);
json2f_namedarr(&jd, "allocations");

pthread_mutex_lock(&db->mtx);
ret = htable_foreach(db->backtraces, (htable_callback_fn)allocdb_print, &jd);
pthread_mutex_unlock(&db->mtx);

json2f_arr_end(&jd);
json2f_obj_end(&jd);
printf("--%s\n", __func__);
return ret;
}

3 changes: 2 additions & 1 deletion allocdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define __ALLOCDB_H__

#include <stdlib.h>
#include <stdio.h>
#include <htable.h>

typedef struct allocdb_t allocdb_t;
Expand Down Expand Up @@ -29,6 +30,6 @@ void allocdb_log_release(allocdb_t *db, void *addr);
void allocdb_log_realloc(allocdb_t *db, void *old_addr, void *new_addr, size_t new_size);
void allocdb_release(allocdb_t *db);

void allocdb_dump(allocdb_t *db);
int allocdb_dump(allocdb_t *db, FILE *fd, char *subsys);

#endif
13 changes: 9 additions & 4 deletions backtrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,21 @@

#include "config.h"

char **get_backtrace_symbols(void **addr, int len) {
return backtrace_symbols(addr, len);
}

void print_backtrace(void **addr, int len) {
int i;
char **symbollist = backtrace_symbols(addr, len);
char **symbollist = get_backtrace_symbols(addr, len);

for(i = 0; i < len && addr[i] != NULL; i++) {
printf("[%02d]: %s\n", i, symbollist[i]);
}
free(symbollist);
}

static void out_of_stack_marker() {
static void __attribute__ ((unused)) out_of_stack_marker() {
};

#ifdef DMM_OWN_BACKTRACE
Expand All @@ -27,8 +31,9 @@ static void out_of_stack_marker() {
* long pc = *(topfp - 0);
*/

//assuming stack is less than 64k
#define STACK_ADDR_MASK (((1UL << 16) - 1) << (CHAR_BIT * sizeof(unsigned long) - 16))
//assuming stack is less than 2048k
//TODO use getrlimit(RLIMIT_STACK ... or parse /proc/self/maps
#define STACK_ADDR_MASK (((1UL << 16) - 1) << (CHAR_BIT * sizeof(unsigned long) - 21))

int get_backtrace(void **addr, int len) {
int i;
Expand Down
1 change: 1 addition & 0 deletions backtrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@

int get_backtrace(void **addr, int len);
void print_backtrace(void **addr, int len);
char **get_backtrace_symbols(void **addr, int len);

#endif /* __BACKTRACE_H__ */
2 changes: 1 addition & 1 deletion config.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@

#define DMM_DEFAULT_ALIGNMENT sizeof(unsigned long)

#define DMM_DEFAULT_DUMP_LOCATION "/tmp"
#define DMM_DEFAULT_DUMP_LOCATION "./"

#endif /* __CONFIG_H__ */
2 changes: 1 addition & 1 deletion dmm.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ static void dmm_make_snapshot(int sig) {
FILE *fd;
int save_error = 0;

snprintf(fn, FNAME_MAX_LEN, "%s/dmm_%d_%d.json", dumps_location, pid, dump_seq);
snprintf(fn, FNAME_MAX_LEN, "%s/dmm_%d_%04d.json", dumps_location, pid, dump_seq);
printf("Saving allocation snapshot to: %s\n", fn);
fd = fopen(fn, "w");
if (fd == NULL) {
Expand Down
10 changes: 8 additions & 2 deletions external/htable.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,17 +171,23 @@ void htable_delete(htable_t *table, void (*entry_free)(htable_entry_t *)) {
free(table);
}

void htable_foreach(htable_t *table, htable_callback_fn callback) {
int htable_foreach(htable_t *table, htable_callback_fn callback, void *context) {
size_t i;
int ret = -1;

for (i = 0; i < table->size; i++) {
if (table->entries[i] != NULL) {
htable_entry_t *e = table->entries[i];
while (e != NULL) {
callback(e);
ret = callback(e, context);
if (ret != 0) {
break;
}
e = e->next;
}
}
}
return ret;
}

#ifdef HTABLE_DEBUG
Expand Down
4 changes: 2 additions & 2 deletions external/htable.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ typedef struct htable_entry_t {

typedef struct htable_t htable_t;

typedef void (*htable_callback_fn)(htable_entry_t *);
typedef int (*htable_callback_fn)(htable_entry_t *, void *context);

htable_t *htable_new(size_t size);
void htable_push(htable_t *table, htable_entry_t *entry);
Expand All @@ -46,7 +46,7 @@ void htable_scrap(htable_t *table, htable_entry_t *entry);

void htable_delete(htable_t *table, void (*entry_free)(htable_entry_t *));

void htable_foreach(htable_t *table, htable_callback_fn);
int htable_foreach(htable_t *table, htable_callback_fn, void *context);

#ifdef HTABLE_DEBUG
void htable_dump(htable_t *table);
Expand Down
24 changes: 24 additions & 0 deletions external/json2f.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@ void inline json2f_long(json2f_t *jd, char *name, long l) {
jd->delim = ',';
}

void inline json2f_ulong(json2f_t *jd, char *name, unsigned long ul) {
if (jd->error) {
return;
}
if(fprintf(jd->fd, "%c\"%s\":%lu", jd->delim, name, ul) < 0) {
jd->error = errno;
}
jd->delim = ',';
}

void inline json2f_str(json2f_t *jd, char *name, char *s) {
if (jd->error) {
return;
Expand Down Expand Up @@ -190,6 +200,20 @@ void inline json2f_arr_long(json2f_t *jd, long *arr, int len) {
}
}

void inline json2f_arr_ulong(json2f_t *jd, unsigned long *arr, int len) {
int i;
if (jd->error) {
return;
}
for (i = 0; i < len; i++) {
if (fprintf(jd->fd, "%c%ld", jd->delim, arr[i]) < 0) {
jd->error = errno;
break;
}
jd->delim = ',';
}
}

int inline json2f_geterr(json2f_t *jd) {
return jd->error;
}
Expand Down
5 changes: 4 additions & 1 deletion hooks_stdlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,16 @@ void stdlib_init() {
}

int stdlib_snapshot(FILE *fd) {
int ret = -1;
tlocker_acquire();

if (allocs != NULL) {
allocdb_dump(allocs);
ret = allocdb_dump(allocs, fd, "STDLIB");
}

tlocker_release();

return ret;
}

void stdlib_release(){
Expand Down

0 comments on commit 001f115

Please sign in to comment.