stdlibc: ~several fixes
[meinos.git] / stacktrace.c
blob103290b7989077458b8f858443600ae279c58133
1 #include <sys/types.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
6 typedef struct {
7 char *name;
8 void *addr;
9 char type;
10 size_t size;
11 } symbol_t;
13 static char *get_debug_data() {
14 size_t size = 0;
15 char *buf = NULL;
17 while (!feof(stdin)) {
18 buf = realloc(buf,size+BUFSIZ);
19 size += fread(buf+size,1,BUFSIZ,stdin);
22 return buf;
25 static char *dd_get_proc(char *debug) {
26 char *line = strstr(debug,"Process: #");
27 if (line!=NULL) {
28 char *space = strchr(line+10,' ');
29 if (space!=NULL) {
30 char *newline = strchr(space,'\n');
31 if (newline!=NULL) {
32 static char name[256];
33 space++;
34 memcpy(name,space,newline-space);
35 name[newline-space] = 0;
36 return name;
40 return NULL;
43 static void *dd_get_eip(char *debug) {
44 char *pos = strstr(debug,"EIP: ");
45 if (pos!=NULL) {
46 return (void*)strtoul(pos+5,NULL,16);
48 return NULL;
51 static symbol_t *get_symbols(char *name) {
52 char *cmd;
53 symbol_t *symbols = NULL;
55 asprintf(&cmd,"nm -pP --defined-only files/bin/%s",name);
56 FILE *nm = popen(cmd,"r");
57 free(cmd);
58 if (nm!=NULL) {
59 size_t i;
60 void *addr;
61 char type;
62 char name[512];
63 size_t size;
65 for (i=0;fscanf(nm,"%s %c %x %x",name,&type,&addr,&size)>0;i++) {
66 symbols = realloc(symbols,(i+1)*sizeof(symbol_t));
67 symbols[i].addr = addr;
68 symbols[i].name = strdup(name);
69 symbols[i].type = type;
70 symbols[i].size = size;
71 addr = 0;
72 type = 0;
73 name[0] = 0;
74 size = 0;
76 symbols = realloc(symbols,(i+1)*sizeof(symbol_t));
77 memset(symbols+i,0,sizeof(symbol_t));
78 pclose(nm);
79 return symbols;
81 return NULL;
84 static symbol_t *match_symbol(symbol_t *symbols,void *addr) {
85 void *max = 0;
86 symbol_t *best = NULL;
87 size_t i;
89 for (i=0;symbols[i].type!=0;i++) {
90 if (addr>symbols[i].addr && symbols[i].addr>max && (symbols[i].type=='t' || symbols[i].type=='T')) {
91 max = symbols[i].addr;
92 best = symbols+i;
95 return best;
98 static void match_stack(char *debug,symbol_t *symbols) {
99 size_t i;
100 char *stack = strstr(debug,"Stack:\n");
101 if (stack!=NULL) {
102 char *line = stack+6;
104 do {
105 void *esp;
106 void *addr;
108 line++; // skip \n
109 sscanf(line,"0x%x: 0x%x",&esp,&addr);
111 symbol_t *symbol = match_symbol(symbols,addr);
112 if (symbol!=NULL) {
113 printf("0x%08x: 0x%08x %s+0x%x (%c,%d)\n",esp,addr,symbol->name,addr-symbol->addr,symbol->type,symbol->size);
115 else printf("0x%08x: 0x%08x\n",esp,addr);
117 } while ((line = strchr(line,'\n'))!=NULL);
121 static void match_eip(symbol_t *symbols,void *eip) {
122 symbol_t *symbol = match_symbol(symbols,eip);
123 if (symbol!=NULL) {
124 printf("(EIP) 0x%08x %s+0x%x (%c,%d)\n",eip,symbol->name,eip-symbol->addr,symbol->type,symbol->size);
126 else printf("(EIP) 0x%08x\n",eip);
129 int main(int argc,char *argv[]) {
130 size_t i;
131 char *debug = get_debug_data();
132 if (debug==NULL) return 1;
134 char *proc_name = dd_get_proc(debug);
135 if (proc_name==NULL) return 1;
136 printf("|======{%s}======[Stacktrace]======|\n",proc_name);
138 symbol_t *symbols = get_symbols(proc_name);
139 if (symbols==NULL) return 1;
141 void *eip = dd_get_eip(debug);
142 if (eip!=NULL) match_eip(symbols,eip);
144 match_stack(debug,symbols);
146 free(debug);
147 for (i=0;symbols[i].type!=0;i++) free(symbols[i].name);
148 free(symbols);
150 return 0;