Changeset 16d40ce in rtems


Ignore:
Timestamp:
02/22/22 22:01:33 (8 months ago)
Author:
Kinsey Moore <kinsey.moore@…>
Branches:
master
Children:
3317d1e
Parents:
dbdf38ea
git-author:
Kinsey Moore <kinsey.moore@…> (02/22/22 22:01:33)
git-committer:
Joel Sherrill <joel@…> (02/23/22 14:35:45)
Message:

cpukit/libdebugger: Avoid cascade for interrupts

This updates behavior of libdebugger to handle debug exceptions in
interrupt context by temporarily removing a software breakpoint,
stepping, and then resuming afterward.

Location:
cpukit/libdebugger
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • cpukit/libdebugger/rtems-debugger-target.c

    rdbdf38ea r16d40ce  
    166166    return target->reg_offset[target->reg_num];
    167167  return 0;
     168}
     169
     170bool
     171rtems_debugger_target_swbreak_is_configured( uintptr_t addr )
     172{
     173  size_t                         i;
     174  rtems_debugger_target_swbreak *swbreaks;
     175  rtems_debugger_target         *target = rtems_debugger->target;
     176
     177  if ( target == NULL ) {
     178    return false;
     179  }
     180
     181  swbreaks = target->swbreaks.block;
     182
     183  if ( swbreaks == NULL ) {
     184    return false;
     185  }
     186
     187  for ( i = 0; i < target->swbreaks.level; ++i ) {
     188    if ( (uintptr_t) swbreaks[ i ].address == addr ) {
     189      return true;
     190    }
     191  }
     192
     193  return false;
    168194}
    169195
     
    324350}
    325351
     352uintptr_t saved_break_address = 0;
     353rtems_id saved_tid = 0;
     354
     355static rtems_debugger_target_exc_action
     356soft_step_and_continue(CPU_Exception_frame* frame)
     357{
     358  uintptr_t              break_address;
     359  rtems_debugger_target *target = rtems_debugger->target;
     360  Thread_Control        *thread = _Thread_Get_executing();
     361  const rtems_id         tid = thread->Object.id;
     362  rtems_debugger_thread  fake_debugger_thread;
     363
     364  /*
     365   * If this was a hwbreak, cascade. If this is a swbreak replace the contents
     366   * of the instruction, step then return the swbreak's contents.
     367   */
     368  if ((target->capabilities & RTEMS_DEBUGGER_TARGET_CAP_SWBREAK) == 0) {
     369    target_printk("rtems-db: exception in an interrupt, cascading\n");
     370    rtems_debugger_unlock();
     371    return rtems_debugger_target_exc_cascade;
     372  }
     373
     374  break_address = rtems_debugger_target_frame_pc( frame );
     375  if ( rtems_debugger_target_swbreak_is_configured( break_address ) == false ) {
     376    target_printk("rtems-db: exception in an interrupt, cascading\n");
     377    rtems_debugger_unlock();
     378    return rtems_debugger_target_exc_cascade;
     379  }
     380
     381  /* Remove the current breakpoint */
     382  rtems_debugger_target_swbreak_control(
     383    false,
     384    break_address,
     385    target->breakpoint_size
     386  );
     387
     388  /* Save off thread ID and break address for later usage */
     389  saved_tid = tid;
     390  saved_break_address = break_address;
     391
     392  /* Populate the fake rtems_debugger_thread */
     393  fake_debugger_thread.flags |= RTEMS_DEBUGGER_THREAD_FLAG_STEP;
     394  fake_debugger_thread.frame = frame;
     395  target_printk("rtems-db: stepping to the next instruction\n");
     396  rtems_debugger_target_thread_stepping(&fake_debugger_thread);
     397
     398  /* rtems_debugger_unlock() not called until the step is resolved */
     399  return rtems_debugger_target_exc_step;
     400}
     401
    326402rtems_debugger_target_exc_action
    327403rtems_debugger_target_exception(CPU_Exception_frame* frame)
    328404{
     405  Thread_Control* thread = _Thread_Get_executing();
     406  const rtems_id  tid = thread->Object.id;
     407
     408  /* Resolve outstanding step+continue */
     409  if ( saved_break_address != 0 && tid == saved_tid ) {
     410    rtems_debugger_target_swbreak_control(
     411      true,
     412      saved_break_address,
     413      rtems_debugger->target->breakpoint_size
     414    );
     415    saved_break_address = saved_tid = 0;
     416
     417    /* Release the debugger lock now that the step+continue is complete */
     418    target_printk("rtems-db: resuming after step\n");
     419    rtems_debugger_unlock();
     420    return rtems_debugger_target_exc_consumed;
     421  }
     422
     423  rtems_debugger_lock();
     424
    329425  if (!rtems_interrupt_is_in_progress()) {
    330426    rtems_debugger_threads*              threads = rtems_debugger->threads;
    331     Thread_Control*                      thread = _Thread_Get_executing();
    332     const rtems_id                       tid = thread->Object.id;
    333427    rtems_id*                            excludes;
    334428    uintptr_t                            pc;
     
    340434                  " frame:%08" PRIxPTR "\n",
    341435                  tid, (intptr_t) thread, (intptr_t) frame);
    342 
    343     rtems_debugger_lock();
    344436
    345437    /*
     
    431523  }
    432524
    433   rtems_debugger_printf("rtems-db: exception in an interrupt, cascading\n");
    434 
    435   return rtems_debugger_target_exc_cascade;
     525  target_printk("[} tid:%08" PRIx32 ": exception in interrupt context\n", tid);
     526
     527  /* soft_step_and_continue releases the debugger lock */
     528  return soft_step_and_continue( frame );
    436529}
    437530
  • cpukit/libdebugger/rtems-debugger-target.h

    rdbdf38ea r16d40ce  
    223223
    224224/**
     225 * Determine whether a software breakpoint is configured for the given address.
     226 */
     227extern bool rtems_debugger_target_swbreak_is_configured( uintptr_t addr );
     228
     229/**
    225230 * Insert hardware breakpoints into the hardware.
    226231 */
Note: See TracChangeset for help on using the changeset viewer.