OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [kernel/] [v2_0/] [src/] [debug/] [dbg_gdb.cxx] - Blame information for rev 307

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
/*==========================================================================
2
//
3
//      dbg_gdb.c
4
//
5
//      GDB Debugging Interface
6
//
7
//==========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//==========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):   nickg
44
// Contributors:        nickg
45
// Date:        1998-08-22
46
// Purpose:     GDB Debugging Interface
47
// Description: Interface for calls from GDB stubs into the OS. These
48
//              currently mostly support thread awareness.
49
//
50
//####DESCRIPTIONEND####
51
//
52
//========================================================================*/
53
 
54
#include <pkgconf/kernel.h>
55
#include <pkgconf/hal.h>                // CYG_HAL_USE_ROM_MONITOR_CYGMON
56
 
57
#ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT
58
 
59
#include <cyg/kernel/ktypes.h>
60
 
61
#include <cyg/kernel/thread.hxx>
62
#include <cyg/kernel/sched.hxx>
63
 
64
#include <cyg/kernel/thread.inl>
65
#include <cyg/kernel/sched.inl>
66
 
67
#include <cyg/hal/hal_arch.h>
68
#include <cyg/hal/hal_stub.h>
69
 
70
extern "C"
71
{
72
#include <cyg/hal/dbg-threads-api.h>
73
};
74
 
75
#define USE_ID 1
76
 
77
#if (CYG_BYTEORDER == CYG_LSBFIRST)
78
 
79
unsigned long swap32(unsigned long x)
80
{
81
    unsigned long r = 0;
82
 
83
    r |= (x>>24)&0xFF;
84
    r |= ((x>>16)&0xFF)<<8;
85
    r |= ((x>>8)&0xFF)<<16;
86
    r |= ((x)&0xFF)<<24;
87
 
88
    return r;
89
}
90
 
91
#else
92
 
93
#define swap32(x) ((unsigned long)(x))
94
 
95
#endif
96
 
97
//--------------------------------------------------------------------------
98
 
99
externC int dbg_thread_capabilities(struct dbg_capabilities * cpb)
100
{
101
    cpb->mask1 = has_thread_current     |
102
        has_thread_registers            |
103
        has_thread_reg_change           |
104
        has_thread_list                 |
105
        has_thread_info                 ;
106
    return 1 ;
107
}
108
 
109
//--------------------------------------------------------------------------
110
 
111
static void dbg_make_threadref(Cyg_Thread *thread, threadref *ref )
112
{
113
    // The following test tries to avoid accessing uninitialized pointers.
114
    // This can happen if we take a breakpoint before the data is copied
115
    // or the BSS zeroed. We currently assume that RAM will reset to zero
116
    // or 0xff. If it is random, we have no hope.
117
 
118
    if( (CYG_ADDRWORD)thread == 0 || (CYG_ADDRWORD)thread == 0xffffffff )
119
    {
120
        ((unsigned long *)ref)[0] = 0;
121
        ((unsigned long *)ref)[1] = 0;
122
    }
123
    else
124
    {
125
        cyg_uint16 id = thread->get_unique_id();
126
 
127
#if USE_ID
128
        ((unsigned long *)ref)[0] = (unsigned long)thread;
129
        ((unsigned long *)ref)[1] = (unsigned long)swap32(id);
130
#else    
131
        ((unsigned long *)ref)[1] = (unsigned long)thread;
132
        ((unsigned long *)ref)[0] = (unsigned long)id;
133
#endif
134
    }
135
}
136
 
137
static Cyg_Thread *dbg_get_thread( threadref *ref)
138
{
139
#if USE_ID
140
 
141
    cyg_uint16 id = 0;
142
 
143
    id = (cyg_uint16)swap32(((unsigned long *)ref)[1]);
144
 
145
    Cyg_Thread *th = Cyg_Thread::get_list_head();
146
    while( th != 0 )
147
    {
148
        if( th->get_unique_id() == id ) break;
149
        th = th->get_list_next();
150
    }
151
 
152
//    if( thread->get_unique_id() != id ) th = 0;
153
 
154
#else
155
 
156
    cyg_uint16 id = 0;
157
 
158
    Cyg_Thread *thread = (Cyg_Thread *)(((unsigned long *)ref)[1]);
159
    id = (cyg_uint16)(((unsigned long *)ref)[0]);
160
 
161
    // Validate the thread.
162
    Cyg_Thread *th = Cyg_Thread::get_list_head();
163
    while( th != 0 )
164
    {
165
        if( th == thread ) break;
166
        th = th->get_list_next();
167
    }
168
 
169
//    if( thread->get_unique_id() != id ) th = 0;
170
 
171
#endif
172
 
173
    return th;
174
}
175
 
