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.41 by cebix, 2004-01-12T15:29:25Z vs.
Revision 1.45 by gbeauche, 2004-01-21T23:50:06Z

# Line 281 | Line 281 | static void powerpc_decode_instruction(i
281   #undef  SIGSEGV_FAULT_ADDRESS
282   #define SIGSEGV_FAULT_ADDRESS                   sip->si_ptr
283   #endif
284 + #if (defined(arm) || defined(__arm__))
285 + #include <asm/ucontext.h> /* use kernel structure, glibc may not be in sync */
286 + #define SIGSEGV_CONTEXT_REGS                    (((struct ucontext *)scp)->uc_mcontext)
287 + #define SIGSEGV_FAULT_INSTRUCTION               (SIGSEGV_CONTEXT_REGS.arm_pc)
288 + #define SIGSEGV_REGISTER_FILE                   (&SIGSEGV_CONTEXT_REGS.arm_r0)
289 + #define SIGSEGV_SKIP_INSTRUCTION                arm_skip_instruction
290 + #endif
291   #endif
292   #endif
293  
# Line 320 | Line 327 | static void powerpc_decode_instruction(i
327   #define SIGSEGV_FAULT_ADDRESS                   get_fault_address(scp)
328   #define SIGSEGV_FAULT_INSTRUCTION               scp->sc_pc
329   #endif
330 + #if (defined(arm) || defined(__arm__))
331 + #define SIGSEGV_FAULT_HANDLER_ARGLIST   int sig, int r1, int r2, int r3, struct sigcontext sc
332 + #define SIGSEGV_FAULT_HANDLER_ARGLIST_1 struct sigcontext *scp
333 + #define SIGSEGV_FAULT_HANDLER_ARGS              &sc
334 + #define SIGSEGV_FAULT_ADDRESS                   scp->fault_address
335 + #define SIGSEGV_FAULT_INSTRUCTION               scp->arm_pc
336 + #define SIGSEGV_REGISTER_FILE                   &scp->arm_r0
337 + #define SIGSEGV_SKIP_INSTRUCTION                arm_skip_instruction
338 + #endif
339   #endif
340  
341   // Irix 5 or 6 on MIPS
# Line 750 | Line 766 | static bool ix86_skip_instruction(unsign
766   #endif
767  
768          // Decode instruction
769 +        int target_size = SIZE_UNKNOWN;
770          switch (eip[0]) {
771          case 0x0f:
772 +                target_size = transfer_size;
773              switch (eip[1]) {
774 +                case 0xbe: // MOVSX r32, r/m8
775              case 0xb6: // MOVZX r32, r/m8
776 +                        transfer_size = SIZE_BYTE;
777 +                        goto do_mov_extend;
778              case 0xb7: // MOVZX r32, r/m16
779 <                switch (eip[2] & 0xc0) {
780 <                case 0x80:
781 <                    reg = (eip[2] >> 3) & 7;
782 <                    transfer_type = SIGSEGV_TRANSFER_LOAD;
783 <                    break;
784 <                case 0x40:
785 <                    reg = (eip[2] >> 3) & 7;
786 <                    transfer_type = SIGSEGV_TRANSFER_LOAD;
787 <                    break;
788 <                case 0x00:
789 <                    reg = (eip[2] >> 3) & 7;
790 <                    transfer_type = SIGSEGV_TRANSFER_LOAD;
791 <                    break;
792 <                }
793 <                len += 3 + ix86_step_over_modrm(eip + 2);
794 <                break;
779 >                        transfer_size = SIZE_WORD;
780 >                        goto do_mov_extend;
781 >                  do_mov_extend:
782 >                        switch (eip[2] & 0xc0) {
783 >                        case 0x80:
784 >                                reg = (eip[2] >> 3) & 7;
785 >                                transfer_type = SIGSEGV_TRANSFER_LOAD;
786 >                                break;
787 >                        case 0x40:
788 >                                reg = (eip[2] >> 3) & 7;
789 >                                transfer_type = SIGSEGV_TRANSFER_LOAD;
790 >                                break;
791 >                        case 0x00:
792 >                                reg = (eip[2] >> 3) & 7;
793 >                                transfer_type = SIGSEGV_TRANSFER_LOAD;
794 >                                break;
795 >                        }
796 >                        len += 3 + ix86_step_over_modrm(eip + 2);
797 >                        break;
798              }
799            break;
800          case 0x8a: // MOV r8, r/m8
# Line 812 | Line 836 | static bool ix86_skip_instruction(unsign
836                  len += 2 + ix86_step_over_modrm(eip + 1);
837                  break;
838          }
839 +        if (target_size == SIZE_UNKNOWN)
840 +                target_size = transfer_size;
841  
842          if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
843                  // Unknown machine code, let it crash. Then patch the decoder
# Line 839 | Line 865 | static bool ix86_skip_instruction(unsign
865                  // Set 0 to the relevant register part
866                  // NOTE: this is only valid for MOV alike instructions
867                  int rloc = x86_reg_map[reg];
868 <                switch (transfer_size) {
868 >                switch (target_size) {
869                  case SIZE_BYTE:
870                          if (has_rex || reg < 4)
871                                  regs[rloc] = (regs[rloc] & ~0x00ffL);
# Line 1240 | Line 1266 | static bool sparc_skip_instruction(unsig
1266   #endif
1267   #endif
1268  
1269 + // Decode and skip ARM instruction
1270 + #if (defined(arm) || defined(__arm__))
1271 + enum {
1272 + #if (defined(__linux__))
1273 +  ARM_REG_PC = 15,
1274 +  ARM_REG_CPSR = 16
1275 + #endif
1276 + };
1277 + static bool arm_skip_instruction(unsigned long * regs)
1278 + {
1279 +  unsigned int * pc = (unsigned int *)regs[ARM_REG_PC];
1280 +
1281 +  if (pc == 0)
1282 +        return false;
1283 +
1284 + #if DEBUG
1285 +  printf("IP: %p [%08x]\n", pc, pc[0]);
1286 + #endif
1287 +
1288 +  transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
1289 +  transfer_size_t transfer_size = SIZE_UNKNOWN;
1290 +  enum { op_sdt = 1, op_sdth = 2 };
1291 +  int op = 0;
1292 +
1293 +  // Handle load/store instructions only
1294 +  const unsigned int opcode = pc[0];
1295 +  switch ((opcode >> 25) & 7) {
1296 +  case 0: // Halfword and Signed Data Transfer (LDRH, STRH, LDRSB, LDRSH)
1297 +        op = op_sdth;
1298 +        // Determine transfer size (S/H bits)
1299 +        switch ((opcode >> 5) & 3) {
1300 +        case 0: // SWP instruction
1301 +          break;
1302 +        case 1: // Unsigned halfwords
1303 +        case 3: // Signed halfwords
1304 +          transfer_size = SIZE_WORD;
1305 +          break;
1306 +        case 2: // Signed byte
1307 +          transfer_size = SIZE_BYTE;
1308 +          break;
1309 +        }
1310 +        break;
1311 +  case 2:
1312 +  case 3: // Single Data Transfer (LDR, STR)
1313 +        op = op_sdt;
1314 +        // Determine transfer size (B bit)
1315 +        if (((opcode >> 22) & 1) == 1)
1316 +          transfer_size = SIZE_BYTE;
1317 +        else
1318 +          transfer_size = SIZE_LONG;
1319 +        break;
1320 +  default:
1321 +        // FIXME: support load/store mutliple?
1322 +        return false;
1323 +  }
1324 +
1325 +  // Check for invalid transfer size (SWP instruction?)
1326 +  if (transfer_size == SIZE_UNKNOWN)
1327 +        return false;
1328 +
1329 +  // Determine transfer type (L bit)
1330 +  if (((opcode >> 20) & 1) == 1)
1331 +        transfer_type = SIGSEGV_TRANSFER_LOAD;
1332 +  else
1333 +        transfer_type = SIGSEGV_TRANSFER_STORE;
1334 +
1335 +  // Compute offset
1336 +  int offset;
1337 +  if (((opcode >> 25) & 1) == 0) {
1338 +        if (op == op_sdt)
1339 +          offset = opcode & 0xfff;
1340 +        else if (op == op_sdth) {
1341 +          int rm = opcode & 0xf;
1342 +          if (((opcode >> 22) & 1) == 0) {
1343 +                // register offset
1344 +                offset = regs[rm];
1345 +          }
1346 +          else {
1347 +                // immediate offset
1348 +                offset = ((opcode >> 4) & 0xf0) | (opcode & 0x0f);
1349 +          }
1350 +        }
1351 +  }
1352 +  else {
1353 +        const int rm = opcode & 0xf;
1354 +        const int sh = (opcode >> 7) & 0x1f;
1355 +        if (((opcode >> 4) & 1) == 1) {
1356 +          // we expect only legal load/store instructions
1357 +          printf("FATAL: invalid shift operand\n");
1358 +          return false;
1359 +        }
1360 +        const unsigned int v = regs[rm];
1361 +        switch ((opcode >> 5) & 3) {
1362 +        case 0: // logical shift left
1363 +          offset = sh ? v << sh : v;
1364 +          break;
1365 +        case 1: // logical shift right
1366 +          offset = sh ? v >> sh : 0;
1367 +          break;
1368 +        case 2: // arithmetic shift right
1369 +          if (sh)
1370 +                offset = ((signed int)v) >> sh;
1371 +          else
1372 +                offset = (v & 0x80000000) ? 0xffffffff : 0;
1373 +          break;
1374 +        case 3: // rotate right
1375 +          if (sh)
1376 +                offset = (v >> sh) | (v << (32 - sh));
1377 +          else
1378 +                offset = (v >> 1) | ((regs[ARM_REG_CPSR] << 2) & 0x80000000);
1379 +          break;
1380 +        }
1381 +  }
1382 +  if (((opcode >> 23) & 1) == 0)
1383 +        offset = -offset;
1384 +
1385 +  int rd = (opcode >> 12) & 0xf;
1386 +  int rn = (opcode >> 16) & 0xf;
1387 + #if DEBUG
1388 +  static const char * reg_names[] = {
1389 +        "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1390 +        "r9", "r9", "sl", "fp", "ip", "sp", "lr", "pc"
1391 +  };
1392 +  printf("%s %s register %s\n",
1393 +                 transfer_size == SIZE_BYTE ? "byte" :
1394 +                 transfer_size == SIZE_WORD ? "word" :
1395 +                 transfer_size == SIZE_LONG ? "long" : "unknown",
1396 +                 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
1397 +                 reg_names[rd]);
1398 + #endif
1399 +
1400 +  unsigned int base = regs[rn];
1401 +  if (((opcode >> 24) & 1) == 1)
1402 +        base += offset;
1403 +
1404 +  if (transfer_type == SIGSEGV_TRANSFER_LOAD)
1405 +        regs[rd] = 0;
1406 +
1407 +  if (((opcode >> 24) & 1) == 0)                // post-index addressing
1408 +        regs[rn] += offset;
1409 +  else if (((opcode >> 21) & 1) == 1)   // write-back address into base
1410 +        regs[rn] = base;
1411 +
1412 +  regs[ARM_REG_PC] += 4;
1413 +  return true;
1414 + }
1415 + #endif
1416 +
1417 +
1418   // Fallbacks
1419   #ifndef SIGSEGV_FAULT_INSTRUCTION
1420   #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_INVALID_PC
# Line 1295 | Line 1470 | static bool handle_badaccess(SIGSEGV_FAU
1470                  }
1471                  break;
1472   #endif
1473 +        case SIGSEGV_RETURN_FAILURE:
1474 +                return false;
1475          }
1476          
1477          // We can't do anything with the fault_address, dump state?
# Line 1697 | Line 1874 | static sigsegv_return_t sigsegv_test_han
1874   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1875   static sigsegv_return_t sigsegv_insn_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
1876   {
1877 + #if DEBUG
1878 +        printf("sigsegv_insn_handler(%p, %p)\n", fault_address, instruction_address);
1879 + #endif
1880          if (((unsigned long)fault_address - (unsigned long)page) < page_size) {
1881   #ifdef __GNUC__
1882                  // Make sure reported fault instruction address falls into
# Line 1831 | Line 2011 | int main(void)
2011          TEST_SKIP_INSTRUCTION(unsigned short);
2012          TEST_SKIP_INSTRUCTION(unsigned int);
2013          TEST_SKIP_INSTRUCTION(unsigned long);
2014 +        TEST_SKIP_INSTRUCTION(signed char);
2015 +        TEST_SKIP_INSTRUCTION(signed short);
2016 +        TEST_SKIP_INSTRUCTION(signed int);
2017 +        TEST_SKIP_INSTRUCTION(signed long);
2018   L_e_region2:
2019  
2020          if (!arch_insn_skipper_tests())

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines