Subversion Repositories HelenOS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2008 Jiri Svoboda
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup debug
  30.  * @{
  31.  */
  32. /** @file
  33.  */
  34.  
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <assert.h>
  38. #include <sys/types.h>
  39. #include <errno.h>
  40. #include <udebug.h>
  41.  
  42. #include "../../../cons.h"
  43. #include "../../../main.h"
  44. #include "../../../breakpoint.h"
  45. #include "../../../include/arch.h"
  46. #include "../../../include/arch/arch.h"
  47. #include "../../../genarch/idec/idec.h"
  48.  
  49. static istate_t istate;
  50.  
  51. typedef enum {
  52.     /* Branch */
  53.     OP_B,
  54.     OP_BL,
  55.     OP_BLX1,
  56.     OP_BLX2,
  57.     OP_BX
  58. } op_t;
  59.  
  60. typedef struct {
  61.     uint32_t mask;
  62.     uint32_t value;
  63.     op_t op;
  64. } instr_desc_t;
  65.  
  66. static instr_desc_t decoding_table[] = {
  67.     /* Unconditional branch (link) and exchange */
  68.     { 0xfe000000, 0xfa000000, OP_BLX1 },
  69.     { 0x0ffffff0, 0x012fff30, OP_BLX2 },
  70.     { 0x0ffffff0, 0x012fff10, OP_BX },
  71.  
  72.     /*
  73.      * Order is significant here, as the condition code for B, BL
  74.      * (the top 4 bits) must not be 0xf, which is caught by BLX, BX
  75.      */
  76.  
  77.     /* Branch (and link) */
  78.     { 0x0f000000, 0x0a000000, OP_B },
  79.     { 0x0f000000, 0x0b000000, OP_BL },
  80.  
  81.     { 0, 0, -1 }
  82. };
  83.  
  84. /** Sign-extend a value to 32 bits.
  85.  *
  86.  * @param val   A signed value (of limited width)
  87.  * @param bits  Bit-width of value.
  88.  * @return The value extended to a 32-bit signed integer.
  89.  */
  90. #define EXTS(val, bits) ((int32_t)(val) << (32 - (bits)) >> (32 - (bits)))
  91.  
  92. void arch_dthread_initialize(dthread_t *dt)
  93. {
  94.     dt->arch.singlestep = false;
  95.  
  96.     bstore_initialize(&dt->arch.cur);
  97.     bstore_initialize(&dt->arch.next[0]);
  98.     bstore_initialize(&dt->arch.next[1]);
  99. }
  100.  
  101. int arch_breakpoint_set(breakpoint_t *b)
  102. {
  103.     int rc;
  104.  
  105.     rc = idec_breakpoint_set(b);
  106.     if (rc != 0) return rc;
  107.  
  108.     return 0;
  109. }
  110.  
  111. int arch_breakpoint_remove(breakpoint_t *b)
  112. {
  113.     return idec_breakpoint_remove(b);
  114. }
  115.  
  116. static int islot_read(uintptr_t addr, uint32_t *instr)
  117. {
  118.     int rc;
  119.  
  120.     rc = udebug_mem_read(app_phone, instr, addr, sizeof(uint32_t));
  121.     if (rc != EOK) {
  122.         cons_printf("Error reading memory address 0x%zx\n", addr);
  123.     }
  124.  
  125.     return rc;
  126. }
  127.  
  128. static int get_reg(dthread_t *dt, int reg_no, uint32_t *value)
  129. {
  130.     int rc;
  131.  
  132.     cons_printf("get_reg...\n");
  133.  
  134.     if (reg_no == 0) {
  135.         *value = 0;
  136.         return 0;
  137.     }
  138.  
  139.     rc = udebug_regs_read(app_phone, dt->hash, &istate);
  140.     if (rc < 0) return rc;
  141.  
  142.     switch (reg_no) {
  143.  
  144.     case 0: *value = istate.r0; break;
  145.     case 1: *value = istate.r1; break;
  146.     case 2: *value = istate.r2; break;
  147.     case 3: *value = istate.r3; break;
  148.     case 4: *value = istate.r4; break;
  149.     case 5: *value = istate.r5; break;
  150.     case 6: *value = istate.r6; break;
  151.     case 7: *value = istate.r7; break;
  152.     case 8: *value = istate.r8; break;
  153.     case 9: *value = istate.r9; break;
  154.     case 10: *value = istate.r10; break;
  155.     case 11: *value = istate.r11; break;
  156.     case 12: *value = istate.r12; break;
  157.     case 13: *value = istate.sp; break;
  158.     case 14: *value = istate.lr; break;
  159.     case 15: *value = istate.pc; break;
  160.  
  161.     }
  162.     printf("get_reg ok (0x%08x)\n", *value);
  163.  
  164.     return 0;
  165. }
  166.  
  167. static op_t instr_decode(uint32_t instr)
  168. {
  169.     instr_desc_t *idesc;
  170.  
  171.     idesc = &decoding_table[0];
  172.     while (idesc->op >= 0) {
  173.         if ((instr & idesc->mask) == idesc->value)
  174.             return idesc->op;
  175.         ++idesc;
  176.     }
  177.  
  178.     return -1;
  179. }
  180.  
  181. /** Get address of the instruction that will be executed after the current one.
  182.  *
  183.  * Assumptions: addr == PC, *addr is not covered by a BREAK.
  184.  *
  185.  * @param dt        Dthread on which to operate.
  186.  * @param addr      Address of an instruction.
  187.  * @param buffer    Buffer for storing up to 2 addresses.
  188.  * @return      Number of stored addresses or negative error code.
  189.  */
  190. int get_next_addr(dthread_t *dt, uintptr_t addr, uintptr_t *buffer)
  191. {
  192.     uint32_t instr;
  193.     int32_t imm, h;
  194.     uint32_t regv;
  195.     op_t op;
  196.     int rc;
  197.     int n;
  198.  
  199.     rc = islot_read(addr, &instr);
  200.     if (rc != 0) return rc;
  201.  
  202.     op = instr_decode(instr);
  203.  
  204.     switch (op) {
  205.     /* Branch (and link) */
  206.     case OP_B:
  207.     case OP_BL:
  208.         /* imm is a 24-bit signed integer */
  209.         imm = EXTS(instr & 0x00ffffff, 24);
  210.         buffer[0] = (addr + 8) + (imm << 2);
  211.         buffer[1] = addr + 4;
  212.         n = 2;
  213.         break;
  214.  
  215.     /* Unconditional branch, link and exchange */
  216.     case OP_BLX1:
  217.         /* imm is a 24-bit signed integer */
  218.         imm = EXTS(instr & 0x00ffffff, 24);
  219.         h = (instr & 0x01000000) ? 1 : 0;
  220.         buffer[0] = (addr + 8) + (imm << 2) + (h << 1);
  221.         n = 1;
  222.         break;
  223.  
  224.     case OP_BLX2:
  225.     case OP_BX:
  226.         /* BLX (2), BX */
  227.         rc = get_reg(dt, instr & 0xf, &regv);
  228.         if (rc != 0) return rc;
  229.  
  230.         buffer[0] = regv & ~0x1;
  231.         buffer[1] = addr + 4;
  232.         n = 2;
  233.         break;
  234.  
  235.     /* TODO: handle instructions writing r15 */
  236.  
  237.     default:
  238.         /* Regular instruction */  
  239.         buffer[0] = addr + 4;
  240.         n = 1;
  241.         break;
  242.     }
  243.  
  244.     return n;
  245. }
  246.  
  247. void arch_event_breakpoint(thash_t thread_hash)
  248. {
  249.     idec_event_breakpoint(thread_hash);
  250. }
  251.  
  252. void arch_event_trap(dthread_t *dt)
  253. {
  254.     /* Unused */
  255.     (void)dt;
  256. }
  257.  
  258. void arch_dump_regs(thash_t thash)
  259. {
  260.     /* TODO */
  261. }
  262.  
  263. void arch_singlestep(dthread_t *dt)
  264. {
  265.     idec_singlestep(dt);
  266. }
  267.  
  268. /** @}
  269.  */
  270.