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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [kernel/] [current/] [src/] [debug/] [dbg_gdb.cxx] - Blame information for rev 851

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

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