221 |
|
#define SIGSEGV_FAULT_HANDLER_ARGLIST_1 siginfo_t *sip, void *scp |
222 |
|
#define SIGSEGV_FAULT_HANDLER_ARGS sip, scp |
223 |
|
#define SIGSEGV_FAULT_ADDRESS sip->si_addr |
224 |
< |
#if defined(__NetBSD__) || defined(__FreeBSD__) |
224 |
> |
#if defined(__sun__) |
225 |
> |
#if (defined(sparc) || defined(__sparc__)) |
226 |
> |
#include <sys/ucontext.h> |
227 |
> |
#define SIGSEGV_CONTEXT_REGS (((ucontext_t *)scp)->uc_mcontext.gregs) |
228 |
> |
#define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_CONTEXT_REGS[REG_PC] |
229 |
> |
#endif |
230 |
> |
#endif |
231 |
> |
#if defined(__FreeBSD__) |
232 |
|
#if (defined(i386) || defined(__i386__)) |
233 |
|
#define SIGSEGV_FAULT_INSTRUCTION (((struct sigcontext *)scp)->sc_eip) |
234 |
|
#define SIGSEGV_REGISTER_FILE ((unsigned int *)&(((struct sigcontext *)scp)->sc_edi)) /* EDI is the first GPR (even below EIP) in sigcontext */ |
297 |
|
#define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp |
298 |
|
#define SIGSEGV_FAULT_ADDRESS get_fault_address(scp) |
299 |
|
#define SIGSEGV_FAULT_INSTRUCTION scp->sc_pc |
293 |
– |
|
294 |
– |
// From Boehm's GC 6.0alpha8 |
295 |
– |
static sigsegv_address_t get_fault_address(struct sigcontext *scp) |
296 |
– |
{ |
297 |
– |
unsigned int instruction = *((unsigned int *)(scp->sc_pc)); |
298 |
– |
unsigned long fault_address = scp->sc_regs[(instruction >> 16) & 0x1f]; |
299 |
– |
fault_address += (signed long)(signed short)(instruction & 0xffff); |
300 |
– |
return (sigsegv_address_t)fault_address; |
301 |
– |
} |
300 |
|
#endif |
301 |
|
#endif |
302 |
|
|
334 |
|
#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV) |
335 |
|
#endif |
336 |
|
|
337 |
< |
// NetBSD or FreeBSD |
338 |
< |
#if defined(__NetBSD__) || defined(__FreeBSD__) |
337 |
> |
// NetBSD |
338 |
> |
#if defined(__NetBSD__) |
339 |
|
#if (defined(m68k) || defined(__m68k__)) |
340 |
|
#include <m68k/frame.h> |
341 |
|
#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp |
363 |
|
} |
364 |
|
return (sigsegv_address_t)fault_addr; |
365 |
|
} |
366 |
< |
#else |
367 |
< |
#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, void *scp, char *addr |
366 |
> |
#endif |
367 |
> |
#if (defined(alpha) || defined(__alpha__)) |
368 |
> |
#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp |
369 |
> |
#define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp |
370 |
> |
#define SIGSEGV_FAULT_ADDRESS get_fault_address(scp) |
371 |
> |
#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGBUS) |
372 |
> |
#endif |
373 |
> |
#if (defined(i386) || defined(__i386__)) |
374 |
> |
#error "FIXME: need to decode instruction and compute EA" |
375 |
> |
#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp |
376 |
> |
#define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp |
377 |
> |
#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV) |
378 |
> |
#endif |
379 |
> |
#endif |
380 |
> |
#if defined(__FreeBSD__) |
381 |
> |
#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGBUS) |
382 |
> |
#if (defined(i386) || defined(__i386__)) |
383 |
> |
#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp, char *addr |
384 |
|
#define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp, addr |
385 |
|
#define SIGSEGV_FAULT_ADDRESS addr |
386 |
< |
#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGBUS) |
386 |
> |
#define SIGSEGV_FAULT_INSTRUCTION scp->sc_eip |
387 |
> |
#define SIGSEGV_REGISTER_FILE ((unsigned int *)&scp->sc_edi) |
388 |
> |
#define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction |
389 |
|
#endif |
390 |
|
#endif |
391 |
|
|
392 |
+ |
// Extract fault address out of a sigcontext |
393 |
+ |
#if (defined(alpha) || defined(__alpha__)) |
394 |
+ |
// From Boehm's GC 6.0alpha8 |
395 |
+ |
static sigsegv_address_t get_fault_address(struct sigcontext *scp) |
396 |
+ |
{ |
397 |
+ |
unsigned int instruction = *((unsigned int *)(scp->sc_pc)); |
398 |
+ |
unsigned long fault_address = scp->sc_regs[(instruction >> 16) & 0x1f]; |
399 |
+ |
fault_address += (signed long)(signed short)(instruction & 0xffff); |
400 |
+ |
return (sigsegv_address_t)fault_address; |
401 |
+ |
} |
402 |
+ |
#endif |
403 |
+ |
|
404 |
+ |
|
405 |
|
// MacOS X, not sure which version this works in. Under 10.1 |
406 |
|
// vm_protect does not appear to work from a signal handler. Under |
407 |
|
// 10.2 signal handlers get siginfo type arguments but the si_addr |
1221 |
|
#include <sys/mman.h> |
1222 |
|
#include "vm_alloc.h" |
1223 |
|
|
1224 |
+ |
const int REF_INDEX = 123; |
1225 |
+ |
const int REF_VALUE = 45; |
1226 |
+ |
|
1227 |
|
static int page_size; |
1228 |
|
static volatile char * page = 0; |
1229 |
|
static volatile int handler_called = 0; |
1230 |
|
|
1231 |
+ |
#ifdef __GNUC__ |
1232 |
+ |
// Code range where we expect the fault to come from |
1233 |
+ |
static void *b_region, *e_region; |
1234 |
+ |
#endif |
1235 |
+ |
|
1236 |
|
static sigsegv_return_t sigsegv_test_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address) |
1237 |
|
{ |
1238 |
|
handler_called++; |
1239 |
< |
if ((fault_address - 123) != page) |
1239 |
> |
if ((fault_address - REF_INDEX) != page) |
1240 |
|
exit(10); |
1241 |
< |
if (vm_protect((char *)((unsigned long)fault_address & -page_size), page_size, VM_PAGE_READ | VM_PAGE_WRITE) != 0) |
1241 |
> |
#ifdef __GNUC__ |
1242 |
> |
// Make sure reported fault instruction address falls into |
1243 |
> |
// expected code range |
1244 |
> |
if (instruction_address != SIGSEGV_INVALID_PC |
1245 |
> |
&& ((instruction_address < (sigsegv_address_t)b_region) || |
1246 |
> |
(instruction_address >= (sigsegv_address_t)e_region))) |
1247 |
|
exit(11); |
1248 |
+ |
#endif |
1249 |
+ |
if (vm_protect((char *)((unsigned long)fault_address & -page_size), page_size, VM_PAGE_READ | VM_PAGE_WRITE) != 0) |
1250 |
+ |
exit(12); |
1251 |
|
return SIGSEGV_RETURN_SUCCESS; |
1252 |
|
} |
1253 |
|
|
1254 |
|
#ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION |
1210 |
– |
#ifdef __GNUC__ |
1211 |
– |
// Code range where we expect the fault to come from |
1212 |
– |
static void *b_region, *e_region; |
1213 |
– |
#endif |
1214 |
– |
|
1255 |
|
static sigsegv_return_t sigsegv_insn_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address) |
1256 |
|
{ |
1257 |
|
if (((unsigned long)fault_address - (unsigned long)page) < page_size) { |
1279 |
|
if ((page = (char *)vm_acquire(page_size)) == VM_MAP_FAILED) |
1280 |
|
return 2; |
1281 |
|
|
1282 |
+ |
memset((void *)page, 0, page_size); |
1283 |
|
if (vm_protect((char *)page, page_size, VM_PAGE_READ) < 0) |
1284 |
|
return 3; |
1285 |
|
|
1286 |
|
if (!sigsegv_install_handler(sigsegv_test_handler)) |
1287 |
|
return 4; |
1288 |
|
|
1289 |
< |
page[123] = 45; |
1290 |
< |
page[123] = 45; |
1291 |
< |
|
1289 |
> |
#ifdef __GNUC__ |
1290 |
> |
b_region = &&L_b_region1; |
1291 |
> |
e_region = &&L_e_region1; |
1292 |
> |
#endif |
1293 |
> |
L_b_region1: |
1294 |
> |
page[REF_INDEX] = REF_VALUE; |
1295 |
> |
if (page[REF_INDEX] != REF_VALUE) |
1296 |
> |
exit(20); |
1297 |
> |
page[REF_INDEX] = REF_VALUE; |
1298 |
> |
L_e_region1: |
1299 |
> |
|
1300 |
|
if (handler_called != 1) |
1301 |
|
return 5; |
1302 |
|
|
1322 |
|
} while (0) |
1323 |
|
|
1324 |
|
#ifdef __GNUC__ |
1325 |
< |
b_region = &&L_b_region; |
1326 |
< |
e_region = &&L_e_region; |
1325 |
> |
b_region = &&L_b_region2; |
1326 |
> |
e_region = &&L_e_region2; |
1327 |
|
#endif |
1328 |
< |
L_b_region: |
1328 |
> |
L_b_region2: |
1329 |
|
TEST_SKIP_INSTRUCTION(unsigned char); |
1330 |
|
TEST_SKIP_INSTRUCTION(unsigned short); |
1331 |
|
TEST_SKIP_INSTRUCTION(unsigned int); |
1332 |
< |
L_e_region: |
1332 |
> |
L_e_region2: |
1333 |
|
#endif |
1334 |
|
|
1335 |
|
vm_exit(); |
1336 |
|
return 0; |
1337 |
|
} |
1338 |
|
#endif |
1339 |
+ |
|
1340 |
+ |
|
1341 |
+ |
|
1342 |
+ |
|
1343 |
+ |
|
1344 |
+ |
|
1345 |
+ |
|
1346 |
+ |
|
1347 |
+ |
|
1348 |
+ |
|
1349 |
+ |
|
1350 |
+ |
|
1351 |
+ |
|
1352 |
+ |
|
1353 |
+ |
|