ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/sigsegv.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/sigsegv.cpp (file contents):
Revision 1.11 by gbeauche, 2002-05-12T13:51:22Z vs.
Revision 1.21 by gbeauche, 2002-10-03T15:49:14Z

# Line 44 | Line 44 | typedef RETSIGTYPE (*signal_handler)(int
44   static bool sigsegv_ignore_fault = false;
45  
46   // User's SIGSEGV handler
47 < static sigsegv_handler_t sigsegv_user_handler = 0;
47 > static sigsegv_fault_handler_t sigsegv_fault_handler = 0;
48  
49   // Function called to dump state if we can't handle the fault
50 < static sigsegv_handler_t sigsegv_dump_state = 0;
50 > static sigsegv_state_dumper_t sigsegv_state_dumper = 0;
51  
52   // Actual SIGSEGV handler installer
53   static bool sigsegv_do_install_handler(int sig);
54  
55  
56   /*
57 + *  Instruction decoding aids
58 + */
59 +
60 + // Transfer type
61 + enum transfer_type_t {
62 +        TYPE_UNKNOWN,
63 +        TYPE_LOAD,
64 +        TYPE_STORE
65 + };
66 +
67 + // Transfer size
68 + enum transfer_size_t {
69 +        SIZE_UNKNOWN,
70 +        SIZE_BYTE,
71 +        SIZE_WORD,
72 +        SIZE_LONG
73 + };
74 +
75 + #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__))
76 + // Addressing mode
77 + enum addressing_mode_t {
78 +        MODE_UNKNOWN,
79 +        MODE_NORM,
80 +        MODE_U,
81 +        MODE_X,
82 +        MODE_UX
83 + };
84 +
85 + // Decoded instruction
86 + struct instruction_t {
87 +        transfer_type_t         transfer_type;
88 +        transfer_size_t         transfer_size;
89 +        addressing_mode_t       addr_mode;
90 +        unsigned int            addr;
91 +        char                            ra, rd;
92 + };
93 +
94 + static void powerpc_decode_instruction(instruction_t *instruction, unsigned int nip, unsigned int * gpr)
95 + {
96 +        // Get opcode and divide into fields
97 +        unsigned int opcode = *((unsigned int *)nip);
98 +        unsigned int primop = opcode >> 26;
99 +        unsigned int exop = (opcode >> 1) & 0x3ff;
100 +        unsigned int ra = (opcode >> 16) & 0x1f;
101 +        unsigned int rb = (opcode >> 11) & 0x1f;
102 +        unsigned int rd = (opcode >> 21) & 0x1f;
103 +        signed int imm = (signed short)(opcode & 0xffff);
104 +        
105 +        // Analyze opcode
106 +        transfer_type_t transfer_type = TYPE_UNKNOWN;
107 +        transfer_size_t transfer_size = SIZE_UNKNOWN;
108 +        addressing_mode_t addr_mode = MODE_UNKNOWN;
109 +        switch (primop) {
110 +        case 31:
111 +                switch (exop) {
112 +                case 23:        // lwzx
113 +                        transfer_type = TYPE_LOAD; transfer_size = SIZE_LONG; addr_mode = MODE_X; break;
114 +                case 55:        // lwzux
115 +                        transfer_type = TYPE_LOAD; transfer_size = SIZE_LONG; addr_mode = MODE_UX; break;
116 +                case 87:        // lbzx
117 +                        transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break;
118 +                case 119:       // lbzux
119 +                        transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break;
120 +                case 151:       // stwx
121 +                        transfer_type = TYPE_STORE; transfer_size = SIZE_LONG; addr_mode = MODE_X; break;
122 +                case 183:       // stwux
123 +                        transfer_type = TYPE_STORE; transfer_size = SIZE_LONG; addr_mode = MODE_UX; break;
124 +                case 215:       // stbx
125 +                        transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break;
126 +                case 247:       // stbux
127 +                        transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break;
128 +                case 279:       // lhzx
129 +                        transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
130 +                case 311:       // lhzux
131 +                        transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
132 +                case 343:       // lhax
133 +                        transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
134 +                case 375:       // lhaux
135 +                        transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
136 +                case 407:       // sthx
137 +                        transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
138 +                case 439:       // sthux
139 +                        transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
140 +                }
141 +                break;
142 +        
143 +        case 32:        // lwz
144 +                transfer_type = TYPE_LOAD; transfer_size = SIZE_LONG; addr_mode = MODE_NORM; break;
145 +        case 33:        // lwzu
146 +                transfer_type = TYPE_LOAD; transfer_size = SIZE_LONG; addr_mode = MODE_U; break;
147 +        case 34:        // lbz
148 +                transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break;
149 +        case 35:        // lbzu
150 +                transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break;
151 +        case 36:        // stw
152 +                transfer_type = TYPE_STORE; transfer_size = SIZE_LONG; addr_mode = MODE_NORM; break;
153 +        case 37:        // stwu
154 +                transfer_type = TYPE_STORE; transfer_size = SIZE_LONG; addr_mode = MODE_U; break;
155 +        case 38:        // stb
156 +                transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break;
157 +        case 39:        // stbu
158 +                transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break;
159 +        case 40:        // lhz
160 +                transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
161 +        case 41:        // lhzu
162 +                transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
163 +        case 42:        // lha
164 +                transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
165 +        case 43:        // lhau
166 +                transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
167 +        case 44:        // sth
168 +                transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
169 +        case 45:        // sthu
170 +                transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
171 +        }
172 +        
173 +        // Calculate effective address
174 +        unsigned int addr = 0;
175 +        switch (addr_mode) {
176 +        case MODE_X:
177 +        case MODE_UX:
178 +                if (ra == 0)
179 +                        addr = gpr[rb];
180 +                else
181 +                        addr = gpr[ra] + gpr[rb];
182 +                break;
183 +        case MODE_NORM:
184 +        case MODE_U:
185 +                if (ra == 0)
186 +                        addr = (signed int)(signed short)imm;
187 +                else
188 +                        addr = gpr[ra] + (signed int)(signed short)imm;
189 +                break;
190 +        default:
191 +                break;
192 +        }
193 +        
194 +        // Commit decoded instruction
195 +        instruction->addr = addr;
196 +        instruction->addr_mode = addr_mode;
197 +        instruction->transfer_type = transfer_type;
198 +        instruction->transfer_size = transfer_size;
199 +        instruction->ra = ra;
200 +        instruction->rd = rd;
201 + }
202 + #endif
203 +
204 +
205 + /*
206   *  OS-dependant SIGSEGV signals support section
207   */
208  
# Line 66 | Line 215 | static bool sigsegv_do_install_handler(i
215   #endif
216   #define SIGSEGV_FAULT_HANDLER_ARGLIST   int sig, siginfo_t *sip, void *scp
217   #define SIGSEGV_FAULT_ADDRESS                   sip->si_addr
218 + #if defined(__NetBSD__) || defined(__FreeBSD__)
219 + #if (defined(i386) || defined(__i386__))
220 + #define SIGSEGV_FAULT_INSTRUCTION               (((struct sigcontext *)scp)->sc_eip)
221 + #define SIGSEGV_REGISTER_FILE                   ((unsigned int *)&(((struct sigcontext *)scp)->sc_edi)) /* EDI is the first GPR (even below EIP) in sigcontext */
222 + #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
223 + #endif
224 + #endif
225   #if defined(__linux__)
226   #if (defined(i386) || defined(__i386__))
227   #include <sys/ucontext.h>
228 < #define SIGSEGV_FAULT_INSTRUCTION               (((ucontext_t *)scp)->uc_mcontext.gregs[14]) /* should use REG_EIP instead */
229 < #define SIGSEGV_REGISTER_FILE                   (unsigned long *)(((ucontext_t *)scp)->uc_mcontext.gregs)
228 > #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.gregs)
229 > #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[14] /* should use REG_EIP instead */
230 > #define SIGSEGV_REGISTER_FILE                   (unsigned int *)SIGSEGV_CONTEXT_REGS
231   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
232   #endif
233 + #if (defined(x86_64) || defined(__x86_64__))
234 + #include <sys/ucontext.h>
235 + #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.gregs)
236 + #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[16] /* should use REG_RIP instead */
237 + #define SIGSEGV_REGISTER_FILE                   (unsigned long *)SIGSEGV_CONTEXT_REGS
238 + #endif
239   #if (defined(ia64) || defined(__ia64__))
240   #define SIGSEGV_FAULT_INSTRUCTION               (((struct sigcontext *)scp)->sc_ip & ~0x3ULL) /* slot number is in bits 0 and 1 */
241   #endif
242   #if (defined(powerpc) || defined(__powerpc__))
243   #include <sys/ucontext.h>
244 < #define SIGSEGV_FAULT_INSTRUCTION               (((ucontext_t *)scp)->uc_mcontext.regs->nip)
244 > #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.regs)
245 > #define SIGSEGV_FAULT_INSTRUCTION               (SIGSEGV_CONTEXT_REGS->nip)
246 > #define SIGSEGV_REGISTER_FILE                   (unsigned int *)&SIGSEGV_CONTEXT_REGS->nip, (unsigned int *)(SIGSEGV_CONTEXT_REGS->gpr)
247 > #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
248   #endif
249   #endif
250   #endif
# Line 92 | Line 258 | static bool sigsegv_do_install_handler(i
258   #define SIGSEGV_FAULT_HANDLER_ARGLIST   int sig, struct sigcontext scs
259   #define SIGSEGV_FAULT_ADDRESS                   scs.cr2
260   #define SIGSEGV_FAULT_INSTRUCTION               scs.eip
261 < #define SIGSEGV_REGISTER_FILE                   (unsigned long *)(&scs)
261 > #define SIGSEGV_REGISTER_FILE                   (unsigned int *)(&scs)
262   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
263   #endif
264   #if (defined(sparc) || defined(__sparc__))
# Line 105 | Line 271 | static bool sigsegv_do_install_handler(i
271   #define SIGSEGV_FAULT_HANDLER_ARGLIST   int sig, struct sigcontext *scp
272   #define SIGSEGV_FAULT_ADDRESS                   scp->regs->dar
273   #define SIGSEGV_FAULT_INSTRUCTION               scp->regs->nip
274 + #define SIGSEGV_REGISTER_FILE                   (unsigned int *)&scp->regs->nip, (unsigned int *)(scp->regs->gpr)
275 + #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
276   #endif
277   #if (defined(alpha) || defined(__alpha__))
278   #include <asm/sigcontext.h>
# Line 158 | Line 326 | static sigsegv_address_t get_fault_addre
326   #if (defined(m68k) || defined(__m68k__))
327   #include <m68k/frame.h>
328   #define SIGSEGV_FAULT_HANDLER_ARGLIST   int sig, int code, struct sigcontext *scp
329 < #define SIGSEGV_FAULT_ADDRESS                   ({                                                                                                                              \
162 <        struct sigstate {                                                                                                                                                                       \
163 <                int ss_flags;                                                                                                                                                                   \
164 <                struct frame ss_frame;                                                                                                                                                  \
165 <        };                                                                                                                                                                                                      \
166 <        struct sigstate *state = (struct sigstate *)scp->sc_ap;                                                                                         \
167 <        char *fault_addr;                                                                                                                                                                       \
168 <        switch (state->ss_frame.f_format) {                                                                                                                                     \
169 <        case 7:         /* 68040 access error */                                                                                                                                \
170 <                /* "code" is sometimes unreliable (i.e. contains NULL or a bogus address), reason unknown */    \
171 <                fault_addr = state->ss_frame.f_fmt7.f_fa;                                                                                                               \
172 <                break;                                                                                                                                                                                  \
173 <        default:                                                                                                                                                                                        \
174 <                fault_addr = (char *)code;                                                                                                                                              \
175 <                break;                                                                                                                                                                                  \
176 <        }                                                                                                                                                                                                       \
177 <        fault_addr;                                                                                                                                                                                     \
178 < })
329 > #define SIGSEGV_FAULT_ADDRESS                   get_fault_address(scp)
330   #define SIGSEGV_ALL_SIGNALS                             FAULT_HANDLER(SIGSEGV)
331 +
332 + // Use decoding scheme from BasiliskII/m68k native
333 + static sigsegv_address_t get_fault_address(struct sigcontext *scp)
334 + {
335 +        struct sigstate {
336 +                int ss_flags;
337 +                struct frame ss_frame;
338 +        };
339 +        struct sigstate *state = (struct sigstate *)scp->sc_ap;
340 +        char *fault_addr;
341 +        switch (state->ss_frame.f_format) {
342 +        case 7:         /* 68040 access error */
343 +                /* "code" is sometimes unreliable (i.e. contains NULL or a bogus address), reason unknown */
344 +                fault_addr = state->ss_frame.f_fmt7.f_fa;
345 +                break;
346 +        default:
347 +                fault_addr = (char *)code;
348 +                break;
349 +        }
350 +        return (sigsegv_address_t)fault_addr;
351 + }
352   #else
353   #define SIGSEGV_FAULT_HANDLER_ARGLIST   int sig, int code, void *scp, char *addr
354   #define SIGSEGV_FAULT_ADDRESS                   addr
# Line 191 | Line 363 | static sigsegv_address_t get_fault_addre
363   #define SIGSEGV_FAULT_ADDRESS                   get_fault_address(scp)
364   #define SIGSEGV_FAULT_INSTRUCTION               scp->sc_ir
365   #define SIGSEGV_ALL_SIGNALS                             FAULT_HANDLER(SIGBUS)
366 + #define SIGSEGV_REGISTER_FILE                   (unsigned int *)&scp->sc_ir, &((unsigned int *) scp->sc_regs)[2]
367 + #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
368  
369 < // From Boehm's GC 6.0alpha8
196 < #define EXTRACT_OP1(iw)     (((iw) & 0xFC000000) >> 26)
197 < #define EXTRACT_OP2(iw)     (((iw) & 0x000007FE) >> 1)
198 < #define EXTRACT_REGA(iw)    (((iw) & 0x001F0000) >> 16)
199 < #define EXTRACT_REGB(iw)    (((iw) & 0x03E00000) >> 21)
200 < #define EXTRACT_REGC(iw)    (((iw) & 0x0000F800) >> 11)
201 < #define EXTRACT_DISP(iw)    ((short *) &(iw))[1]
202 <
369 > // Use decoding scheme from SheepShaver
370   static sigsegv_address_t get_fault_address(struct sigcontext *scp)
371   {
372 <        unsigned int   instr = *((unsigned int *) scp->sc_ir);
373 <        unsigned int * regs = &((unsigned int *) scp->sc_regs)[2];
374 <        int            disp = 0, tmp;
375 <        unsigned int   baseA = 0, baseB = 0;
376 <        unsigned int   addr, alignmask = 0xFFFFFFFF;
377 <
211 <        switch(EXTRACT_OP1(instr)) {
212 <        case 38:   /* stb */
213 <        case 39:   /* stbu */
214 <        case 54:   /* stfd */
215 <        case 55:   /* stfdu */
216 <        case 52:   /* stfs */
217 <        case 53:   /* stfsu */
218 <        case 44:   /* sth */
219 <        case 45:   /* sthu */
220 <        case 47:   /* stmw */
221 <        case 36:   /* stw */
222 <        case 37:   /* stwu */
223 <                tmp = EXTRACT_REGA(instr);
224 <                if(tmp > 0)
225 <                        baseA = regs[tmp];
226 <                disp = EXTRACT_DISP(instr);
227 <                break;
228 <        case 31:
229 <                switch(EXTRACT_OP2(instr)) {
230 <                case 86:    /* dcbf */
231 <                case 54:    /* dcbst */
232 <                case 1014:  /* dcbz */
233 <                case 247:   /* stbux */
234 <                case 215:   /* stbx */
235 <                case 759:   /* stfdux */
236 <                case 727:   /* stfdx */
237 <                case 983:   /* stfiwx */
238 <                case 695:   /* stfsux */
239 <                case 663:   /* stfsx */
240 <                case 918:   /* sthbrx */
241 <                case 439:   /* sthux */
242 <                case 407:   /* sthx */
243 <                case 661:   /* stswx */
244 <                case 662:   /* stwbrx */
245 <                case 150:   /* stwcx. */
246 <                case 183:   /* stwux */
247 <                case 151:   /* stwx */
248 <                case 135:   /* stvebx */
249 <                case 167:   /* stvehx */
250 <                case 199:   /* stvewx */
251 <                case 231:   /* stvx */
252 <                case 487:   /* stvxl */
253 <                        tmp = EXTRACT_REGA(instr);
254 <                        if(tmp > 0)
255 <                                baseA = regs[tmp];
256 <                        baseB = regs[EXTRACT_REGC(instr)];
257 <                        /* determine Altivec alignment mask */
258 <                        switch(EXTRACT_OP2(instr)) {
259 <                        case 167:   /* stvehx */
260 <                                alignmask = 0xFFFFFFFE;
261 <                                break;
262 <                        case 199:   /* stvewx */
263 <                                alignmask = 0xFFFFFFFC;
264 <                                break;
265 <                        case 231:   /* stvx */
266 <                                alignmask = 0xFFFFFFF0;
267 <                                break;
268 <                        case 487:  /* stvxl */
269 <                                alignmask = 0xFFFFFFF0;
270 <                                break;
271 <                        }
272 <                        break;
273 <                case 725:   /* stswi */
274 <                        tmp = EXTRACT_REGA(instr);
275 <                        if(tmp > 0)
276 <                                baseA = regs[tmp];
277 <                        break;
278 <                default:   /* ignore instruction */
279 <                        return 0;
280 <                        break;
281 <                }
282 <                break;
283 <        default:   /* ignore instruction */
284 <                return 0;
285 <                break;
286 <        }
287 <        
288 <        addr = (baseA + baseB) + disp;
289 <        addr &= alignmask;
290 <        return (sigsegv_address_t)addr;
372 >        unsigned int   nip = (unsigned int) scp->sc_ir;
373 >        unsigned int * gpr = &((unsigned int *) scp->sc_regs)[2];
374 >        instruction_t  instr;
375 >
376 >        powerpc_decode_instruction(&instr, nip, gpr);
377 >        return (sigsegv_address_t)instr.addr;
378   }
379   #endif
380   #endif
381   #endif
382  
383 +
384 + /*
385 + *  Instruction skipping
386 + */
387 +
388   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
389   // Decode and skip X86 instruction
390   #if (defined(i386) || defined(__i386__))
# Line 309 | Line 401 | enum {
401          X86_REG_EDI = 4
402   };
403   #endif
404 + #if defined(__NetBSD__) || defined(__FreeBSD__)
405 + enum {
406 +        X86_REG_EIP = 10,
407 +        X86_REG_EAX = 7,
408 +        X86_REG_ECX = 6,
409 +        X86_REG_EDX = 5,
410 +        X86_REG_EBX = 4,
411 +        X86_REG_ESP = 13,
412 +        X86_REG_EBP = 2,
413 +        X86_REG_ESI = 1,
414 +        X86_REG_EDI = 0
415 + };
416 + #endif
417   // FIXME: this is partly redundant with the instruction decoding phase
418   // to discover transfer type and register number
419   static inline int ix86_step_over_modrm(unsigned char * p)
# Line 343 | Line 448 | static inline int ix86_step_over_modrm(u
448          return offset;
449   }
450  
451 < static bool ix86_skip_instruction(sigsegv_address_t fault_instruction, unsigned long * regs)
451 > static bool ix86_skip_instruction(unsigned int * regs)
452   {
453 <        unsigned char * eip = (unsigned char *)fault_instruction;
453 >        unsigned char * eip = (unsigned char *)regs[X86_REG_EIP];
454  
455          if (eip == 0)
456                  return false;
457          
458 <        // Transfer type
459 <        enum {
355 <                TYPE_UNKNOWN,
356 <                TYPE_LOAD,
357 <                TYPE_STORE
358 <        } transfer_type = TYPE_UNKNOWN;
359 <        
360 <        // Transfer size
361 <        enum {
362 <                SIZE_BYTE,
363 <                SIZE_WORD,
364 <                SIZE_LONG
365 <        } transfer_size = SIZE_LONG;
458 >        transfer_type_t transfer_type = TYPE_UNKNOWN;
459 >        transfer_size_t transfer_size = SIZE_LONG;
460          
461          int reg = -1;
462          int len = 0;
# Line 376 | Line 470 | static bool ix86_skip_instruction(sigseg
470  
471          // Decode instruction
472          switch (eip[0]) {
473 +        case 0x0f:
474 +            switch (eip[1]) {
475 +            case 0xb6: // MOVZX r32, r/m8
476 +            case 0xb7: // MOVZX r32, r/m16
477 +                switch (eip[2] & 0xc0) {
478 +                case 0x80:
479 +                    reg = (eip[2] >> 3) & 7;
480 +                    transfer_type = TYPE_LOAD;
481 +                    break;
482 +                case 0x40:
483 +                    reg = (eip[2] >> 3) & 7;
484 +                    transfer_type = TYPE_LOAD;
485 +                    break;
486 +                case 0x00:
487 +                    reg = (eip[2] >> 3) & 7;
488 +                    transfer_type = TYPE_LOAD;
489 +                    break;
490 +                }
491 +                len += 3 + ix86_step_over_modrm(eip + 2);
492 +                break;
493 +            }
494 +          break;
495          case 0x8a: // MOV r8, r/m8
496                  transfer_size = SIZE_BYTE;
497          case 0x8b: // MOV r32, r/m32 (or 16-bit operation)
# Line 463 | Line 579 | static bool ix86_skip_instruction(sigseg
579          return true;
580   }
581   #endif
582 +
583 + // Decode and skip PPC instruction
584 + #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__))
585 + static bool powerpc_skip_instruction(unsigned int * nip_p, unsigned int * regs)
586 + {
587 +        instruction_t instr;
588 +        powerpc_decode_instruction(&instr, *nip_p, regs);
589 +        
590 +        if (instr.transfer_type == TYPE_UNKNOWN) {
591 +                // Unknown machine code, let it crash. Then patch the decoder
592 +                return false;
593 +        }
594 +
595 + #if DEBUG
596 +        printf("%08x: %s %s access", *nip_p,
597 +                   instr.transfer_size == SIZE_BYTE ? "byte" : instr.transfer_size == SIZE_WORD ? "word" : "long",
598 +                   instr.transfer_type == TYPE_LOAD ? "read" : "write");
599 +        
600 +        if (instr.addr_mode == MODE_U || instr.addr_mode == MODE_UX)
601 +                printf(" r%d (ra = %08x)\n", instr.ra, instr.addr);
602 +        if (instr.transfer_type == TYPE_LOAD)
603 +                printf(" r%d (rd = 0)\n", instr.rd);
604 + #endif
605 +        
606 +        if (instr.addr_mode == MODE_U || instr.addr_mode == MODE_UX)
607 +                regs[instr.ra] = instr.addr;
608 +        if (instr.transfer_type == TYPE_LOAD)
609 +                regs[instr.rd] = 0;
610 +        
611 +        *nip_p += 4;
612 +        return true;
613 + }
614 + #endif
615   #endif
616  
617   // Fallbacks
# Line 488 | Line 637 | static void sigsegv_handler(SIGSEGV_FAUL
637          bool fault_recovered = false;
638          
639          // Call user's handler and reinstall the global handler, if required
640 <        if (sigsegv_user_handler(fault_address, fault_instruction)) {
640 >        if (sigsegv_fault_handler(fault_address, fault_instruction)) {
641   #if (defined(HAVE_SIGACTION) ? defined(SIGACTION_NEED_REINSTALL) : defined(SIGNAL_NEED_REINSTALL))
642                  sigsegv_do_install_handler(sig);
643   #endif
# Line 497 | Line 646 | static void sigsegv_handler(SIGSEGV_FAUL
646   #if HAVE_SIGSEGV_SKIP_INSTRUCTION
647          else if (sigsegv_ignore_fault) {
648                  // Call the instruction skipper with the register file available
649 <                if (SIGSEGV_SKIP_INSTRUCTION(fault_instruction, SIGSEGV_REGISTER_FILE))
649 >                if (SIGSEGV_SKIP_INSTRUCTION(SIGSEGV_REGISTER_FILE))
650                          fault_recovered = true;
651          }
652   #endif
# Line 509 | Line 658 | static void sigsegv_handler(SIGSEGV_FAUL
658   #undef FAULT_HANDLER
659                  
660                  // We can't do anything with the fault_address, dump state?
661 <                if (sigsegv_dump_state != 0)
662 <                        sigsegv_dump_state(fault_address, fault_instruction);
661 >                if (sigsegv_state_dumper != 0)
662 >                        sigsegv_state_dumper(fault_address, fault_instruction);
663          }
664   }
665   #endif
# Line 557 | Line 706 | static bool sigsegv_do_install_handler(i
706   }
707   #endif
708  
709 < bool sigsegv_install_handler(sigsegv_handler_t handler)
709 > bool sigsegv_install_handler(sigsegv_fault_handler_t handler)
710   {
711   #ifdef HAVE_SIGSEGV_RECOVERY
712 <        sigsegv_user_handler = handler;
712 >        sigsegv_fault_handler = handler;
713          bool success = true;
714   #define FAULT_HANDLER(sig) success = success && sigsegv_do_install_handler(sig);
715          SIGSEGV_ALL_SIGNALS
# Line 580 | Line 729 | bool sigsegv_install_handler(sigsegv_han
729   void sigsegv_deinstall_handler(void)
730   {
731   #ifdef HAVE_SIGSEGV_RECOVERY
732 <        sigsegv_user_handler = 0;
732 >        sigsegv_fault_handler = 0;
733   #define FAULT_HANDLER(sig) signal(sig, SIG_DFL);
734          SIGSEGV_ALL_SIGNALS
735   #undef FAULT_HANDLER
# Line 602 | Line 751 | void sigsegv_set_ignore_state(bool ignor
751   *  Set callback function when we cannot handle the fault
752   */
753  
754 < void sigsegv_set_dump_state(sigsegv_handler_t handler)
754 > void sigsegv_set_dump_state(sigsegv_state_dumper_t handler)
755   {
756 <        sigsegv_dump_state = handler;
756 >        sigsegv_state_dumper = handler;
757   }
758  
759  
# Line 665 | Line 814 | int main(void)
814          if (!sigsegv_install_handler(sigsegv_insn_handler))
815                  return 1;
816          
817 <        if (vm_protect((char *)page, page_size, VM_PAGE_WRITE) < 0)
817 >        if (vm_protect((char *)page, page_size, VM_PAGE_READ | VM_PAGE_WRITE) < 0)
818                  return 1;
819          
820          for (int i = 0; i < page_size; i++)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines