Back to home page

OSCL-LXR

 
 

    


0001 #include <stdlib.h>
0002 #include <string.h>
0003 #include <stdio.h>
0004 #include <signal.h>
0005 #include <unistd.h>
0006 #include <sys/mman.h>
0007 
0008 #include "utils.h"
0009 
0010 extern char __start___ex_table[];
0011 extern char __stop___ex_table[];
0012 
0013 #if defined(__powerpc64__)
0014 #define UCONTEXT_NIA(UC)    (UC)->uc_mcontext.gp_regs[PT_NIP]
0015 #elif defined(__powerpc__)
0016 #define UCONTEXT_NIA(UC)    (UC)->uc_mcontext.uc_regs->gregs[PT_NIP]
0017 #else
0018 #error implement UCONTEXT_NIA
0019 #endif
0020 
0021 static void segv_handler(int signr, siginfo_t *info, void *ptr)
0022 {
0023     ucontext_t *uc = (ucontext_t *)ptr;
0024     unsigned long addr = (unsigned long)info->si_addr;
0025     unsigned long *ip = &UCONTEXT_NIA(uc);
0026     unsigned long *ex_p = (unsigned long *)__start___ex_table;
0027 
0028     while (ex_p < (unsigned long *)__stop___ex_table) {
0029         unsigned long insn, fixup;
0030 
0031         insn = *ex_p++;
0032         fixup = *ex_p++;
0033 
0034         if (insn == *ip) {
0035             *ip = fixup;
0036             return;
0037         }
0038     }
0039 
0040     printf("No exception table match for NIA %lx ADDR %lx\n", *ip, addr);
0041     abort();
0042 }
0043 
0044 static void setup_segv_handler(void)
0045 {
0046     struct sigaction action;
0047 
0048     memset(&action, 0, sizeof(action));
0049     action.sa_sigaction = segv_handler;
0050     action.sa_flags = SA_SIGINFO;
0051     sigaction(SIGSEGV, &action, NULL);
0052 }
0053 
0054 unsigned long COPY_LOOP(void *to, const void *from, unsigned long size);
0055 unsigned long test_copy_tofrom_user_reference(void *to, const void *from, unsigned long size);
0056 
0057 static int total_passed;
0058 static int total_failed;
0059 
0060 static void do_one_test(char *dstp, char *srcp, unsigned long len)
0061 {
0062     unsigned long got, expected;
0063 
0064     got = COPY_LOOP(dstp, srcp, len);
0065     expected = test_copy_tofrom_user_reference(dstp, srcp, len);
0066 
0067     if (got != expected) {
0068         total_failed++;
0069         printf("FAIL from=%p to=%p len=%ld returned %ld, expected %ld\n",
0070                srcp, dstp, len, got, expected);
0071         //abort();
0072     } else
0073         total_passed++;
0074 }
0075 
0076 //#define MAX_LEN 512
0077 #define MAX_LEN 16
0078 
0079 int test_copy_exception(void)
0080 {
0081     int page_size;
0082     static char *p, *q;
0083     unsigned long src, dst, len;
0084 
0085     page_size = getpagesize();
0086     p = mmap(NULL, page_size * 2, PROT_READ|PROT_WRITE,
0087         MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
0088 
0089     if (p == MAP_FAILED) {
0090         perror("mmap");
0091         exit(1);
0092     }
0093 
0094     memset(p, 0, page_size);
0095 
0096     setup_segv_handler();
0097 
0098     if (mprotect(p + page_size, page_size, PROT_NONE)) {
0099         perror("mprotect");
0100         exit(1);
0101     }
0102 
0103     q = p + page_size - MAX_LEN;
0104 
0105     for (src = 0; src < MAX_LEN; src++) {
0106         for (dst = 0; dst < MAX_LEN; dst++) {
0107             for (len = 0; len < MAX_LEN+1; len++) {
0108                 // printf("from=%p to=%p len=%ld\n", q+dst, q+src, len);
0109                 do_one_test(q+dst, q+src, len);
0110             }
0111         }
0112     }
0113 
0114     printf("Totals:\n");
0115     printf("  Pass: %d\n", total_passed);
0116     printf("  Fail: %d\n", total_failed);
0117 
0118     return 0;
0119 }
0120 
0121 int main(void)
0122 {
0123     return test_harness(test_copy_exception, str(COPY_LOOP));
0124 }