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.23 by gbeauche, 2003-08-17T10:52:52Z vs.
Revision 1.24 by gbeauche, 2003-09-29T07:02:58Z

# Line 45 | Line 45 | using std::list;
45   // Type of the system signal handler
46   typedef RETSIGTYPE (*signal_handler)(int);
47  
48 // Ignore range chain
49 struct ignore_range_t {
50        sigsegv_address_t       start;
51        unsigned long           length;
52        int                                     transfer_type;
53 };
54
55 typedef list<ignore_range_t> ignore_range_list_t;
56 ignore_range_list_t sigsegv_ignore_ranges;
57
48   // User's SIGSEGV handler
49   static sigsegv_fault_handler_t sigsegv_fault_handler = 0;
50  
# Line 64 | Line 54 | static sigsegv_state_dumper_t sigsegv_st
54   // Actual SIGSEGV handler installer
55   static bool sigsegv_do_install_handler(int sig);
56  
67 // Find ignore range matching address
68 static inline ignore_range_list_t::iterator sigsegv_find_ignore_range(sigsegv_address_t address)
69 {
70        ignore_range_list_t::iterator it;
71        for (it = sigsegv_ignore_ranges.begin(); it != sigsegv_ignore_ranges.end(); it++)
72                if (address >= it->start && address < it->start + it->length)
73                        break;
74        return it;
75 }
76
57  
58   /*
59   *  Instruction decoding aids
# Line 610 | Line 590 | static bool powerpc_skip_instruction(uns
590                  return false;
591          }
592  
613        ignore_range_list_t::iterator it = sigsegv_find_ignore_range((sigsegv_address_t)instr.addr);
614        if (it == sigsegv_ignore_ranges.end() || ((it->transfer_type & instr.transfer_type) != instr.transfer_type)) {
615                // Address doesn't fall into ignore ranges list, let it crash.
616                return false;
617        }
618
593   #if DEBUG
594          printf("%08x: %s %s access", *nip_p,
595                     instr.transfer_size == SIZE_BYTE ? "byte" : instr.transfer_size == SIZE_WORD ? "word" : "long",
# Line 661 | Line 635 | static void sigsegv_handler(SIGSEGV_FAUL
635          bool fault_recovered = false;
636          
637          // Call user's handler and reinstall the global handler, if required
638 <        if (sigsegv_fault_handler(fault_address, fault_instruction)) {
638 >        switch (sigsegv_fault_handler(fault_address, fault_instruction)) {
639 >        case SIGSEGV_RETURN_SUCCESS:
640   #if (defined(HAVE_SIGACTION) ? defined(SIGACTION_NEED_REINSTALL) : defined(SIGNAL_NEED_REINSTALL))
641                  sigsegv_do_install_handler(sig);
642   #endif
643                  fault_recovered = true;
644 <        }
644 >                break;
645   #if HAVE_SIGSEGV_SKIP_INSTRUCTION
646 <        else if (sigsegv_ignore_ranges.size() > 0) {
646 >        case SIGSEGV_RETURN_SKIP_INSTRUCTION:
647                  // Call the instruction skipper with the register file available
648                  if (SIGSEGV_SKIP_INSTRUCTION(SIGSEGV_REGISTER_FILE))
649                          fault_recovered = true;
650 <        }
650 >                break;
651   #endif
652 +        }
653  
654          if (!fault_recovered) {
655 <                // FAIL: reinstall default handler for "safe" crash
655 >                // Failure: reinstall default handler for "safe" crash
656   #define FAULT_HANDLER(sig) signal(sig, SIG_DFL);
657                  SIGSEGV_ALL_SIGNALS
658   #undef FAULT_HANDLER
# Line 761 | Line 737 | void sigsegv_deinstall_handler(void)
737  
738  
739   /*
764 *  Add SIGSEGV ignore range
765 */
766
767 void sigsegv_add_ignore_range(sigsegv_address_t address, unsigned long length, int transfer_type)
768 {
769        ignore_range_t ignore_range;
770        ignore_range.start = address;
771        ignore_range.length = length;
772        ignore_range.transfer_type = transfer_type;
773        sigsegv_ignore_ranges.push_front(ignore_range);
774 }
775
776
777 /*
778 *  Remove SIGSEGV ignore range. Range must match installed one, otherwise FALSE is returned.
779 */
780
781 bool sigsegv_remove_ignore_range(sigsegv_address_t address, unsigned long length, int transfer_type)
782 {
783        ignore_range_list_t::iterator it;
784        for (it = sigsegv_ignore_ranges.begin(); it != sigsegv_ignore_ranges.end(); it++)
785                if (it->start == address && it->length == length && ((it->transfer_type & transfer_type) == transfer_type))
786                        break;
787
788        if (it != sigsegv_ignore_ranges.end()) {
789                if (it->transfer_type != transfer_type)
790                        it->transfer_type &= ~transfer_type;
791                else
792                        sigsegv_ignore_ranges.erase(it);
793                return true;
794        }
795
796        return false;
797 }
798
799
800 /*
740   *  Set callback function when we cannot handle the fault
741   */
742  
# Line 822 | Line 761 | static int page_size;
761   static volatile char * page = 0;
762   static volatile int handler_called = 0;
763  
764 < static bool sigsegv_test_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
764 > static sigsegv_return_t sigsegv_test_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
765   {
766          handler_called++;
767          if ((fault_address - 123) != page)
768                  exit(1);
769          if (vm_protect((char *)((unsigned long)fault_address & -page_size), page_size, VM_PAGE_READ | VM_PAGE_WRITE) != 0)
770                  exit(1);
771 <        return true;
771 >        return SIGSEGV_RETURN_SUCCESS;
772   }
773  
774   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
775 < static bool sigsegv_insn_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
775 > static sigsegv_return_t sigsegv_insn_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
776   {
777 <        return false;
777 >        if (((unsigned long)fault_address - (unsigned long)page) < page_size)
778 >                return SIGSEGV_SRETURN_KIP_INSTRUCTION;
779 >        return SIGSEGV_RETURN_FAILURE;
780   }
781   #endif
782  
# Line 873 | Line 814 | int main(void)
814          if (vm_protect((char *)page, page_size, VM_PAGE_NOACCESS) < 0)
815                  return 1;
816          
876        sigsegv_add_ignore_range((char *)page, page_size, SIGSEGV_TRANSFER_LOAD | SIGSEGV_TRANSFER_STORE);
877
817   #define TEST_SKIP_INSTRUCTION(TYPE) do {                                \
818                  const unsigned int TAG = 0x12345678;                    \
819                  TYPE data = *((TYPE *)(page + sizeof(TYPE)));   \

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines