summaryrefslogblamecommitdiffstats
path: root/c/src/librdbg/src/_servtgt.c
blob: 0ec9f3c1bfc49015677726bc3fef2c266078e850 (plain) (tree)
1
2
3
4
5
6
7
8

                                                                             

         


                                                                             
                   




                        
                         
                  
                       


                            










                             
                 


                               



                                                                       

                                                                
 
                                           

 





                                                                             

                                                          

 


                                                       
 
           





                                                                             

                                   




                                          



                                                   

            
                                           
                                                                            
                                                      
 
              
                                             
 
                                  
 
                                                              










                                                                          

                                           
 

                                 









                                                                             



                                                               

                           
 

            


                                          
            
                                            
 
                                               
 
                            
 
    

                                                                      
     

























                                                                    

                                         









                                                                         
                                 









                                                                         
                                 

                                                         



                                                              





                                                                       


                                         
                                                         
 
                





                                                                             

                                                               

                                                


                                                                                 


                                           

                                                                           
                                       
                                              
     


                                                                       





                                                                     







                                                       

                                                                            
 
                                                                                
          
                                                                         








                                                   

                                                                          

           
                                                                        
          
                                                                       







                                                   
 
            





                                                                       








                                                        
                                                                      
 


                                                                                
                                         

                                    
     


         
                                                                    
 
                                                                             
           

                                                                        
                                         

                                    
     


         

                                                         
              
 
/*
 ============================================================================
 _SERVTGT
 $Id$
 ============================================================================
*/

#include <string.h>
#include <rtems.h>
#include <rtems/error.h>

#include <rdbg/rdbg.h>
#include <rdbg/rdbg_f.h>
#include <rdbg/servrpc.h>
#include <errno.h>
#include <sys/socket.h>
#include <assert.h>
#include <rtems/score/cpu.h>

#ifdef DDEBUG
#define Ptrace	TgtDbgPtrace
#else
#define Ptrace	TgtRealPtrace
#endif

extern int errno;

rtems_id eventTaskId;
rtems_id serializeSemId;
rtems_id wakeupEventSemId;
rtems_id debugId;

CPU_Exception_frame Idle_frame;

/* -----------------------------------------------------------------
   TgtRealPtrace - lowest level ptrace() wrapper
   ----------------------------------------------------------------- */

  int
TgtRealPtrace (int req, PID aid, char *addr, int d, void *addr2)
{
  return ptrace (req, aid, addr, d, addr2);
}

/* -----------------------------------------------------------------------
   TgtChange() is called when the system stops.
   It informs the generic layers must be informed of
   that fact. 
   ----------------------------------------------------------------------- */

  static int
TgtChange (PID pid, CPU_Exception_frame * ctx, int status)
{

  if (TgtHandleChildChange (pid, &status, NULL, ctx)) {
    TgtNotifyWaitChange (pid, status, -1);
  }

  return 0;
}

/* -----------------------------------------------------------------------
   eventTask
   ----------------------------------------------------------------------- */

  rtems_task