176
//--------------------------------------------------------------------------
177
 
178
externC int dbg_currthread(threadref * varparm)
179
{
180
    Cyg_Thread *thread = Cyg_Scheduler::get_current_thread();
181
 
182
    dbg_make_threadref(thread, varparm );
183
 
184
    return 1 ;
185
}
186
 
187
//--------------------------------------------------------------------------
188
 
189
externC int dbg_thread_id(threadref *threadid)
190
{
191
    Cyg_Thread *thread = dbg_get_thread(threadid);
192
    if( thread == 0 ) return 0;
193
    return thread->get_unique_id ();
194
}
195
 
196
//--------------------------------------------------------------------------
197
 
198
externC int dbg_currthread_id(void)
199
{
200
    Cyg_Thread *thread = Cyg_Scheduler::get_current_thread();
201
    return thread->get_unique_id ();
202
}
203
 
204
//--------------------------------------------------------------------------
205
 
206
externC int dbg_threadlist(int startflag,
207
                   threadref * lastthreadid,
208
                   threadref * next_thread)
209
{
210
    Cyg_Thread *thread;
211
    if( startflag )
212
    {
213
        thread = Cyg_Thread::get_list_head();
214
        dbg_make_threadref(thread, next_thread);
215
    }
216
    else
217
    {
218
        thread = dbg_get_thread(lastthreadid);
219
 
220
        if( thread == 0 ) return 0;
221
        thread = thread->get_list_next();
222
 
223
        if( thread == 0 ) return 0;
224
        dbg_make_threadref(thread, next_thread);
225
    }
226
    return 1 ;
227
}
228
 
229
//--------------------------------------------------------------------------
230
// Some support routines for manufacturing thread info strings
231
 
232
static char *dbg_addstr(char *s, char *t)
233
{
234
    while( (*s++ = *t++) != 0 );
235
 
236
    return s-1;
237
}
238
 
239
static char *dbg_addint(char *s, int n, int base)
240
{
241
    char buf[16];
242
    char sign = '+';
243
    cyg_count8 bpos;
244
    char *digits = "0123456789ABCDEF";
245
 
246
    if( n < 0 ) n = -n, sign = '-';
247
 
248
    /* Set pos to start */
249
    bpos = 0;
250
 
251
    /* construct digits into buffer in reverse order */
252
    if( n == 0 ) buf[bpos++] = '0';
253
    else while( n != 0 )
254
    {
255
        cyg_ucount8 d = n % base;
256
        buf[bpos++] = digits[d];
257
        n /= base;
258
    }
259
 
260
    /* set sign if negative. */
261
    if( sign == '-' )
262
    {
263
        buf[bpos] = sign;
264
    }
265
    else bpos--;
266
 
267
    /* Now write it out in correct order. */
268
    while( bpos >= 0 )
269
        *s++ = buf[bpos--];
270
 
271
    *s = 0;
272
 
273
    return s;
274
}
275
 
276
static char *dbg_adddec(char *s, int x)
277
{
278
    return dbg_addint(s, x, 10);
279
}
280
 
281
//--------------------------------------------------------------------------
282
 
283
externC int dbg_threadinfo(
284
                   threadref * threadid,
285
                   struct cygmon_thread_debug_info * info)
286
{
287
    static char statebuf[60];
288
 
289
    Cyg_Thread *thread = dbg_get_thread(threadid);
290
    if( thread == 0 ) return 0;
291
 
292
    info->context_exists        = 1;
293
 
294
    char *sbp = statebuf;
295
    char *s;
296
 
297
    if( thread->get_state() & Cyg_Thread::SUSPENDED )
298
    {
299
        sbp = dbg_addstr( sbp, "suspended+");
300
    }
301
 
302
    switch( thread->get_state() & ~Cyg_Thread::SUSPENDED )
303
    {
304
    case Cyg_Thread::RUNNING:
305
        if ( Cyg_Scheduler::get_current_thread() == thread ) {
306
            s = "running";              break;
307
        }
308
        else if ( thread->get_state() & Cyg_Thread::SUSPENDED ) {
309
            s = ""; sbp--; /*kill '+'*/ break;
310
        }
311
        else {
312
            s = "ready";                break;
313
        }
314
    case Cyg_Thread::SLEEPING:
315
        s = "sleeping";                 break;
316
    case Cyg_Thread::COUNTSLEEP | Cyg_Thread::SLEEPING:
317
    case Cyg_Thread::COUNTSLEEP:
318
        s = "counted sleep";            break;
319
    case Cyg_Thread::CREATING:
320
        s = "creating"; sbp = statebuf; break;
321
    case Cyg_Thread::EXITED:
322
        s = "exited"; sbp = statebuf;   break;
323
    default:
324
        s = "unknown state";            break;
325
    }
326
 
327
    sbp = dbg_addstr( sbp, s );
328
    sbp = dbg_addstr( sbp, ", Priority: " );
329
    sbp = dbg_adddec( sbp, thread->get_priority() );
330
 
331
    info->thread_display        = statebuf;
332
 
333
#ifdef CYGVAR_KERNEL_THREADS_NAME
334
    info->unique_thread_name    = thread->get_name();
335
#else
336
    info->unique_thread_name    = 0;
337
#endif
338
 
339
    info->more_display          = 0;
340
 
341
    return 1 ;
342
}
343
 
344
//--------------------------------------------------------------------------
345
 
346
externC int dbg_getthreadreg(
347
                     threadref * osthreadid,
348
                     int regcount, /* count of registers in the array */
349
                     void * regval)  /* fillin this array */
350
{
351
    Cyg_Thread *thread = dbg_get_thread(osthreadid);
352
 
353
    if( thread == 0 ) return 0;
354
 
355
    if( thread == Cyg_Scheduler::get_current_thread() )
356
    {
357
#if defined(CYG_HAL_USE_ROM_MONITOR_CYGMON)
358
        // We have no state for the current thread, Cygmon has
359
        // got that and we cannot get at it.
360
        return 0;
361
#elif defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
362
        // registers hold the state of the current thread.
363
        __stub_copy_registers ((target_register_t *)regval, registers);
364
#else
365
        return 0;
366
#endif
367
    }
368
    else
369
    {
370
        HAL_SavedRegisters *regs = thread->get_saved_context();
371
        if( regs == 0 ) return 0;
372
 
373
        HAL_GET_GDB_REGISTERS (regval, regs);
374
    }
375
 
376
    return 1 ;
377
}
378
 
379
//--------------------------------------------------------------------------
380
 
381
externC int dbg_setthreadreg(
382
                            threadref * osthreadid,
383
                            int regcount , /* number of registers */
384
                            void * regval)
385
{
386
    Cyg_Thread *thread = dbg_get_thread(osthreadid);
387
 
388
    if( thread == 0 ) return 0;
389
 
390
    if( thread == Cyg_Scheduler::get_current_thread() )
391
    {
392
#if defined(CYG_HAL_USE_ROM_MONITOR_CYGMON)
393
        // We have no state for the current thread, Cygmon has
394
        // got that and we cannot get at it.
395
        return 0;
396
#elif defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
397
        // registers hold the state of the current thread.
398
        __stub_copy_registers (registers, (target_register_t *)regval);
399
#else
400
        return 0;
401
#endif
402
    }
403
    else
404
    {
405
        HAL_SavedRegisters *regs = thread->get_saved_context();
406
        if( regs == 0 ) return 0;
407
 
408
        HAL_SET_GDB_REGISTERS (regs, regval);
409
    }
410
 
411
    return 1;
412
}
413
 
414
//--------------------------------------------------------------------------
415
// Thread scheduler control for debugger.
416
// Arguments:
417
//      osthreadid      : must match currently executing thread.
418
//                        Future use: change the currently executing thread.
419
//      lock            : 0 == unlock scheduler, 1 == lock scheduler
420
//      mode            : 0 == single-instruction step, 1 == free running
421
//
422
// Return values:
423
// 1  == success
424
// 0  == failure
425
// -1 == request that the caller handle this itself
426
//       (eg.by disabling interrupts)
427
//
428
 
429
externC int dbg_scheduler(
430
                          threadref * osthreadid,
431
                          int lock,     /* 0 == unlock, 1 == lock */
432
                          int mode)     /* 0 == step,   1 == continue */
433
{
434
#if 0
435
    /* Minimal implementation: let stub do the work.  */
436
    return -1;                          // Stub will disable interrupts
437
#else
438
    Cyg_Thread *thread = dbg_get_thread(osthreadid);
439
 
440
    if( thread == 0 ) return 0;         // fail
441
 
442
    if( thread == Cyg_Scheduler::get_current_thread() )
443
    {
444
        // OK to proceed
445
 
446
        if (lock)
447
        {
448
            Cyg_Scheduler::lock();
449
        }
450
        else
451
        {
452
            if (Cyg_Scheduler::get_sched_lock() >= 1)
453
                Cyg_Scheduler::unlock_simple();
454
        }
455
        return 1;                       // success
456
    }
457
    else
458
    {
459
        // Cannot accept any thread other than current one
460
        return 0;                       // fail
461
    }
462
#endif
463
}
464
 
465
 
466
#endif // CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT
467
 
468
//--------------------------------------------------------------------------
469
// End of dbg_gdb.cxx

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.