2 * Posix OS specific functions for TCC
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <sys/ucontext.h>
24 /* fix for glibc 2.1 */
30 /* return the PC at frame level 'level'. Return non zero if not found */
31 static int rt_get_caller_pc(unsigned long *paddr
,
32 ucontext_t
*uc
, int level
)
38 #if defined(__FreeBSD__)
39 *paddr
= uc
->uc_mcontext
.mc_eip
;
40 #elif defined(__dietlibc__)
41 *paddr
= uc
->uc_mcontext
.eip
;
43 *paddr
= uc
->uc_mcontext
.gregs
[REG_EIP
];
47 #if defined(__FreeBSD__)
48 fp
= uc
->uc_mcontext
.mc_ebp
;
49 #elif defined(__dietlibc__)
50 fp
= uc
->uc_mcontext
.ebp
;
52 fp
= uc
->uc_mcontext
.gregs
[REG_EBP
];
54 for(i
=1;i
<level
;i
++) {
55 /* XXX: check address validity with program info */
56 if (fp
<= 0x1000 || fp
>= 0xc0000000)
58 fp
= ((unsigned long *)fp
)[0];
60 *paddr
= ((unsigned long *)fp
)[1];
64 #elif defined(__x86_64__)
65 /* return the PC at frame level 'level'. Return non zero if not found */
66 static int rt_get_caller_pc(unsigned long *paddr
,
67 ucontext_t
*uc
, int level
)
73 /* XXX: only support linux */
74 #if defined(__FreeBSD__)
75 *paddr
= uc
->uc_mcontext
.mc_rip
;
77 *paddr
= uc
->uc_mcontext
.gregs
[REG_RIP
];
81 #if defined(__FreeBSD__)
82 fp
= uc
->uc_mcontext
.mc_rbp
;
84 fp
= uc
->uc_mcontext
.gregs
[REG_RBP
];
86 for(i
=1;i
<level
;i
++) {
87 /* XXX: check address validity with program info */
90 fp
= ((unsigned long *)fp
)[0];
92 *paddr
= ((unsigned long *)fp
)[1];
97 #warning add arch specific rt_get_caller_pc()
98 static int rt_get_caller_pc(unsigned long *paddr
,
99 ucontext_t
*uc
, int level
)
107 /* emit a run time error at position 'pc' */
108 void rt_error(ucontext_t
*uc
, const char *fmt
, ...)
115 fprintf(stderr
, "Runtime error: ");
116 vfprintf(stderr
, fmt
, ap
);
117 fprintf(stderr
, "\n");
118 for(i
=0;i
<num_callers
;i
++) {
119 if (rt_get_caller_pc(&pc
, uc
, i
) < 0)
122 fprintf(stderr
, "at ");
124 fprintf(stderr
, "by ");
125 pc
= rt_printline(pc
);
126 if (pc
== rt_prog_main
&& pc
)
133 /* signal handler for fatal errors */
134 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
136 ucontext_t
*uc
= puc
;
140 switch(siginf
->si_code
) {
143 rt_error(uc
, "division by zero");
146 rt_error(uc
, "floating point exception");
152 if (rt_bound_error_msg
&& *rt_bound_error_msg
)
153 rt_error(uc
, *rt_bound_error_msg
);
155 rt_error(uc
, "dereferencing invalid pointer");
158 rt_error(uc
, "illegal instruction");
161 rt_error(uc
, "abort() called");
164 rt_error(uc
, "caught signal %d", signum
);
170 /* Generate a stack backtrace when a CPU exception occurs. */
171 void handle_cpu_exception(void)
173 struct sigaction sigact
;
174 /* install TCC signal handlers to print debug info on fatal
176 sigact
.sa_flags
= SA_SIGINFO
| SA_RESETHAND
;
177 sigact
.sa_sigaction
= sig_error
;
178 sigemptyset(&sigact
.sa_mask
);
179 sigaction(SIGFPE
, &sigact
, NULL
);
180 sigaction(SIGILL
, &sigact
, NULL
);
181 sigaction(SIGSEGV
, &sigact
, NULL
);
182 sigaction(SIGBUS
, &sigact
, NULL
);
183 sigaction(SIGABRT
, &sigact
, NULL
);