eventTask (rtems_task_argument pid)
{
  Exception_context *ctx;

  DPRINTF (("event task: pid %d\n", pid));

  /*
   * we spend all our time waiting for a semaphore.
   * If wait change, we send info
   */

  for (;;) {
    DPRINTF (("Event Task: wait event\n"));
    rtems_semaphore_obtain (wakeupEventSemId, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    DPRINTF (("Event Task: wake up !!!!!!!!!!!!!\n"));

    errno = 0;
    ctx = GetExceptCtx (currentTargetThread);

    CheckForSingleStep (ctx->ctx);

    TgtChange (pid, ctx->ctx, STS_MAKESIG (ExcepToSig (ctx)));
  }
}

/* -------------------------------------------------------------------
   MyThreadIdle -

   This task is used to initiate the exception mechanism:
   It calls the enterDebug function with justSaveContext=1
   only to push a first valid context in the list
   ---------------------------------------------------------------------*/

  rtems_task
MyThreadIdle (rtems_task_argument argument)
{
  enterRdbg ();
  rtems_task_delete (RTEMS_SELF);
}

/* -----------------------------------------------------------------------
   TgtAttach - attach to a process that is running without control.

   Notes:
      - this function performs a ptrace ATTACH equivalent (attaching to a
	process that we do not control now).
   ----------------------------------------------------------------------- */

  Boolean
TgtAttach (int conn_idx,        /* client that is requesting */
           PID pid)
{                               /* process to attach to */
  rtems_name task_name;
  rtems_status_code status;

  errno = 0;

  DPRINTF (("TgtAttach pid=%d\n", pid));

  Ptrace (RPT_ATTACH, pid, NULL, 0, NULL);
  if (errno)
    return (False);             /* failed */

  TgtCreateNew (pid, conn_idx, 0, NULL, False);

  connect_rdbg_exception ();

  /*
   * Search for and remove debugging tasks / semaphores left over from
   * a previous attach without a detach.
   */

  if (rtems_task_ident (rtems_build_name ('E', 'v', 'n', 't'),
                        RTEMS_SEARCH_ALL_NODES,
                        &eventTaskId) == RTEMS_SUCCESSFUL)
    rtems_task_delete (eventTaskId);

  if (rtems_semaphore_ident (rtems_build_name ('D', 'B', 'G', 's'),
                             RTEMS_SEARCH_ALL_NODES,
                             &serializeSemId) == RTEMS_SUCCESSFUL)
    rtems_semaphore_delete (serializeSemId);

  if (rtems_semaphore_ident (rtems_build_name ('D', 'B', 'G', 'w'),
                             RTEMS_SEARCH_ALL_NODES,
                             &wakeupEventSemId) == RTEMS_SUCCESSFUL)
    rtems_semaphore_delete (wakeupEventSemId);

  /*
   * Create the attach debugger task
   */
  task_name = rtems_build_name ('E', 'v', 'n', 't');
  if ((status = rtems_task_create (task_name, 10, 24576,
                                   RTEMS_INTERRUPT_LEVEL (0),
                                   RTEMS_DEFAULT_ATTRIBUTES |
                                   RTEMS_SYSTEM_TASK, &eventTaskId))
      != RTEMS_SUCCESSFUL) {
    printf ("status = %d\n", status);
    rtems_panic ("Can't create task.\n");
  }

  status = rtems_task_start (eventTaskId, eventTask, pid);

  status = rtems_semaphore_create (rtems_build_name ('D', 'B', 'G', 's'),
                                   1,
                                   RTEMS_FIFO |
                                   RTEMS_COUNTING_SEMAPHORE |
                                   RTEMS_NO_INHERIT_PRIORITY |
                                   RTEMS_NO_PRIORITY_CEILING |
                                   RTEMS_LOCAL, 0, &serializeSemId);
  if (status != RTEMS_SUCCESSFUL)
    rtems_panic ("Can't create serialize semaphore: `%s'\n",
                 rtems_status_text (status));

  status = rtems_semaphore_create (rtems_build_name ('D', 'B', 'G', 'w'),
                                   0,
                                   RTEMS_FIFO |
                                   RTEMS_COUNTING_SEMAPHORE |
                                   RTEMS_NO_INHERIT_PRIORITY |
                                   RTEMS_NO_PRIORITY_CEILING |
                                   RTEMS_LOCAL, 0, &wakeupEventSemId);
  if (status != RTEMS_SUCCESSFUL)
    rtems_panic ("Can't create wakeup semaphore: `%s'\n",
                 rtems_status_text (status));

  /*
   * Create the MyThreadIdle task to init Exception mechanism 
   */
  task_name = rtems_build_name ('R', 'i', 'n', 'i');
  if ((status = rtems_task_create (task_name, 10, 24576,
                                   RTEMS_INTERRUPT_LEVEL (0),
                                   RTEMS_DEFAULT_ATTRIBUTES, &debugId))
      != RTEMS_SUCCESSFUL) {
    printf ("status = %d (%s)\n", status, rtems_status_text (status));
    rtems_panic ("Can't create task.\n");
  }

  status = rtems_task_start (debugId, MyThreadIdle, pid);

  return (True);
}

/* -----------------------------------------------------------------------
   TgtPtrace - handle ptrace requests for server.
   ----------------------------------------------------------------------- */

int
TgtPtrace (int req, PID pid, char *addr, int data, void *addr2)
{
  if ((req == RPT_SINGLESTEP || req == RPT_CONT)
      && addr2) {               /* clear then step *//* addr2 is the old value */

    int ret;

    errno = 0;
    TgtBreakRestoreOrig (pid, addr, addr2);
    ret = Ptrace (RPT_SINGLESTEP, pid, addr, data, NULL);   /* step over */
    if (ret) {                  /* error, cannot single-step */
      int pid_idx = FindPidEntry (pid);
      TgtBreakCancelStep (&pid_list[pid_idx]);
    }
    return (ret);               /* failed or done */
  } else
      return (Ptrace (req, pid, addr, data, addr2));  /* normal call */
}

/* -----------------------------------------------------------------
   TgtGetThreadName - get thread name
   --------------------------------------------------------------- */

  int
TgtGetThreadName (PID_LIST * plst,  /* Process entry */
                  unsigned Id,  /* Thread ID */
                  char *ThrName)
{                               /* Thread name */
  int index;
  unsigned name;

  if (Id < _Objects_Information_table[OBJECTS_CLASSIC_API][1]->maximum_id &&
      Id > _Objects_Information_table[OBJECTS_CLASSIC_API][1]->minimum_id) {

    index = Id - _Objects_Information_table[OBJECTS_CLASSIC_API][1]->minimum_id;
    name =
      *(unsigned *) (_Objects_Information_table[OBJECTS_CLASSIC_API][1]->
                     local_table[1 + index]->name);
    ThrName[0] = (char) ((name >> 24) & 0xFF);
    ThrName[1] = (char) ((name >> 16) & 0xFF);
    ThrName[2] = (char) ((name >> 8) & 0xFF);
    ThrName[3] = (char) (name & 0xFF);
    ThrName[4] = 0x0;
    return 0;
  }

  if (Id < _Objects_Information_table[OBJECTS_POSIX_API][1]->maximum_id &&
      Id > _Objects_Information_table[OBJECTS_POSIX_API][1]->minimum_id) {

    index =
      Id - _Objects_Information_table[OBJECTS_POSIX_API][1]->minimum_id;
    name =
      *(unsigned *) (_Objects_Information_table[OBJECTS_POSIX_API][1]->
                     local_table[1 + index]->name);
    ThrName[0] = (char) ((name >> 24) & 0xFF);
    ThrName[1] = (char) ((name >> 16) & 0xFF);
    ThrName[2] = (char) ((name >> 8) & 0xFF);
    ThrName[3] = (char) (name & 0xFF);
    ThrName[4] = 0x0;
    return 0;
  }

  return -1;
}

/* -----------------------------------------------------------------
   TgtThreadList - return all the threads in the system
   ----------------------------------------------------------------- */

  int
TgtThreadList (PID_LIST * plst, /* Process entry */
               unsigned *threads,   /* Output buffer */
               unsigned size)
{                               /* Output buffer size */
  int curr = 0;
  Objects_Id id;
  unsigned index;

  id = _Objects_Information_table[OBJECTS_CLASSIC_API][1]->minimum_id;

  while (id < _Objects_Information_table[OBJECTS_CLASSIC_API][1]->maximum_id) {
    index = id - _Objects_Information_table[OBJECTS_CLASSIC_API][1]->minimum_id;
    if (_Objects_Information_table[OBJECTS_CLASSIC_API][1]->
        local_table[1 + index] != NULL) {
      threads[curr] = (unsigned) id;
      curr++;
    }
    id++;
  }

  id = _Objects_Information_table[OBJECTS_POSIX_API][1]->minimum_id;

  while (id < _Objects_Information_table[OBJECTS_POSIX_API][1]->maximum_id) {
    index =
      id - _Objects_Information_table[OBJECTS_POSIX_API][1]->minimum_id;
    if (_Objects_Information_table[OBJECTS_POSIX_API][1]->
        local_table[1 + index] != NULL) {
      threads[curr] = (unsigned) id;
      curr++;
    }
    id++;
  }

#warning "ignores ITRON tasks and could be a single loop"

  return curr;
}