-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathstackdump.h
138 lines (127 loc) · 3.02 KB
/
stackdump.h
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
132
133
134
135
136
137
#ifndef _STACK_DUMP_HEADER_
#define _STACK_DUMP_HEADER_
#include <cstdio>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
class GDB_On_SEGV
{
static char arg_buffer1[256];
static char lbuf[PATH_MAX];
static char stdoutbuf[256];
static char *p;
static struct sigaction old_sa; // consider the case in which the stack is corrupted.
static struct sigaction sa; // we allocate it staticly.
static void waitgdb(int fd) {
int c = 1;
int i;
while((i = read(fd, stdoutbuf, sizeof(stdoutbuf))) > 0) {
for(int j = 0; j < i; j++) {
switch(stdoutbuf[j]) {
case '\n':
c = 1;
break;
case '(':
if(c == 1) c++; else c = 0;
break;
case 'g':
if(c == 2) c++; else c = 0;
break;
case 'd':
if(c == 3) c++; else c = 0;
break;
case 'b':
if(c == 4) c++; else c = 0;
break;
case ')':
if(c == 5) c++; else c = 0;
break;
default:
c = 0;
}
if(c == 6) {
write(1, stdoutbuf, i);
return;
}
}
write(1, stdoutbuf, i);
}
}
public:
static void gdb_handler(int dummy) {
int pid;
if((pid = fork()) != 0) {
int status;
waitpid(pid, &status, 0);
write(2, "End\n", 4);
exit(1);
} else {
int p[2];
int fp[2];
if(pipe(p) != 0) {
write(2, "pipe (p) failed\n", 16);
exit(2);
}
if(pipe(fp) != 0) {
write(2, "pipe (fp) failed\n", 17);
exit(2);
}
if((pid = fork()) != 0) {
close(p[0]);
close(fp[1]);
waitgdb(fp[0]);
write(1, "bt full\n", 8);
write(p[1], "bt full\n", 8);
waitgdb(fp[0]);
write(1, "up 3\n", 5);
write(p[1], "up 3\n", 5);
waitgdb(fp[0]);
write(1, "l\n", 2);
write(p[1], "l\n", 2);
waitgdb(fp[0]);
write(1, "disas\n", 6);
write(p[1], "disas\n", 6);
waitgdb(fp[0]);
write(1, "quit\n", 5);
write(p[1], "quit\n", 5);
// sleep(3);
exit(3);
} else {
close(p[1]);
close(fp[0]);
dup2(p[0], 0);
dup2(fp[1], 1);
execlp("gdb", "gdb", "-q", lbuf, arg_buffer1, NULL);
}
}
}
GDB_On_SEGV(char* argv0) {
p = realpath(argv0, lbuf);
if(p == NULL) {
fprintf(stderr, "Failed to expand the executable path '%s'\n", argv0);
exit(1);
}
// fprintf(stderr, "My executable path is %s\n", p);
sprintf(arg_buffer1, "%d", getpid());
memset(&sa, 0, sizeof(sa));
memset(&old_sa, 0, sizeof(old_sa));
sa.sa_handler = gdb_handler;
sa.sa_flags = SA_RESETHAND;
sigemptyset(&sa.sa_mask);
sigaction(SIGSEGV, &sa, &old_sa);
}
~GDB_On_SEGV() {
sigaction(SIGSEGV, &old_sa, NULL);
}
};
char GDB_On_SEGV::arg_buffer1[256];
char GDB_On_SEGV::lbuf[PATH_MAX];
char GDB_On_SEGV::stdoutbuf[256];
char *GDB_On_SEGV::p;
struct sigaction GDB_On_SEGV::old_sa;
struct sigaction GDB_On_SEGV::sa;
#endif // #ifndef _STACK_DUMP_HEADER_