mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-06 07:33:17 +00:00
2001-03-05 Greg Menke <gregory.menke@gsfc.nasa.gov>
* mips-stub.c: Debugged & tweaked the gdb command processing, zbreak stuff, breakpoint and step code. Implemented 'T' command support and debugged remote gdb support w/ the Mongoose bsp. Added the memory segment support. * memlimits.h: Disabled all contents in favor of memory sement support. This file could probably go away. * rtems-stub-glue.c (rtems_gdb_index_to_stub_id()): New routine. rtems_gdb_stub_get_register_from_context(): Implemented MIPS version. rtems_gdb_stub_get_offsets(): Implemented MIPS version. * README: Updated.
This commit is contained in:
@@ -1,3 +1,16 @@
|
|||||||
|
2001-03-05 Greg Menke <gregory.menke@gsfc.nasa.gov>
|
||||||
|
|
||||||
|
* mips-stub.c: Debugged & tweaked the gdb command processing,
|
||||||
|
zbreak stuff, breakpoint and step code. Implemented 'T' command
|
||||||
|
support and debugged remote gdb support w/ the Mongoose bsp.
|
||||||
|
Added the memory segment support.
|
||||||
|
* memlimits.h: Disabled all contents in favor of memory sement
|
||||||
|
support. This file could probably go away.
|
||||||
|
* rtems-stub-glue.c (rtems_gdb_index_to_stub_id()): New routine.
|
||||||
|
rtems_gdb_stub_get_register_from_context(): Implemented MIPS version.
|
||||||
|
rtems_gdb_stub_get_offsets(): Implemented MIPS version.
|
||||||
|
* README: Updated.
|
||||||
|
|
||||||
2001-03-01 Joel Sherrill <joel@OARcorp.com>
|
2001-03-01 Joel Sherrill <joel@OARcorp.com>
|
||||||
|
|
||||||
* ChangeLog: Corrected previous entry.
|
* ChangeLog: Corrected previous entry.
|
||||||
|
|||||||
@@ -2,6 +2,29 @@
|
|||||||
# $Id$
|
# $Id$
|
||||||
#
|
#
|
||||||
|
|
||||||
|
/*****************************************************/
|
||||||
|
|
||||||
|
Debugged this stub against the MongooseV bsp. Relies on putting break
|
||||||
|
instructions on breakpoints and step targets- normal stuff, and does not
|
||||||
|
employ hardware breakpoint support at this time. As written, a single
|
||||||
|
breakpoint in a loop will not be reasserted unless the user steps or has
|
||||||
|
a 2nd one, since breakpoints are only reset when the gdb stub is
|
||||||
|
re-entered. A useful enhancement would be to fix the break instruction
|
||||||
|
management so the stub could invisibly put a 2nd break after the 1st
|
||||||
|
"official" one so it can silently reset breakpoints. Shouldn't be too
|
||||||
|
hard, mostly a matter of working it out.
|
||||||
|
|
||||||
|
This was tested only against an R3000 MIPS. It should work OK on a
|
||||||
|
R4000. Needs to be tested at some point.
|
||||||
|
|
||||||
|
This stub supports threads as implemented by gdb 5 and doesn't have any
|
||||||
|
bugs I'm aware of.
|
||||||
|
|
||||||
|
Greg Menke
|
||||||
|
3/5/2002
|
||||||
|
|
||||||
|
/*****************************************************/
|
||||||
|
|
||||||
|
|
||||||
The contents of this directory are based upon the "r46kstub.tar.gz" package
|
The contents of this directory are based upon the "r46kstub.tar.gz" package
|
||||||
released to the net by
|
released to the net by
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ const char* vhstr2int(const char *buf, int *ival);
|
|||||||
int hstr2byte(const char *buf, int *bval);
|
int hstr2byte(const char *buf, int *bval);
|
||||||
int hstr2nibble(const char *buf, int *nibble);
|
int hstr2nibble(const char *buf, int *nibble);
|
||||||
|
|
||||||
|
Thread_Control *rtems_gdb_index_to_stub_id(int);
|
||||||
int rtems_gdb_stub_thread_support_ok(void);
|
int rtems_gdb_stub_thread_support_ok(void);
|
||||||
int rtems_gdb_stub_get_current_thread(void);
|
int rtems_gdb_stub_get_current_thread(void);
|
||||||
int rtems_gdb_stub_get_next_thread(int);
|
int rtems_gdb_stub_get_next_thread(int);
|
||||||
@@ -159,4 +160,21 @@ void rtems_gdb_process_query(
|
|||||||
|
|
||||||
#define NUM_REGS 72
|
#define NUM_REGS 72
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void mips_gdb_stub_install(int enableThreads) ;
|
||||||
|
|
||||||
|
|
||||||
|
#define MEMOPT_READABLE 1
|
||||||
|
#define MEMOPT_WRITEABLE 2
|
||||||
|
|
||||||
|
#define NUM_MEMSEGS 10
|
||||||
|
|
||||||
|
int gdbstub_add_memsegment(unsigned,unsigned,int);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _GDB_IF_H */
|
#endif /* _GDB_IF_H */
|
||||||
|
|||||||
@@ -12,8 +12,8 @@
|
|||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LIMITS_H_
|
#ifndef _MEMLIMITS_H_
|
||||||
#define _LIMITS_H_
|
#define _MEMLIMITS_H_
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The macros in this file are specific to a given implementation.
|
* The macros in this file are specific to a given implementation.
|
||||||
@@ -45,6 +45,7 @@
|
|||||||
* to have different readability and/or writeability attributes.
|
* to have different readability and/or writeability attributes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
#define K0_LIMIT_FOR_READ (K0BASE+0x18000000)
|
#define K0_LIMIT_FOR_READ (K0BASE+0x18000000)
|
||||||
#define K1_LIMIT_FOR_READ (K1BASE+K1SIZE)
|
#define K1_LIMIT_FOR_READ (K1BASE+K1SIZE)
|
||||||
|
|
||||||
@@ -67,4 +68,21 @@
|
|||||||
&& (((K0BASE <= (int)ptr) && ((int)ptr < K0_LIMIT_FOR_STEP)) \
|
&& (((K0BASE <= (int)ptr) && ((int)ptr < K0_LIMIT_FOR_STEP)) \
|
||||||
|| ((K1BASE <= (int)ptr) && ((int)ptr < K1_LIMIT_FOR_STEP))))
|
|| ((K1BASE <= (int)ptr) && ((int)ptr < K1_LIMIT_FOR_STEP))))
|
||||||
|
|
||||||
#endif /* _LIMITS_H_ */
|
struct memseg
|
||||||
|
{
|
||||||
|
unsigned begin, end, opts;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MEMOPT_READABLE 1
|
||||||
|
#define MEMOPT_WRITEABLE 2
|
||||||
|
|
||||||
|
#define NUM_MEMSEGS 10
|
||||||
|
|
||||||
|
|
||||||
|
int add_memsegment(unsigned,unsigned,int);
|
||||||
|
int is_readable(unsigned,unsigned);
|
||||||
|
int is_writeable(unsigned,unsigned);
|
||||||
|
int is_steppable(unsigned);
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* _MEMLIMITS_H_ */
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -29,7 +29,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <rtems.h>
|
#include <rtems.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "gdb_if.h"
|
#include "gdb_if.h"
|
||||||
@@ -40,6 +39,7 @@
|
|||||||
|
|
||||||
extern const char gdb_hexchars[];
|
extern const char gdb_hexchars[];
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prototypes for CPU dependent routines that are conditional
|
* Prototypes for CPU dependent routines that are conditional
|
||||||
* at the bottom of this file.
|
* at the bottom of this file.
|
||||||
@@ -50,6 +50,12 @@ void rtems_gdb_stub_get_registers_from_context(
|
|||||||
Thread_Control *th
|
Thread_Control *th
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Check whether it is OK to enable thread support */
|
/* Check whether it is OK to enable thread support */
|
||||||
int rtems_gdb_stub_thread_support_ok(void)
|
int rtems_gdb_stub_thread_support_ok(void)
|
||||||
{
|
{
|
||||||
@@ -59,6 +65,10 @@ int rtems_gdb_stub_thread_support_ok(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* rtems_gdb_stub_id_to_index
|
* rtems_gdb_stub_id_to_index
|
||||||
*
|
*
|
||||||
@@ -101,12 +111,84 @@ int rtems_gdb_stub_id_to_index(
|
|||||||
return first_posix_id + (thread_obj_id - min_id);
|
return first_posix_id + (thread_obj_id - min_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Return the RTEMS thread id from a gdb thread id */
|
||||||
|
Thread_Control *rtems_gdb_index_to_stub_id(
|
||||||
|
int thread
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Objects_Id thread_obj_id;
|
||||||
|
Objects_Id min_id, max_id;
|
||||||
|
int first_posix_id, first_rtems_id;
|
||||||
|
Objects_Information *obj_info;
|
||||||
|
Thread_Control *th;
|
||||||
|
|
||||||
|
ASSERT(registers != NULL);
|
||||||
|
|
||||||
|
if (_System_state_Get() != SYSTEM_STATE_UP || thread <= 0) {
|
||||||
|
/* Should not happen */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thread == 1) {
|
||||||
|
th = _Thread_Idle;
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let us get object associtated with current thread */
|
||||||
|
first_rtems_id = 2;
|
||||||
|
|
||||||
|
thread_obj_id = _Thread_Executing->Object.id;
|
||||||
|
|
||||||
|
/* Let us figure out thread_id for gdb */
|
||||||
|
obj_info = _Objects_Information_table[OBJECTS_RTEMS_TASKS];
|
||||||
|
|
||||||
|
min_id = obj_info->minimum_id;
|
||||||
|
max_id = obj_info->maximum_id;
|
||||||
|
|
||||||
|
if (thread <= (first_rtems_id + (max_id - min_id))) {
|
||||||
|
th = (Thread_Control *)(obj_info->local_table[thread - first_rtems_id + 1]);
|
||||||
|
|
||||||
|
if (th != NULL) {
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Thread does not exist */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
first_posix_id = first_rtems_id + (max_id - min_id) + 1;
|
||||||
|
|
||||||
|
obj_info = _Objects_Information_table[OBJECTS_POSIX_THREADS];
|
||||||
|
|
||||||
|
min_id = obj_info->minimum_id;
|
||||||
|
max_id = obj_info->maximum_id;
|
||||||
|
|
||||||
|
th = (Thread_Control *)(obj_info->local_table[thread - first_posix_id + 1]);
|
||||||
|
if (th == NULL) {
|
||||||
|
/* Thread does not exist */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
found:
|
||||||
|
return th;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Get id of the thread stopped by exception */
|
/* Get id of the thread stopped by exception */
|
||||||
int rtems_gdb_stub_get_current_thread(void)
|
int rtems_gdb_stub_get_current_thread(void)
|
||||||
{
|
{
|
||||||
return rtems_gdb_stub_id_to_index( _Thread_Executing->Object.id );
|
return rtems_gdb_stub_id_to_index( _Thread_Executing->Object.id );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Get id of the next thread after athread, if argument <= 0 find the
|
/* Get id of the next thread after athread, if argument <= 0 find the
|
||||||
first available thread, return thread if found or 0 if not */
|
first available thread, return thread if found or 0 if not */
|
||||||
int rtems_gdb_stub_get_next_thread(int athread)
|
int rtems_gdb_stub_get_next_thread(int athread)
|
||||||
@@ -176,6 +258,10 @@ int rtems_gdb_stub_get_next_thread(int athread)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Get thread registers, return 0 if thread does not
|
/* Get thread registers, return 0 if thread does not
|
||||||
exist, and 1 otherwise */
|
exist, and 1 otherwise */
|
||||||
int rtems_gdb_stub_get_thread_regs(
|
int rtems_gdb_stub_get_thread_regs(
|
||||||
@@ -183,70 +269,27 @@ int rtems_gdb_stub_get_thread_regs(
|
|||||||
unsigned int *registers
|
unsigned int *registers
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Objects_Id thread_obj_id;
|
Thread_Control *th;
|
||||||
Objects_Id min_id, max_id;
|
|
||||||
int first_posix_id, first_rtems_id;
|
|
||||||
Objects_Information *obj_info;
|
|
||||||
Thread_Control *th;
|
|
||||||
|
|
||||||
ASSERT(registers != NULL);
|
th= rtems_gdb_index_to_stub_id(thread);
|
||||||
|
|
||||||
if (_System_state_Get() != SYSTEM_STATE_UP || thread <= 0) {
|
if( th )
|
||||||
/* Should not happen */
|
{
|
||||||
return 0;
|
rtems_gdb_stub_get_registers_from_context( registers, th );
|
||||||
}
|
return 1;
|
||||||
|
}
|
||||||
if (thread == 1) {
|
return 0;
|
||||||
th = _Thread_Idle;
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Let us get object associtated with current thread */
|
|
||||||
first_rtems_id = 2;
|
|
||||||
|
|
||||||
thread_obj_id = _Thread_Executing->Object.id;
|
|
||||||
|
|
||||||
/* Let us figure out thread_id for gdb */
|
|
||||||
obj_info = _Objects_Information_table[OBJECTS_RTEMS_TASKS];
|
|
||||||
|
|
||||||
min_id = obj_info->minimum_id;
|
|
||||||
max_id = obj_info->maximum_id;
|
|
||||||
|
|
||||||
if (thread <= (first_rtems_id + (max_id - min_id))) {
|
|
||||||
th = (Thread_Control *)(obj_info->local_table[thread - first_rtems_id + 1]);
|
|
||||||
|
|
||||||
if (th != NULL) {
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Thread does not exist */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
first_posix_id = first_rtems_id + (max_id - min_id) + 1;
|
|
||||||
|
|
||||||
obj_info = _Objects_Information_table[OBJECTS_POSIX_THREADS];
|
|
||||||
|
|
||||||
min_id = obj_info->minimum_id;
|
|
||||||
max_id = obj_info->maximum_id;
|
|
||||||
|
|
||||||
th = (Thread_Control *)(obj_info->local_table[thread - first_posix_id + 1]);
|
|
||||||
if (th == NULL) {
|
|
||||||
/* Thread does not exist */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
found:
|
|
||||||
|
|
||||||
rtems_gdb_stub_get_registers_from_context( registers, th );
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Set thread registers, return 0 if thread does not
|
/* Set thread registers, return 0 if thread does not
|
||||||
exist or register values will screw up the threads,
|
exist or register values will screw up the threads,
|
||||||
and 1 otherwise */
|
and 1 otherwise */
|
||||||
|
|
||||||
int rtems_gdb_stub_set_thread_regs(
|
int rtems_gdb_stub_set_thread_regs(
|
||||||
int thread,
|
int thread,
|
||||||
unsigned int *registers
|
unsigned int *registers
|
||||||
@@ -260,6 +303,10 @@ int rtems_gdb_stub_set_thread_regs(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Get thread information, return 0 if thread does not
|
/* Get thread information, return 0 if thread does not
|
||||||
exist and 1 otherwise */
|
exist and 1 otherwise */
|
||||||
int rtems_gdb_stub_get_thread_info(
|
int rtems_gdb_stub_get_thread_info(
|
||||||
@@ -267,122 +314,126 @@ int rtems_gdb_stub_get_thread_info(
|
|||||||
struct rtems_gdb_stub_thread_info *info
|
struct rtems_gdb_stub_thread_info *info
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Objects_Id thread_obj_id;
|
Objects_Id thread_obj_id;
|
||||||
Objects_Id min_id, max_id;
|
Objects_Id min_id, max_id;
|
||||||
int first_posix_id, first_rtems_id;
|
int first_posix_id, first_rtems_id;
|
||||||
Objects_Information *obj_info;
|
Objects_Information *obj_info;
|
||||||
Thread_Control *th;
|
Thread_Control *th;
|
||||||
unsigned32 name;
|
unsigned32 name;
|
||||||
char tmp_buf[20];
|
char tmp_buf[20];
|
||||||
|
|
||||||
ASSERT(info != NULL);
|
ASSERT(info != NULL);
|
||||||
|
|
||||||
if (thread <= 0) {
|
if (thread <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_System_state_Get() != SYSTEM_STATE_UP || thread == 1) {
|
if (_System_state_Get() != SYSTEM_STATE_UP || thread == 1) {
|
||||||
/* We have one thread let us use value
|
/* We have one thread let us use value
|
||||||
which will never happen for real thread */
|
which will never happen for real thread */
|
||||||
strcpy(info->display, "idle thread");
|
strcpy(info->display, "idle thread");
|
||||||
strcpy(info->name, "IDLE");
|
strcpy(info->name, "IDLE");
|
||||||
info->more_display[0] = 0; /* Nothing */
|
info->more_display[0] = 0; /* Nothing */
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Let us get object associtated with current thread */
|
/* Let us get object associtated with current thread */
|
||||||
thread_obj_id = _Thread_Executing->Object.id;
|
thread_obj_id = _Thread_Executing->Object.id;
|
||||||
|
|
||||||
/* Let us figure out thread_id for gdb */
|
/* Let us figure out thread_id for gdb */
|
||||||
first_rtems_id = 2;
|
first_rtems_id = 2;
|
||||||
|
|
||||||
obj_info = _Objects_Information_table[OBJECTS_RTEMS_TASKS];
|
obj_info = _Objects_Information_table[OBJECTS_RTEMS_TASKS];
|
||||||
|
|
||||||
min_id = obj_info->minimum_id;
|
min_id = obj_info->minimum_id;
|
||||||
max_id = obj_info->maximum_id;
|
max_id = obj_info->maximum_id;
|
||||||
|
|
||||||
if (thread <= (first_rtems_id + (max_id - min_id))) {
|
if (thread <= (first_rtems_id + (max_id - min_id))) {
|
||||||
th = (Thread_Control *)(obj_info->local_table[thread -
|
th = (Thread_Control *)(obj_info->local_table[thread -
|
||||||
first_rtems_id + 1]);
|
first_rtems_id + 1]);
|
||||||
|
|
||||||
if (th == NULL) {
|
if (th == NULL) {
|
||||||
/* Thread does not exist */
|
/* Thread does not exist */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(info->display, "rtems task: control at 0x");
|
strcpy(info->display, "rtems task: control at 0x");
|
||||||
|
|
||||||
tmp_buf[0] = gdb_hexchars[(((int)th) >> 28) & 0xf];
|
tmp_buf[0] = gdb_hexchars[(((int)th) >> 28) & 0xf];
|
||||||
tmp_buf[1] = gdb_hexchars[(((int)th) >> 24) & 0xf];
|
tmp_buf[1] = gdb_hexchars[(((int)th) >> 24) & 0xf];
|
||||||
tmp_buf[2] = gdb_hexchars[(((int)th) >> 20) & 0xf];
|
tmp_buf[2] = gdb_hexchars[(((int)th) >> 20) & 0xf];
|
||||||
tmp_buf[3] = gdb_hexchars[(((int)th) >> 16) & 0xf];
|
tmp_buf[3] = gdb_hexchars[(((int)th) >> 16) & 0xf];
|
||||||
tmp_buf[4] = gdb_hexchars[(((int)th) >> 12) & 0xf];
|
tmp_buf[4] = gdb_hexchars[(((int)th) >> 12) & 0xf];
|
||||||
tmp_buf[5] = gdb_hexchars[(((int)th) >> 8) & 0xf];
|
tmp_buf[5] = gdb_hexchars[(((int)th) >> 8) & 0xf];
|
||||||
tmp_buf[6] = gdb_hexchars[(((int)th) >> 4) & 0xf];
|
tmp_buf[6] = gdb_hexchars[(((int)th) >> 4) & 0xf];
|
||||||
tmp_buf[7] = gdb_hexchars[((int)th) & 0xf];
|
tmp_buf[7] = gdb_hexchars[((int)th) & 0xf];
|
||||||
tmp_buf[8] = 0;
|
tmp_buf[8] = 0;
|
||||||
|
|
||||||
strcat(info->display, tmp_buf);
|
strcat(info->display, tmp_buf);
|
||||||
|
|
||||||
name = *(unsigned32 *)(obj_info->local_table[thread]->name);
|
name = *(unsigned32 *)(obj_info->local_table[thread]->name);
|
||||||
|
|
||||||
info->name[0] = (name >> 24) & 0xff;
|
info->name[0] = (name >> 24) & 0xff;
|
||||||
info->name[1] = (name >> 16) & 0xff;
|
info->name[1] = (name >> 16) & 0xff;
|
||||||
info->name[2] = (name >> 8) & 0xff;
|
info->name[2] = (name >> 8) & 0xff;
|
||||||
info->name[3] = name & 0xff;
|
info->name[3] = name & 0xff;
|
||||||
info->name[4] = 0;
|
info->name[4] = 0;
|
||||||
|
|
||||||
info->more_display[0] = 0; /* Nothing */
|
info->more_display[0] = 0; /* Nothing */
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
first_posix_id = first_rtems_id + (max_id - min_id) + 1;
|
first_posix_id = first_rtems_id + (max_id - min_id) + 1;
|
||||||
|
|
||||||
obj_info = _Objects_Information_table[OBJECTS_POSIX_THREADS];
|
obj_info = _Objects_Information_table[OBJECTS_POSIX_THREADS];
|
||||||
|
|
||||||
min_id = obj_info->minimum_id;
|
min_id = obj_info->minimum_id;
|
||||||
max_id = obj_info->maximum_id;
|
max_id = obj_info->maximum_id;
|
||||||
|
|
||||||
th = (Thread_Control *)(obj_info->local_table[thread - first_posix_id + 1]);
|
th = (Thread_Control *)(obj_info->local_table[thread - first_posix_id + 1]);
|
||||||
if (th == NULL)
|
if (th == NULL)
|
||||||
{
|
{
|
||||||
/* Thread does not exist */
|
/* Thread does not exist */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(info->display, "posix thread: control at 0x");
|
strcpy(info->display, "posix thread: control at 0x");
|
||||||
|
|
||||||
tmp_buf[0] = gdb_hexchars[(((int)th) >> 28) & 0xf];
|
tmp_buf[0] = gdb_hexchars[(((int)th) >> 28) & 0xf];
|
||||||
tmp_buf[1] = gdb_hexchars[(((int)th) >> 24) & 0xf];
|
tmp_buf[1] = gdb_hexchars[(((int)th) >> 24) & 0xf];
|
||||||
tmp_buf[2] = gdb_hexchars[(((int)th) >> 20) & 0xf];
|
tmp_buf[2] = gdb_hexchars[(((int)th) >> 20) & 0xf];
|
||||||
tmp_buf[3] = gdb_hexchars[(((int)th) >> 16) & 0xf];
|
tmp_buf[3] = gdb_hexchars[(((int)th) >> 16) & 0xf];
|
||||||
tmp_buf[4] = gdb_hexchars[(((int)th) >> 12) & 0xf];
|
tmp_buf[4] = gdb_hexchars[(((int)th) >> 12) & 0xf];
|
||||||
tmp_buf[5] = gdb_hexchars[(((int)th) >> 8) & 0xf];
|
tmp_buf[5] = gdb_hexchars[(((int)th) >> 8) & 0xf];
|
||||||
tmp_buf[6] = gdb_hexchars[(((int)th) >> 4) & 0xf];
|
tmp_buf[6] = gdb_hexchars[(((int)th) >> 4) & 0xf];
|
||||||
tmp_buf[7] = gdb_hexchars[((int)th) & 0xf];
|
tmp_buf[7] = gdb_hexchars[((int)th) & 0xf];
|
||||||
tmp_buf[8] = 0;
|
tmp_buf[8] = 0;
|
||||||
|
|
||||||
strcat(info->display, tmp_buf);
|
strcat(info->display, tmp_buf);
|
||||||
|
|
||||||
name = *(unsigned32 *)(obj_info->local_table[thread -
|
name = *(unsigned32 *)(obj_info->local_table[thread -
|
||||||
first_posix_id + 1]->name);
|
first_posix_id + 1]->name);
|
||||||
|
|
||||||
info->name[0] = (name >> 24) & 0xff;
|
info->name[0] = (name >> 24) & 0xff;
|
||||||
info->name[1] = (name >> 16) & 0xff;
|
info->name[1] = (name >> 16) & 0xff;
|
||||||
info->name[2] = (name >> 8) & 0xff;
|
info->name[2] = (name >> 8) & 0xff;
|
||||||
info->name[3] = name & 0xff;
|
info->name[3] = name & 0xff;
|
||||||
info->name[4] = 0;
|
info->name[4] = 0;
|
||||||
|
|
||||||
info->more_display[0] = 0; /* Nothing */
|
info->more_display[0] = 0; /* Nothing */
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************/
|
/*******************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Format: x<type-1x>,<address-x>,<length-x>, where x is 'z' or 'Z' */
|
/* Format: x<type-1x>,<address-x>,<length-x>, where x is 'z' or 'Z' */
|
||||||
int parse_zbreak(const char *in, int *type, unsigned char **addr, int *len)
|
int parse_zbreak(const char *in, int *type, unsigned char **addr, int *len)
|
||||||
{
|
{
|
||||||
@@ -597,27 +648,36 @@ pack_qm_thread(char *out, int thread)
|
|||||||
static void
|
static void
|
||||||
pack_qm_header(char *out, int count, int done, int athread)
|
pack_qm_header(char *out, int count, int done, int athread)
|
||||||
{
|
{
|
||||||
ASSERT(out != 0);
|
ASSERT(out != 0);
|
||||||
ASSERT(count >= 0 && count < 256);
|
ASSERT(count >= 0 && count < 256);
|
||||||
|
|
||||||
*out++ = 'q';
|
*out++ = 'q';
|
||||||
*out++ = 'M';
|
*out++ = 'M';
|
||||||
|
|
||||||
*out++ = gdb_hexchars[(count >> 4) & 0x0f];
|
*out++ = gdb_hexchars[(count >> 4) & 0x0f];
|
||||||
*out++ = gdb_hexchars[count & 0x0f];
|
*out++ = gdb_hexchars[count & 0x0f];
|
||||||
|
|
||||||
if (done) {
|
if (done) {
|
||||||
*out++ = '1';
|
*out++ = '1';
|
||||||
} else {
|
} else {
|
||||||
*out++ = '0';
|
*out++ = '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
thread2fhstr(out, athread);
|
thread2fhstr(out, athread);
|
||||||
|
return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void rtems_gdb_process_query(
|
void rtems_gdb_process_query(
|
||||||
char *inbuffer,
|
char *inbuffer,
|
||||||
char *outbuffer,
|
char *outbuffer,
|
||||||
@@ -642,6 +702,9 @@ void rtems_gdb_process_query(
|
|||||||
*optr = 0;
|
*optr = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case 'P':
|
case 'P':
|
||||||
/* Thread info query */
|
/* Thread info query */
|
||||||
if (!do_threads) {
|
if (!do_threads) {
|
||||||
@@ -669,10 +732,14 @@ void rtems_gdb_process_query(
|
|||||||
/* Build response */
|
/* Build response */
|
||||||
pack_qq(outbuffer, mask, rthread, &info);
|
pack_qq(outbuffer, mask, rthread, &info);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case 'L':
|
case 'L':
|
||||||
/* Thread info query */
|
/* Thread list query */
|
||||||
if (!do_threads) {
|
if (!do_threads) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -724,9 +791,14 @@ void rtems_gdb_process_query(
|
|||||||
|
|
||||||
/* Fill header */
|
/* Fill header */
|
||||||
pack_qm_header(outbuffer, i, done, athread);
|
pack_qm_header(outbuffer, i, done, athread);
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (memcmp(inbuffer, "qOffsets", 8) == 0) {
|
if (memcmp(inbuffer, "qOffsets", 8) == 0) {
|
||||||
unsigned char *t, *d, *b;
|
unsigned char *t, *d, *b;
|
||||||
@@ -772,9 +844,13 @@ void rtems_gdb_process_query(
|
|||||||
/* qCRC, qRcmd, qu and qz will be added here */
|
/* qCRC, qRcmd, qu and qz will be added here */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Present thread in the variable length string format */
|
/* Present thread in the variable length string format */
|
||||||
char*
|
char*
|
||||||
thread2vhstr(char *buf, int thread)
|
thread2vhstr(char *buf, int thread)
|
||||||
@@ -1196,6 +1272,7 @@ set_mem_err (void)
|
|||||||
that the compiler won't save any registers (if there is a fault
|
that the compiler won't save any registers (if there is a fault
|
||||||
to mem_fault, they won't get restored, so there better not be any
|
to mem_fault, they won't get restored, so there better not be any
|
||||||
saved). */
|
saved). */
|
||||||
|
|
||||||
unsigned char
|
unsigned char
|
||||||
get_byte (const unsigned char *addr)
|
get_byte (const unsigned char *addr)
|
||||||
{
|
{
|
||||||
@@ -1210,6 +1287,12 @@ set_byte (unsigned char *addr, int val)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* From here down, the code is CPU model specific and generally maps
|
* From here down, the code is CPU model specific and generally maps
|
||||||
* the RTEMS thread context format to gdb's.
|
* the RTEMS thread context format to gdb's.
|
||||||
@@ -1273,24 +1356,53 @@ int rtems_gdb_stub_get_offsets(
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#elif defined(__mips__)
|
#elif defined(__mips__)
|
||||||
|
|
||||||
|
|
||||||
void rtems_gdb_stub_get_registers_from_context(
|
void rtems_gdb_stub_get_registers_from_context(
|
||||||
int *registers,
|
int *registers,
|
||||||
Thread_Control *th
|
Thread_Control *th
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
registers[S0] = (unsigned)th->Registers.s0;
|
||||||
|
registers[S1] = (unsigned)th->Registers.s1;
|
||||||
|
registers[S2] = (unsigned)th->Registers.s2;
|
||||||
|
registers[S3] = (unsigned)th->Registers.s3;
|
||||||
|
registers[S4] = (unsigned)th->Registers.s4;
|
||||||
|
registers[S5] = (unsigned)th->Registers.s5;
|
||||||
|
registers[S6] = (unsigned)th->Registers.s6;
|
||||||
|
registers[S7] = (unsigned)th->Registers.s7;
|
||||||
|
|
||||||
|
registers[SP] = (unsigned)th->Registers.sp;
|
||||||
|
registers[RA] = (unsigned)th->Registers.ra;
|
||||||
|
|
||||||
|
registers[SR] = (unsigned)th->Registers.c0_sr;
|
||||||
|
registers[PC] = (unsigned)th->Registers.c0_epc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int rtems_gdb_stub_get_offsets(
|
int rtems_gdb_stub_get_offsets(
|
||||||
unsigned char **text_addr,
|
unsigned char **text_addr,
|
||||||
unsigned char **data_addr,
|
unsigned char **data_addr,
|
||||||
unsigned char **bss_addr
|
unsigned char **bss_addr
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
extern unsigned32 _ftext;
|
||||||
|
extern unsigned32 _fdata;
|
||||||
|
extern unsigned32 _bss_start;
|
||||||
|
|
||||||
|
*text_addr = &_ftext;
|
||||||
|
*data_addr = &_fdata;
|
||||||
|
*bss_addr = &_bss_start;
|
||||||
|
*/
|
||||||
*text_addr = 0;
|
*text_addr = 0;
|
||||||
*data_addr = 0;
|
*data_addr = 0;
|
||||||
*bss_addr = 0;
|
*bss_addr = 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <rtems.h>
|
#include <rtems.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "gdb_if.h"
|
#include "gdb_if.h"
|
||||||
@@ -40,6 +39,7 @@
|
|||||||
|
|
||||||
extern const char gdb_hexchars[];
|
extern const char gdb_hexchars[];
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prototypes for CPU dependent routines that are conditional
|
* Prototypes for CPU dependent routines that are conditional
|
||||||
* at the bottom of this file.
|
* at the bottom of this file.
|
||||||
@@ -50,6 +50,12 @@ void rtems_gdb_stub_get_registers_from_context(
|
|||||||
Thread_Control *th
|
Thread_Control *th
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Check whether it is OK to enable thread support */
|
/* Check whether it is OK to enable thread support */
|
||||||
int rtems_gdb_stub_thread_support_ok(void)
|
int rtems_gdb_stub_thread_support_ok(void)
|
||||||
{
|
{
|
||||||
@@ -59,6 +65,10 @@ int rtems_gdb_stub_thread_support_ok(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* rtems_gdb_stub_id_to_index
|
* rtems_gdb_stub_id_to_index
|
||||||
*
|
*
|
||||||
@@ -101,12 +111,84 @@ int rtems_gdb_stub_id_to_index(
|
|||||||
return first_posix_id + (thread_obj_id - min_id);
|
return first_posix_id + (thread_obj_id - min_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Return the RTEMS thread id from a gdb thread id */
|
||||||
|
Thread_Control *rtems_gdb_index_to_stub_id(
|
||||||
|
int thread
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Objects_Id thread_obj_id;
|
||||||
|
Objects_Id min_id, max_id;
|
||||||
|
int first_posix_id, first_rtems_id;
|
||||||
|
Objects_Information *obj_info;
|
||||||
|
Thread_Control *th;
|
||||||
|
|
||||||
|
ASSERT(registers != NULL);
|
||||||
|
|
||||||
|
if (_System_state_Get() != SYSTEM_STATE_UP || thread <= 0) {
|
||||||
|
/* Should not happen */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thread == 1) {
|
||||||
|
th = _Thread_Idle;
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let us get object associtated with current thread */
|
||||||
|
first_rtems_id = 2;
|
||||||
|
|
||||||
|
thread_obj_id = _Thread_Executing->Object.id;
|
||||||
|
|
||||||
|
/* Let us figure out thread_id for gdb */
|
||||||
|
obj_info = _Objects_Information_table[OBJECTS_RTEMS_TASKS];
|
||||||
|
|
||||||
|
min_id = obj_info->minimum_id;
|
||||||
|
max_id = obj_info->maximum_id;
|
||||||
|
|
||||||
|
if (thread <= (first_rtems_id + (max_id - min_id))) {
|
||||||
|
th = (Thread_Control *)(obj_info->local_table[thread - first_rtems_id + 1]);
|
||||||
|
|
||||||
|
if (th != NULL) {
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Thread does not exist */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
first_posix_id = first_rtems_id + (max_id - min_id) + 1;
|
||||||
|
|
||||||
|
obj_info = _Objects_Information_table[OBJECTS_POSIX_THREADS];
|
||||||
|
|
||||||
|
min_id = obj_info->minimum_id;
|
||||||
|
max_id = obj_info->maximum_id;
|
||||||
|
|
||||||
|
th = (Thread_Control *)(obj_info->local_table[thread - first_posix_id + 1]);
|
||||||
|
if (th == NULL) {
|
||||||
|
/* Thread does not exist */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
found:
|
||||||
|
return th;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Get id of the thread stopped by exception */
|
/* Get id of the thread stopped by exception */
|
||||||
int rtems_gdb_stub_get_current_thread(void)
|
int rtems_gdb_stub_get_current_thread(void)
|
||||||
{
|
{
|
||||||
return rtems_gdb_stub_id_to_index( _Thread_Executing->Object.id );
|
return rtems_gdb_stub_id_to_index( _Thread_Executing->Object.id );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Get id of the next thread after athread, if argument <= 0 find the
|
/* Get id of the next thread after athread, if argument <= 0 find the
|
||||||
first available thread, return thread if found or 0 if not */
|
first available thread, return thread if found or 0 if not */
|
||||||
int rtems_gdb_stub_get_next_thread(int athread)
|
int rtems_gdb_stub_get_next_thread(int athread)
|
||||||
@@ -176,6 +258,10 @@ int rtems_gdb_stub_get_next_thread(int athread)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Get thread registers, return 0 if thread does not
|
/* Get thread registers, return 0 if thread does not
|
||||||
exist, and 1 otherwise */
|
exist, and 1 otherwise */
|
||||||
int rtems_gdb_stub_get_thread_regs(
|
int rtems_gdb_stub_get_thread_regs(
|
||||||
@@ -183,70 +269,27 @@ int rtems_gdb_stub_get_thread_regs(
|
|||||||
unsigned int *registers
|
unsigned int *registers
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Objects_Id thread_obj_id;
|
Thread_Control *th;
|
||||||
Objects_Id min_id, max_id;
|
|
||||||
int first_posix_id, first_rtems_id;
|
|
||||||
Objects_Information *obj_info;
|
|
||||||
Thread_Control *th;
|
|
||||||
|
|
||||||
ASSERT(registers != NULL);
|
th= rtems_gdb_index_to_stub_id(thread);
|
||||||
|
|
||||||
if (_System_state_Get() != SYSTEM_STATE_UP || thread <= 0) {
|
if( th )
|
||||||
/* Should not happen */
|
{
|
||||||
return 0;
|
rtems_gdb_stub_get_registers_from_context( registers, th );
|
||||||
}
|
return 1;
|
||||||
|
}
|
||||||
if (thread == 1) {
|
return 0;
|
||||||
th = _Thread_Idle;
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Let us get object associtated with current thread */
|
|
||||||
first_rtems_id = 2;
|
|
||||||
|
|
||||||
thread_obj_id = _Thread_Executing->Object.id;
|
|
||||||
|
|
||||||
/* Let us figure out thread_id for gdb */
|
|
||||||
obj_info = _Objects_Information_table[OBJECTS_RTEMS_TASKS];
|
|
||||||
|
|
||||||
min_id = obj_info->minimum_id;
|
|
||||||
max_id = obj_info->maximum_id;
|
|
||||||
|
|
||||||
if (thread <= (first_rtems_id + (max_id - min_id))) {
|
|
||||||
th = (Thread_Control *)(obj_info->local_table[thread - first_rtems_id + 1]);
|
|
||||||
|
|
||||||
if (th != NULL) {
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Thread does not exist */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
first_posix_id = first_rtems_id + (max_id - min_id) + 1;
|
|
||||||
|
|
||||||
obj_info = _Objects_Information_table[OBJECTS_POSIX_THREADS];
|
|
||||||
|
|
||||||
min_id = obj_info->minimum_id;
|
|
||||||
max_id = obj_info->maximum_id;
|
|
||||||
|
|
||||||
th = (Thread_Control *)(obj_info->local_table[thread - first_posix_id + 1]);
|
|
||||||
if (th == NULL) {
|
|
||||||
/* Thread does not exist */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
found:
|
|
||||||
|
|
||||||
rtems_gdb_stub_get_registers_from_context( registers, th );
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Set thread registers, return 0 if thread does not
|
/* Set thread registers, return 0 if thread does not
|
||||||
exist or register values will screw up the threads,
|
exist or register values will screw up the threads,
|
||||||
and 1 otherwise */
|
and 1 otherwise */
|
||||||
|
|
||||||
int rtems_gdb_stub_set_thread_regs(
|
int rtems_gdb_stub_set_thread_regs(
|
||||||
int thread,
|
int thread,
|
||||||
unsigned int *registers
|
unsigned int *registers
|
||||||
@@ -260,6 +303,10 @@ int rtems_gdb_stub_set_thread_regs(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Get thread information, return 0 if thread does not
|
/* Get thread information, return 0 if thread does not
|
||||||
exist and 1 otherwise */
|
exist and 1 otherwise */
|
||||||
int rtems_gdb_stub_get_thread_info(
|
int rtems_gdb_stub_get_thread_info(
|
||||||
@@ -267,122 +314,126 @@ int rtems_gdb_stub_get_thread_info(
|
|||||||
struct rtems_gdb_stub_thread_info *info
|
struct rtems_gdb_stub_thread_info *info
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Objects_Id thread_obj_id;
|
Objects_Id thread_obj_id;
|
||||||
Objects_Id min_id, max_id;
|
Objects_Id min_id, max_id;
|
||||||
int first_posix_id, first_rtems_id;
|
int first_posix_id, first_rtems_id;
|
||||||
Objects_Information *obj_info;
|
Objects_Information *obj_info;
|
||||||
Thread_Control *th;
|
Thread_Control *th;
|
||||||
unsigned32 name;
|
unsigned32 name;
|
||||||
char tmp_buf[20];
|
char tmp_buf[20];
|
||||||
|
|
||||||
ASSERT(info != NULL);
|
ASSERT(info != NULL);
|
||||||
|
|
||||||
if (thread <= 0) {
|
if (thread <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_System_state_Get() != SYSTEM_STATE_UP || thread == 1) {
|
if (_System_state_Get() != SYSTEM_STATE_UP || thread == 1) {
|
||||||
/* We have one thread let us use value
|
/* We have one thread let us use value
|
||||||
which will never happen for real thread */
|
which will never happen for real thread */
|
||||||
strcpy(info->display, "idle thread");
|
strcpy(info->display, "idle thread");
|
||||||
strcpy(info->name, "IDLE");
|
strcpy(info->name, "IDLE");
|
||||||
info->more_display[0] = 0; /* Nothing */
|
info->more_display[0] = 0; /* Nothing */
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Let us get object associtated with current thread */
|
/* Let us get object associtated with current thread */
|
||||||
thread_obj_id = _Thread_Executing->Object.id;
|
thread_obj_id = _Thread_Executing->Object.id;
|
||||||
|
|
||||||
/* Let us figure out thread_id for gdb */
|
/* Let us figure out thread_id for gdb */
|
||||||
first_rtems_id = 2;
|
first_rtems_id = 2;
|
||||||
|
|
||||||
obj_info = _Objects_Information_table[OBJECTS_RTEMS_TASKS];
|
obj_info = _Objects_Information_table[OBJECTS_RTEMS_TASKS];
|
||||||
|
|
||||||
min_id = obj_info->minimum_id;
|
min_id = obj_info->minimum_id;
|
||||||
max_id = obj_info->maximum_id;
|
max_id = obj_info->maximum_id;
|
||||||
|
|
||||||
if (thread <= (first_rtems_id + (max_id - min_id))) {
|
if (thread <= (first_rtems_id + (max_id - min_id))) {
|
||||||
th = (Thread_Control *)(obj_info->local_table[thread -
|
th = (Thread_Control *)(obj_info->local_table[thread -
|
||||||
first_rtems_id + 1]);
|
first_rtems_id + 1]);
|
||||||
|
|
||||||
if (th == NULL) {
|
if (th == NULL) {
|
||||||
/* Thread does not exist */
|
/* Thread does not exist */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(info->display, "rtems task: control at 0x");
|
strcpy(info->display, "rtems task: control at 0x");
|
||||||
|
|
||||||
tmp_buf[0] = gdb_hexchars[(((int)th) >> 28) & 0xf];
|
tmp_buf[0] = gdb_hexchars[(((int)th) >> 28) & 0xf];
|
||||||
tmp_buf[1] = gdb_hexchars[(((int)th) >> 24) & 0xf];
|
tmp_buf[1] = gdb_hexchars[(((int)th) >> 24) & 0xf];
|
||||||
tmp_buf[2] = gdb_hexchars[(((int)th) >> 20) & 0xf];
|
tmp_buf[2] = gdb_hexchars[(((int)th) >> 20) & 0xf];
|
||||||
tmp_buf[3] = gdb_hexchars[(((int)th) >> 16) & 0xf];
|
tmp_buf[3] = gdb_hexchars[(((int)th) >> 16) & 0xf];
|
||||||
tmp_buf[4] = gdb_hexchars[(((int)th) >> 12) & 0xf];
|
tmp_buf[4] = gdb_hexchars[(((int)th) >> 12) & 0xf];
|
||||||
tmp_buf[5] = gdb_hexchars[(((int)th) >> 8) & 0xf];
|
tmp_buf[5] = gdb_hexchars[(((int)th) >> 8) & 0xf];
|
||||||
tmp_buf[6] = gdb_hexchars[(((int)th) >> 4) & 0xf];
|
tmp_buf[6] = gdb_hexchars[(((int)th) >> 4) & 0xf];
|
||||||
tmp_buf[7] = gdb_hexchars[((int)th) & 0xf];
|
tmp_buf[7] = gdb_hexchars[((int)th) & 0xf];
|
||||||
tmp_buf[8] = 0;
|
tmp_buf[8] = 0;
|
||||||
|
|
||||||
strcat(info->display, tmp_buf);
|
strcat(info->display, tmp_buf);
|
||||||
|
|
||||||
name = *(unsigned32 *)(obj_info->local_table[thread]->name);
|
name = *(unsigned32 *)(obj_info->local_table[thread]->name);
|
||||||
|
|
||||||
info->name[0] = (name >> 24) & 0xff;
|
info->name[0] = (name >> 24) & 0xff;
|
||||||
info->name[1] = (name >> 16) & 0xff;
|
info->name[1] = (name >> 16) & 0xff;
|
||||||
info->name[2] = (name >> 8) & 0xff;
|
info->name[2] = (name >> 8) & 0xff;
|
||||||
info->name[3] = name & 0xff;
|
info->name[3] = name & 0xff;
|
||||||
info->name[4] = 0;
|
info->name[4] = 0;
|
||||||
|
|
||||||
info->more_display[0] = 0; /* Nothing */
|
info->more_display[0] = 0; /* Nothing */
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
first_posix_id = first_rtems_id + (max_id - min_id) + 1;
|
first_posix_id = first_rtems_id + (max_id - min_id) + 1;
|
||||||
|
|
||||||
obj_info = _Objects_Information_table[OBJECTS_POSIX_THREADS];
|
obj_info = _Objects_Information_table[OBJECTS_POSIX_THREADS];
|
||||||
|
|
||||||
min_id = obj_info->minimum_id;
|
min_id = obj_info->minimum_id;
|
||||||
max_id = obj_info->maximum_id;
|
max_id = obj_info->maximum_id;
|
||||||
|
|
||||||
th = (Thread_Control *)(obj_info->local_table[thread - first_posix_id + 1]);
|
th = (Thread_Control *)(obj_info->local_table[thread - first_posix_id + 1]);
|
||||||
if (th == NULL)
|
if (th == NULL)
|
||||||
{
|
{
|
||||||
/* Thread does not exist */
|
/* Thread does not exist */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(info->display, "posix thread: control at 0x");
|
strcpy(info->display, "posix thread: control at 0x");
|
||||||
|
|
||||||
tmp_buf[0] = gdb_hexchars[(((int)th) >> 28) & 0xf];
|
tmp_buf[0] = gdb_hexchars[(((int)th) >> 28) & 0xf];
|
||||||
tmp_buf[1] = gdb_hexchars[(((int)th) >> 24) & 0xf];
|
tmp_buf[1] = gdb_hexchars[(((int)th) >> 24) & 0xf];
|
||||||
tmp_buf[2] = gdb_hexchars[(((int)th) >> 20) & 0xf];
|
tmp_buf[2] = gdb_hexchars[(((int)th) >> 20) & 0xf];
|
||||||
tmp_buf[3] = gdb_hexchars[(((int)th) >> 16) & 0xf];
|
tmp_buf[3] = gdb_hexchars[(((int)th) >> 16) & 0xf];
|
||||||
tmp_buf[4] = gdb_hexchars[(((int)th) >> 12) & 0xf];
|
tmp_buf[4] = gdb_hexchars[(((int)th) >> 12) & 0xf];
|
||||||
tmp_buf[5] = gdb_hexchars[(((int)th) >> 8) & 0xf];
|
tmp_buf[5] = gdb_hexchars[(((int)th) >> 8) & 0xf];
|
||||||
tmp_buf[6] = gdb_hexchars[(((int)th) >> 4) & 0xf];
|
tmp_buf[6] = gdb_hexchars[(((int)th) >> 4) & 0xf];
|
||||||
tmp_buf[7] = gdb_hexchars[((int)th) & 0xf];
|
tmp_buf[7] = gdb_hexchars[((int)th) & 0xf];
|
||||||
tmp_buf[8] = 0;
|
tmp_buf[8] = 0;
|
||||||
|
|
||||||
strcat(info->display, tmp_buf);
|
strcat(info->display, tmp_buf);
|
||||||
|
|
||||||
name = *(unsigned32 *)(obj_info->local_table[thread -
|
name = *(unsigned32 *)(obj_info->local_table[thread -
|
||||||
first_posix_id + 1]->name);
|
first_posix_id + 1]->name);
|
||||||
|
|
||||||
info->name[0] = (name >> 24) & 0xff;
|
info->name[0] = (name >> 24) & 0xff;
|
||||||
info->name[1] = (name >> 16) & 0xff;
|
info->name[1] = (name >> 16) & 0xff;
|
||||||
info->name[2] = (name >> 8) & 0xff;
|
info->name[2] = (name >> 8) & 0xff;
|
||||||
info->name[3] = name & 0xff;
|
info->name[3] = name & 0xff;
|
||||||
info->name[4] = 0;
|
info->name[4] = 0;
|
||||||
|
|
||||||
info->more_display[0] = 0; /* Nothing */
|
info->more_display[0] = 0; /* Nothing */
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************/
|
/*******************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Format: x<type-1x>,<address-x>,<length-x>, where x is 'z' or 'Z' */
|
/* Format: x<type-1x>,<address-x>,<length-x>, where x is 'z' or 'Z' */
|
||||||
int parse_zbreak(const char *in, int *type, unsigned char **addr, int *len)
|
int parse_zbreak(const char *in, int *type, unsigned char **addr, int *len)
|
||||||
{
|
{
|
||||||
@@ -597,27 +648,36 @@ pack_qm_thread(char *out, int thread)
|
|||||||
static void
|
static void
|
||||||
pack_qm_header(char *out, int count, int done, int athread)
|
pack_qm_header(char *out, int count, int done, int athread)
|
||||||
{
|
{
|
||||||
ASSERT(out != 0);
|
ASSERT(out != 0);
|
||||||
ASSERT(count >= 0 && count < 256);
|
ASSERT(count >= 0 && count < 256);
|
||||||
|
|
||||||
*out++ = 'q';
|
*out++ = 'q';
|
||||||
*out++ = 'M';
|
*out++ = 'M';
|
||||||
|
|
||||||
*out++ = gdb_hexchars[(count >> 4) & 0x0f];
|
*out++ = gdb_hexchars[(count >> 4) & 0x0f];
|
||||||
*out++ = gdb_hexchars[count & 0x0f];
|
*out++ = gdb_hexchars[count & 0x0f];
|
||||||
|
|
||||||
if (done) {
|
if (done) {
|
||||||
*out++ = '1';
|
*out++ = '1';
|
||||||
} else {
|
} else {
|
||||||
*out++ = '0';
|
*out++ = '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
thread2fhstr(out, athread);
|
thread2fhstr(out, athread);
|
||||||
|
return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void rtems_gdb_process_query(
|
void rtems_gdb_process_query(
|
||||||
char *inbuffer,
|
char *inbuffer,
|
||||||
char *outbuffer,
|
char *outbuffer,
|
||||||
@@ -642,6 +702,9 @@ void rtems_gdb_process_query(
|
|||||||
*optr = 0;
|
*optr = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case 'P':
|
case 'P':
|
||||||
/* Thread info query */
|
/* Thread info query */
|
||||||
if (!do_threads) {
|
if (!do_threads) {
|
||||||
@@ -669,10 +732,14 @@ void rtems_gdb_process_query(
|
|||||||
/* Build response */
|
/* Build response */
|
||||||
pack_qq(outbuffer, mask, rthread, &info);
|
pack_qq(outbuffer, mask, rthread, &info);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case 'L':
|
case 'L':
|
||||||
/* Thread info query */
|
/* Thread list query */
|
||||||
if (!do_threads) {
|
if (!do_threads) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -724,9 +791,14 @@ void rtems_gdb_process_query(
|
|||||||
|
|
||||||
/* Fill header */
|
/* Fill header */
|
||||||
pack_qm_header(outbuffer, i, done, athread);
|
pack_qm_header(outbuffer, i, done, athread);
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (memcmp(inbuffer, "qOffsets", 8) == 0) {
|
if (memcmp(inbuffer, "qOffsets", 8) == 0) {
|
||||||
unsigned char *t, *d, *b;
|
unsigned char *t, *d, *b;
|
||||||
@@ -772,9 +844,13 @@ void rtems_gdb_process_query(
|
|||||||
/* qCRC, qRcmd, qu and qz will be added here */
|
/* qCRC, qRcmd, qu and qz will be added here */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Present thread in the variable length string format */
|
/* Present thread in the variable length string format */
|
||||||
char*
|
char*
|
||||||
thread2vhstr(char *buf, int thread)
|
thread2vhstr(char *buf, int thread)
|
||||||
@@ -1196,6 +1272,7 @@ set_mem_err (void)
|
|||||||
that the compiler won't save any registers (if there is a fault
|
that the compiler won't save any registers (if there is a fault
|
||||||
to mem_fault, they won't get restored, so there better not be any
|
to mem_fault, they won't get restored, so there better not be any
|
||||||
saved). */
|
saved). */
|
||||||
|
|
||||||
unsigned char
|
unsigned char
|
||||||
get_byte (const unsigned char *addr)
|
get_byte (const unsigned char *addr)
|
||||||
{
|
{
|
||||||
@@ -1210,6 +1287,12 @@ set_byte (unsigned char *addr, int val)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* From here down, the code is CPU model specific and generally maps
|
* From here down, the code is CPU model specific and generally maps
|
||||||
* the RTEMS thread context format to gdb's.
|
* the RTEMS thread context format to gdb's.
|
||||||
@@ -1273,24 +1356,53 @@ int rtems_gdb_stub_get_offsets(
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#elif defined(__mips__)
|
#elif defined(__mips__)
|
||||||
|
|
||||||
|
|
||||||
void rtems_gdb_stub_get_registers_from_context(
|
void rtems_gdb_stub_get_registers_from_context(
|
||||||
int *registers,
|
int *registers,
|
||||||
Thread_Control *th
|
Thread_Control *th
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
registers[S0] = (unsigned)th->Registers.s0;
|
||||||
|
registers[S1] = (unsigned)th->Registers.s1;
|
||||||
|
registers[S2] = (unsigned)th->Registers.s2;
|
||||||
|
registers[S3] = (unsigned)th->Registers.s3;
|
||||||
|
registers[S4] = (unsigned)th->Registers.s4;
|
||||||
|
registers[S5] = (unsigned)th->Registers.s5;
|
||||||
|
registers[S6] = (unsigned)th->Registers.s6;
|
||||||
|
registers[S7] = (unsigned)th->Registers.s7;
|
||||||
|
|
||||||
|
registers[SP] = (unsigned)th->Registers.sp;
|
||||||
|
registers[RA] = (unsigned)th->Registers.ra;
|
||||||
|
|
||||||
|
registers[SR] = (unsigned)th->Registers.c0_sr;
|
||||||
|
registers[PC] = (unsigned)th->Registers.c0_epc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int rtems_gdb_stub_get_offsets(
|
int rtems_gdb_stub_get_offsets(
|
||||||
unsigned char **text_addr,
|
unsigned char **text_addr,
|
||||||
unsigned char **data_addr,
|
unsigned char **data_addr,
|
||||||
unsigned char **bss_addr
|
unsigned char **bss_addr
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
extern unsigned32 _ftext;
|
||||||
|
extern unsigned32 _fdata;
|
||||||
|
extern unsigned32 _bss_start;
|
||||||
|
|
||||||
|
*text_addr = &_ftext;
|
||||||
|
*data_addr = &_fdata;
|
||||||
|
*bss_addr = &_bss_start;
|
||||||
|
*/
|
||||||
*text_addr = 0;
|
*text_addr = 0;
|
||||||
*data_addr = 0;
|
*data_addr = 0;
|
||||||
*bss_addr = 0;
|
*bss_addr = 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user