Subversion Repositories HelenOS

Rev

Blame | 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_BA,
  55.     OP_BL,
  56.     OP_BLA,
  57.  
  58.     /* Branch conditional */
  59.     OP_BC,
  60.     OP_BCA,
  61.     OP_BCL,
  62.     OP_BCLA,
  63.  
  64.     /* Branch conditional to counter register */
  65.     OP_BCCTR,
  66.     OP_BCCTRL,
  67.  
  68.     /* Branch conditional to link register */
  69.     OP_BCLR,
  70.     OP_BCLRL
  71. } op_t;
  72.  
  73. typedef struct {
  74.     uint32_t mask;
  75.     uint32_t value;
  76.     op_t op;
  77. } instr_desc_t;
  78.  
  79. static instr_desc_t decoding_table[] = {
  80.     { 0xfc000003, 0x48000000, OP_B },
  81.     { 0xfc000003, 0x48000002, OP_BA },
  82.     { 0xfc000003, 0x48000001, OP_BL },
  83.     { 0xfc000003, 0x48000003, OP_BLA },
  84.  
  85.     { 0xfc000003, 0x40000000, OP_BC },
  86.     { 0xfc000003, 0x40000002, OP_BCA },
  87.     { 0xfc000003, 0x40000001, OP_BCL },
  88.     { 0xfc000003, 0x40000003, OP_BCLA },
  89.  
  90.     { 0xfc00ffff, 0x4c000420, OP_BCCTR },
  91.     { 0xfc00ffff, 0x4c000421, OP_BCCTRL },
  92.  
  93.     { 0xfc00ffff, 0x4c000020, OP_BCLR },
  94.     { 0xfc00ffff, 0x4c000021, OP_BCLRL },
  95.  
  96.     { 0, 0, -1 }
  97. };
  98.  
  99. /** Sign-extend a value to 32 bits.
  100.  *
  101.  * @param val   A signed value (of limited width)
  102.  * @param bits  Bit-width of value.
  103.  * @return The value extended to a 32-bit signed integer.
  104.  */
  105. #define EXTS(val, bits) ((int32_t)(val) << (32 - (bits)) >> (32 - (bits)))
  106.  
  107. /** (opcode mask) Branch instruction uses absolute address */
  108. #define MASK_AA 0x00000002
  109. /** (opcode mask) Branch instruction saves PC to the link register */
  110. #define MASK_LK 0x00000001
  111.  
  112. void arch_dthread_initialize(dthread_t *dt)
  113. {
  114.     dt->arch.singlestep = false;
  115.  
  116.     bstore_initialize(&dt->arch.cur);
  117.     bstore_initialize(&dt->arch.next[0]);
  118.     bstore_initialize(&dt->arch.next[1]);
  119. }
  120.  
  121. int arch_breakpoint_set(breakpoint_t *b)
  122. {
  123.     int rc;
  124.  
  125.     cons_printf("break=0x%x\n", OPCODE_BREAK);
  126.     rc = idec_breakpoint_set(b);
  127.     if (rc != 0) return rc;
  128.  
  129.     return 0;
  130. }
  131.  
  132. int arch_breakpoint_remove(breakpoint_t *b)
  133. {
  134.     return idec_breakpoint_remove(b);
  135. }
  136.  
  137. static int islot_read(uintptr_t addr, uint32_t *instr)
  138. {
  139.     int rc;
  140.  
  141.     rc = udebug_mem_read(app_phone, instr, addr, sizeof(uint32_t));
  142.     if (rc != EOK) {
  143.         cons_printf("Error reading memory address 0x%zx\n", addr);
  144.     }
  145.  
  146.     return rc;
  147. }
  148.  
  149. static op_t instr_decode(uint32_t instr)
  150. {
  151.     instr_desc_t *idesc;
  152.  
  153.     idesc = &decoding_table[0];
  154.     while (idesc->op >= 0) {
  155.         if ((instr & idesc->mask) == idesc->value)
  156.             return idesc->op;
  157.         ++idesc;
  158.     }
  159.  
  160.     return -1;
  161. }
  162.  
  163. static int get_ctr(dthread_t *dt, uint32_t *value)
  164. {
  165.     int rc;
  166.  
  167.     rc = udebug_regs_read(app_phone, dt->hash, &istate);
  168.     if (rc < 0) return rc;
  169.  
  170.     *value = istate.ctr;
  171.     printf("get_ctr ok (0x%08x)\n", *value);
  172.  
  173.     return 0;
  174. }
  175.  
  176. static int get_lr(dthread_t *dt, uint32_t *value)
  177. {
  178.     int rc;
  179.  
  180.     rc = udebug_regs_read(app_phone, dt->hash, &istate);
  181.     if (rc < 0) return rc;
  182.  
  183.     *value = istate.lr;
  184.     printf("get_lr ok (0x%08x)\n", *value);
  185.  
  186.     return 0;
  187. }
  188.  
  189. /** Get address of the instruction that will be executed after the current one.
  190.  *
  191.  * Assumptions: addr == PC, *addr is not covered by a BREAK.
  192.  *
  193.  * @param dt        Dthread on which to operate.
  194.  * @param addr      Address of an instruction.
  195.  * @param buffer    Buffer for storing up to 2 addresses.
  196.  * @return      Number of stored addresses or negative error code.
  197.  */
  198. int get_next_addr(dthread_t *dt, uintptr_t addr, uintptr_t *buffer)
  199. {
  200.     uint32_t instr;
  201.     int32_t li;
  202.     int32_t bd;
  203.     uint32_t ctr, lr;
  204.     op_t op;
  205.     int rc;
  206.     int n;
  207.  
  208.     rc = islot_read(addr, &instr);
  209.     if (rc != 0) return rc;
  210.  
  211.     op = instr_decode(instr);
  212.  
  213.     switch (op) {
  214.     /* Branch (Bx) */
  215.     case OP_B:
  216.     case OP_BA:
  217.     case OP_BL:
  218.     case OP_BLA:
  219.         /* LI is a 26-bit signed integer */
  220.         li = EXTS(instr & 0x03fffffc, 26);
  221.         if (instr & MASK_AA)
  222.             buffer[0] = li;
  223.         else
  224.             buffer[0] = addr + li;
  225.         n = 1;
  226.         break;
  227.  
  228.     /* Branch conditional (BCx) */
  229.     case OP_BC:
  230.     case OP_BCA:
  231.     case OP_BCL:
  232.     case OP_BCLA:
  233.         /* BD is a 16-bit signed integer */
  234.         bd = EXTS(instr & 0x0000fffc, 16);
  235.         if (instr & MASK_AA)
  236.             buffer[0] = bd;
  237.         else
  238.             buffer[0] = addr + bd;
  239.  
  240.         buffer[1] = addr + 4;   /* not taken */
  241.         n = 2;
  242.         break;
  243.  
  244.     /* Branch conditional to counter register (BCCTRx) */
  245.     case OP_BCCTR:
  246.     case OP_BCCTRL:
  247.         rc = get_ctr(dt, &ctr);
  248.         if (rc != 0) return rc;
  249.  
  250.         buffer[0] = ctr & ~0x00000003;
  251.         buffer[1] = addr + 4;   /* not taken */
  252.         n = 2;
  253.         break;
  254.  
  255.     /* Branch conditional to link register (BCLRx) */
  256.     case OP_BCLR:
  257.     case OP_BCLRL:
  258.         rc = get_lr(dt, &lr);
  259.         if (rc != 0) return rc;
  260.    
  261.         buffer[0] = lr & ~0x00000003;
  262.         buffer[1] = addr + 4;   /* not taken */
  263.         n = 2;
  264.         break;
  265.  
  266.     default:
  267.         /* Regular instruction */  
  268.         buffer[0] = addr + 4;
  269.         n = 1;
  270.         break;
  271.     }
  272.  
  273.     return n;
  274. }
  275.  
  276. void arch_event_breakpoint(thash_t thread_hash)
  277. {
  278.     idec_event_breakpoint(thread_hash);
  279. }
  280.  
  281. void arch_event_trap(dthread_t *dt)
  282. {
  283.     /* Unused */
  284.     (void)dt;
  285. }
  286.  
  287. void arch_dump_regs(thash_t thash)
  288. {
  289.     /* TODO */
  290. }
  291.  
  292. void arch_singlestep(dthread_t *dt)
  293. {
  294.     idec_singlestep(dt);
  295. }
  296.  
  297. /** @}
  298.  */
  299.