Subversion Repositories HelenOS

Rev

Rev 3012 | Rev 3099 | 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 <udebug.h>
  40.  
  41. #include "../../../cons.h"
  42. #include "../../../main.h"
  43. #include "../../../breakpoint.h"
  44. #include "../../../include/arch.h"
  45.  
  46. #define OPCODE_BREAK        0x0000000d
  47.  
  48. static istate_t istate;
  49.  
  50. int arch_breakpoint_set(breakpoint_t *b)
  51. {
  52.     return bstore_push(&b->arch.bs, b->addr, OPCODE_BREAK);
  53. }
  54.  
  55. int arch_breakpoint_remove(breakpoint_t *b)
  56. {
  57.     return bstore_pop(&b->arch.bs);
  58. }
  59.  
  60. static void _ev_breakpoint(thash_t thread_hash)
  61. {
  62.     breakpoint_t *b;
  63.     dthread_t *dt;
  64.     int rc;
  65.     uint32_t epc;
  66.     int brk_addr;
  67.     uint32_t brkp;
  68.  
  69.     brkp = OPCODE_BREAK;
  70.  
  71.     cons_printf("arch_event_breakpoint\n");
  72.  
  73.     rc = udebug_regs_read(app_phone, thread_hash, &istate);
  74.     cons_printf("udebug_regs_read -> %d\n", rc);
  75.     epc = istate_get_pc(&istate);
  76.     cons_printf("EPC was 0x%08x\n", epc);
  77.     brk_addr = epc;
  78.  
  79.     dt = dthread_get();
  80.  
  81.     if (active_bkpt != NULL) {
  82.         assert(active_bkpt->arch.bs.address == brk_addr);
  83.  
  84.         /* A breakpoint-clearing BRK has been hit */
  85.         cons_printf("restoring breakpoint %d\n", b->id);
  86.         rc = bstore_pop(&b->arch.bs);
  87.         if (rc != 0) return;
  88.         rc = bstore_push(&b->arch.bs, brk_addr - 4, OPCODE_BREAK);
  89.         if (rc != 0) return;
  90.         active_bkpt = NULL;
  91.         return;
  92.     }
  93.  
  94.     b = breakpoint_find_by_addr(brk_addr);
  95.     if (b == NULL) {
  96.         cons_printf("Unrecognized breakpoint at 0x%lx\n", brk_addr);
  97.     }
  98.  
  99.     /* A breakpoint has been hit */
  100.     cons_printf("breakpoint_hit...\n");
  101.     breakpoint_hit(b);
  102.  
  103.     /* While in breakpoint_hit(), singlestep was activated */
  104.     if (dt->arch.singlestep) return;
  105.  
  106.     cons_printf("move breakpoint\b");
  107.     rc = bstore_pop(&b->arch.bs);
  108.     if (rc != 0) return;
  109.  
  110.     /*
  111.      * There could be another breakpoint at brk_addr + 4,
  112.      * but that's okay. We'll pop the active breakpoint bs
  113.      * before doing anything else.
  114.      */
  115.     rc = bstore_push(&b->arch.bs, brk_addr + 4, OPCODE_BREAK);
  116.     if (rc != 0) return;
  117.  
  118.     active_bkpt = b;
  119.     b->active = true;
  120.  
  121.     cons_printf("end_hit...\n");
  122. }
  123.  
  124.  
  125. static void _ev_singlestep(thash_t thread_hash)
  126. {
  127.     dthread_t *dt;
  128.     int rc;
  129.     uint32_t epc;
  130.     int brk_addr;
  131.     uint32_t brkp;
  132.  
  133.     dt = dthread_get();
  134.  
  135.     assert(active_bkpt == NULL);
  136.     assert(dt->arch.singlestep);
  137.     brkp = OPCODE_BREAK;
  138.  
  139.     cons_printf("arch_event_breakpoint\n");
  140.  
  141.     rc = udebug_regs_read(app_phone, thread_hash, &istate);
  142.     cons_printf("udebug_regs_read -> %d\n", rc);
  143.     epc = istate_get_pc(&istate);
  144.     cons_printf("EPC was 0x%08x\n", epc);
  145.     brk_addr = epc;
  146.  
  147.     if (dt->arch.cur.valid) {
  148.         cons_printf("restore breakpoint BRK\n");
  149.         rc = bstore_pop(&dt->arch.cur);
  150.     }
  151.  
  152.     cons_printf("clear singlestep BRK\n");
  153.     rc = bstore_pop(&dt->arch.next);
  154.  
  155.     dt->arch.singlestep = false;
  156.  
  157.     singlestep_hit();
  158. }
  159.  
  160.  
  161. void arch_event_breakpoint(thash_t thread_hash)
  162. {
  163.     dthread_t *dt;
  164.  
  165.     dt = dthread_get();
  166.     if (dt->arch.singlestep) {
  167.         _ev_singlestep(thread_hash);
  168.     } else {
  169.         _ev_breakpoint(thread_hash);
  170.     }
  171. }
  172.  
  173. void arch_event_trap(dthread_t *dt)
  174. {
  175.     /* Unused */
  176.     (void)dt;
  177. }
  178.  
  179. void arch_dump_regs(thash_t thash)
  180. {
  181.     /* TODO */
  182. }
  183.  
  184. void arch_singlestep(dthread_t *dt)
  185. {
  186.     int rc;
  187.     uint32_t epc;
  188.     breakpoint_t *b;
  189.     uint32_t old_instr;
  190.  
  191.     assert(active_bkpt == NULL);
  192.     assert(dt->arch.singlestep == false);
  193.  
  194.     cons_printf("arch_singlestep(dt)\n");
  195.     rc = udebug_regs_read(app_phone, dt->hash, &istate);
  196.     cons_printf("udebug_regs_read -> %d\n", rc);
  197.     epc = istate_get_pc(&istate);
  198.     cons_printf("EPC was 0x%08x\n", epc);
  199.  
  200.     cons_printf("initial set singlestep\n");
  201.     b = breakpoint_find_by_addr(epc);
  202.     if (b != NULL) {
  203.         /* Cover breakpoint with old instruction */
  204.         old_instr = b->arch.bs.value;
  205.         rc = bstore_push(&dt->arch.cur, epc, old_instr);
  206.         if (rc < 0) return;
  207.     }
  208.  
  209.     /* Cover next instruction with BREAK */
  210.     rc = bstore_push(&dt->arch.next, epc + 4, OPCODE_BREAK);
  211.     if (rc < 0) return;
  212.  
  213.     dt->arch.singlestep = true;
  214.     dthread_resume(dt);
  215. }
  216.  
  217. /** @}
  218.  */
  219.