root/trunk/libffado/src/debugmodule/debugmodule.cpp

Revision 1713, 23.8 kB (checked in by arnonym, 14 years ago)

Print the hexdump of the quadlets to stderr.

Print the stuff from show() as normal messages, not as debug.
And print the first 512 bytes of the application space of the dice-chip. Trying to figure out which bits to set to control line/instrument and high/low switches.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * Copyright (C) 2005-2008 by Daniel Wagner
3  * Copyright (C) 2005-2008 by Pieter Palmers
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 2 of the License, or
13  * (at your option) version 3 of the License.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #include "debugmodule.h"
26
27 #include <stdarg.h>
28 #include "libutil/ByteSwap.h"
29
30 #include <iostream>
31
32 #include <time.h>
33 #include <string.h>
34
35 #if DEBUG_BACKTRACE_SUPPORT
36     #include <execinfo.h>
37     #include <cxxabi.h>
38     #define GNU_SOURCE
39     #include <dlfcn.h>
40 #endif
41
42 #if DEBUG_USE_MESSAGE_BUFFER
43 #else
44     #ifdef DEBUG
45         #warning Printing debug info without ringbuffer, not RT-safe!
46     #else
47         #error Printing debug info without ringbuffer, not RT-safe (not allowed for non-debug builds)!
48     #endif
49 #endif
50
51 using namespace std;
52
53 struct ColorEntry  {
54     const char* preSequence;
55     const char* postSequence;
56 };
57
58 ColorEntry colorTable[] = {
59     { "",           ""        },
60     { "\033[31mFatal",   "\033[0m" },
61     { "\033[31mError",   "\033[0m" },
62     { "\033[31mWarning", "\033[0m" },
63     { "Debug",           ""        },
64 };
65
66
67 DebugModule::DebugModule( std::string name,  debug_level_t level )
68     : m_name( name )
69     , m_level( level )
70 {
71     if ( !DebugModuleManager::instance()->registerModule( *this ) ) {
72         cerr << "Could not register DebugModule (" << name
73              << ") at DebugModuleManager"
74              << endl;
75     }
76 }
77
78 DebugModule::~DebugModule()
79 {
80 //     if ( m_level >= eDL_VeryVerbose ) {
81 //         cout << "Unregistering "
82 //              << this->getName()
83 //              << " at DebugModuleManager"
84 //              << endl;
85 //     }
86     if ( !DebugModuleManager::instance()->unregisterModule( *this ) ) {
87         cerr << "Could not unregister DebugModule at DebugModuleManager"
88              << endl;
89     }
90
91 }
92
93 void
94 DebugModule::printShort( debug_level_t level,
95                          const char* format,
96                          ... ) const
97 {
98
99     // bypass for performance
100 #if DEBUG_BACKLOG_SUPPORT
101     if (level > BACKLOG_MIN_LEVEL
102         && level > m_level) {
103         return;
104     }
105 #else
106     if ( level >m_level ) {
107         return;
108     }
109 #endif
110
111     const char *warning = "WARNING: message truncated!\n";
112     const int warning_size = 32;
113     va_list arg;
114     char msg[MB_BUFFERSIZE];
115
116     // format the message such that it remains together
117     int chars_written=0;
118     int retval=0;
119
120     va_start( arg, format );
121     retval = vsnprintf(msg+chars_written, MB_BUFFERSIZE, format, arg);
122     va_end( arg );
123     if (retval >= 0) {  // ignore errors
124         chars_written += retval;
125     }
126
127     // output a warning if the message was truncated
128     if (chars_written == MB_BUFFERSIZE) {
129         snprintf(msg+MB_BUFFERSIZE-warning_size, warning_size, "%s", warning);
130     }
131
132 #if DEBUG_BACKLOG_SUPPORT
133     // print to backlog if necessary
134     if (level <= BACKLOG_MIN_LEVEL) {
135         DebugModuleManager::instance()->backlog_print( msg );
136     }
137 #endif
138
139     // print to stderr if necessary
140     if ( level <= m_level ) {
141         DebugModuleManager::instance()->print( msg );
142     }
143 }
144
145 void
146 DebugModule::print( debug_level_t level,
147                     const char*   file,
148                     const char*   function,
149                     unsigned int  line,
150                     const char*   format,
151                     ... ) const
152 {
153     // bypass for performance
154 #if DEBUG_BACKLOG_SUPPORT
155     if (level > BACKLOG_MIN_LEVEL
156         && level > m_level) {
157         return;
158     }
159 #else
160     if ( level >m_level ) {
161         return;
162     }
163 #endif
164
165     const char *warning = "WARNING: message truncated!\n";
166     const int warning_size = 32;
167
168     va_list arg;
169     char msg[MB_BUFFERSIZE];
170
171     // remove the path info from the filename
172     const char *f = file;
173     const char *fname = file;
174     while((f=strstr(f, "/"))) {
175         f++; // move away from delimiter
176         fname=f;
177     }
178
179     // add a timing timestamp
180     struct timespec ts;
181     clock_gettime(CLOCK_MONOTONIC, &ts);
182     uint64_t ts_usec=(uint64_t)(ts.tv_sec * 1000000LL + ts.tv_nsec / 1000LL);
183
184     // format the message such that it remains together
185     int chars_written=0;
186     int retval=0;
187     retval = snprintf(msg, MB_BUFFERSIZE, "%011llu: %s (%s)[%4d] %s: ",
188                       ts_usec, getPreSequence( level ),
189                       fname,  line,  function );
190     if (retval >= 0) chars_written += retval; // ignore errors
191
192     va_start( arg, format );
193     retval = vsnprintf( msg + chars_written,
194                         MB_BUFFERSIZE - chars_written,
195                         format, arg);
196     va_end( arg );
197     if (retval >= 0) chars_written += retval; // ignore errors
198
199     retval = snprintf( msg + chars_written,
200                        MB_BUFFERSIZE - chars_written,
201                        "%s", getPostSequence( level ) );
202     if (retval >= 0) chars_written += retval; // ignore errors
203
204     // output a warning if the message was truncated
205     if (chars_written == MB_BUFFERSIZE) {
206         snprintf(msg + MB_BUFFERSIZE - warning_size,
207                  warning_size,
208                  "%s", warning);
209     }
210
211 #if DEBUG_BACKLOG_SUPPORT
212     // print to backlog if necessary
213     if (level <= BACKLOG_MIN_LEVEL) {
214         DebugModuleManager::instance()->backlog_print( msg );
215     }
216 #endif
217
218     // print to stderr if necessary
219     if ( level <= m_level ) {
220         DebugModuleManager::instance()->print( msg );
221     }
222 }
223
224 const char*
225 DebugModule::getPreSequence( debug_level_t level ) const
226 {
227     if ( ( level <= eDL_Normal ) && ( level >= eDL_Message ) ) {
228         return colorTable[level].preSequence;
229     }
230     return colorTable[eDL_Normal].preSequence;
231 }
232
233 const char*
234 DebugModule::getPostSequence( debug_level_t level ) const
235 {
236     if ( ( level <= eDL_Normal ) && ( level >= eDL_Message ) ) {
237         return colorTable[level].postSequence;
238     }
239     return colorTable[eDL_Normal].postSequence;
240 }
241
242 //--------------------------------------
243
244 DebugModuleManager* DebugModuleManager::m_instance = 0;
245
246 DebugModuleManager::DebugModuleManager()
247     : mb_initialized(0)
248 #if DEBUG_USE_MESSAGE_BUFFER
249     , mb_inbuffer(0)
250     , mb_outbuffer(0)
251     , mb_overruns(0)
252 #endif
253 #if DEBUG_BACKTRACE_SUPPORT
254     , m_backtrace_buffer_nb_seen(0)
255 #endif
256 #if DEBUG_BACKLOG_SUPPORT
257     , bl_mb_inbuffer(0)
258 #endif
259 {
260
261 }
262
263 DebugModuleManager::~DebugModuleManager()
264 {
265     // cleanin up leftover modules
266     for ( DebugModuleVectorIterator it = m_debugModules.begin();
267           it != m_debugModules.end();
268           ++it )
269     {
270         fprintf(stderr,"Cleaning up leftover debug module: %s\n",(*it)->getName().c_str());
271         m_debugModules.erase( it );
272         delete *it;
273     }
274
275     if (!mb_initialized)
276         return;
277
278 #if DEBUG_USE_MESSAGE_BUFFER
279     pthread_mutex_lock(&mb_write_lock);
280     mb_initialized = 0;
281     sem_post(&mb_writes);
282     pthread_mutex_unlock(&mb_write_lock);
283
284     pthread_join(mb_writer_thread, NULL);
285     mb_flush();
286 #endif
287
288 #if DEBUG_BACKTRACE_SUPPORT
289     pthread_mutex_lock(&m_backtrace_lock);
290     // print a list of the symbols seen in a backtrace
291     fprintf(stderr, "Backtrace saw %d symbols:\n", m_backtrace_buffer_nb_seen);
292     char **strings = backtrace_symbols(m_backtrace_buffer_seen, m_backtrace_buffer_nb_seen);
293     if (strings == NULL) {
294         perror("backtrace_symbols");
295     } else {
296         char* outbuf = NULL;
297         size_t length;
298         int status;
299         Dl_info info;
300         for (int j = 0; j < m_backtrace_buffer_nb_seen; j++) {
301             if (dladdr(m_backtrace_buffer_seen[j], &info) != 0) {
302                 outbuf = __cxxabiv1::__cxa_demangle(info.dli_sname, outbuf, &length, &status);
303                 if(outbuf && status == 0) {
304                     fprintf(stderr, " %p => %s\n",
305                             m_backtrace_buffer_seen[j], outbuf);
306                     free(outbuf);
307                     outbuf = NULL;
308                 } else {
309                     fprintf(stderr, " %p => %s (demangle status: %d)\n",
310                             m_backtrace_buffer_seen[j], strings[j], status);
311                 }
312             } else {
313                 fprintf(stderr, " %p => %s\n",
314                         m_backtrace_buffer_seen[j], strings[j]);
315             }
316         }
317         free(strings);
318     }
319     pthread_mutex_unlock(&m_backtrace_lock);
320 #endif
321
322 #if DEBUG_USE_MESSAGE_BUFFER
323     if (mb_overruns)
324         fprintf(stderr, "WARNING: %d message buffer overruns!\n",
325             mb_overruns);
326     else
327         fprintf(stderr, "no message buffer overruns\n");
328
329     pthread_mutex_destroy(&mb_write_lock);
330     sem_destroy(&mb_writes);
331 #endif
332
333 #if DEBUG_BACKTRACE_SUPPORT
334     pthread_mutex_destroy(&m_backtrace_lock);
335 #endif
336
337 #if DEBUG_BACKLOG_SUPPORT
338     pthread_mutex_destroy(&bl_mb_write_lock);
339 #endif
340
341 }
342
343 bool
344 DebugModuleManager::init()
345 {
346     if (mb_initialized)
347         return true;
348
349         // if ( m_level >= eDL_VeryVerbose )
350         //         cout << "DebugModuleManager init..." << endl;
351
352 #if DEBUG_BACKTRACE_SUPPORT
353     pthread_mutex_init(&m_backtrace_lock, NULL);
354 #endif
355
356 #if DEBUG_BACKLOG_SUPPORT
357     pthread_mutex_init(&bl_mb_write_lock, NULL);
358 #endif
359
360 #if DEBUG_USE_MESSAGE_BUFFER
361     pthread_mutex_init(&mb_flush_lock, NULL);
362     pthread_mutex_init(&mb_write_lock, NULL);
363     sem_init(&mb_writes, 0, 0);
364
365     mb_overruns = 0;
366
367     int res;
368     #if DEBUG_MESSAGE_BUFFER_REALTIME
369     /* Get the client thread to run as an RT-FIFO
370         scheduled thread of appropriate priority.
371     */
372     pthread_attr_t attributes;
373     struct sched_param rt_param;
374     pthread_attr_init(&attributes);
375     if ((res = pthread_attr_setinheritsched(&attributes, PTHREAD_EXPLICIT_SCHED))) {
376         fprintf(stderr, "Cannot request explicit scheduling for RT thread  %d %s\n", res, strerror(res));
377         return -1;
378     }
379     if ((res = pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_JOINABLE))) {
380         fprintf(stderr, "Cannot request joinable thread creation for RT thread  %d %s\n", res, strerror(res));
381         return -1;
382     }
383     if ((res = pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM))) {
384         fprintf(stderr, "Cannot set scheduling scope for RT thread %d %s\n", res, strerror(res));
385         return -1;
386     }
387
388     if ((res = pthread_attr_setschedpolicy(&attributes, SCHED_FIFO))) {
389
390     //if ((res = pthread_attr_setschedpolicy(&attributes, SCHED_RR))) {
391         fprintf(stderr, "Cannot set FIFO scheduling class for RT thread  %d %s\n", res, strerror(res));
392         return -1;
393     }
394
395     memset(&rt_param, 0, sizeof(rt_param));
396     rt_param.sched_priority = DEBUG_MESSAGE_BUFFER_REALTIME_PRIO;
397
398     if ((res = pthread_attr_setschedparam(&attributes, &rt_param))) {
399         fprintf(stderr, "Cannot set scheduling priority for RT thread %d %s\n", res, strerror(res));
400         return -1;
401     }
402
403     mb_initialized = 1; // set to 1 otherwise the thread might exit (race condition)
404     if ((res = pthread_create(&mb_writer_thread, &attributes, mb_thread_func, (void *)this))) {
405         fprintf(stderr, "Cannot create thread %d %s\n", res, strerror(res));
406         mb_initialized = 0;
407     }
408     #else
409     mb_initialized = 1; // set to 1 otherwise the thread might exit (race condition)
410     if ((res = pthread_create(&mb_writer_thread, NULL, &mb_thread_func, (void *)this))) {
411         fprintf(stderr, "Cannot create thread %d %s\n", res, strerror(res));
412         mb_initialized = 0;
413     }
414     #endif
415 #endif
416
417     return true;
418 }
419
420 DebugModuleManager*
421 DebugModuleManager::instance()
422 {
423     if ( !m_instance ) {
424         m_instance = new DebugModuleManager;
425         if ( !m_instance ) {
426             cerr << "DebugModuleManager::instance Failed to create "
427                  << "DebugModuleManager" << endl;
428         }
429         if ( !m_instance->init() ) {
430             cerr << "DebugModuleManager::instance Failed to init "
431                  << "DebugModuleManager" << endl;
432         }
433     }
434     return m_instance;
435 }
436
437 bool
438 DebugModuleManager::registerModule( DebugModule& debugModule )
439 {
440     bool already_present=false;
441
442     for ( DebugModuleVectorIterator it = m_debugModules.begin();
443           it != m_debugModules.end();
444           ++it )
445     {
446         if ( *it == &debugModule ) {
447             already_present=true;
448             return true;
449         }
450     }
451
452     if (already_present) {
453         cerr << "DebugModuleManager::registerModule: Module already registered: "
454             << "DebugModule (" << debugModule.getName() << ")" << endl;
455     } else {
456         m_debugModules.push_back( &debugModule );
457     }
458     return true;
459 }
460
461 bool
462 DebugModuleManager::unregisterModule( DebugModule& debugModule )
463 {
464
465     for ( DebugModuleVectorIterator it = m_debugModules.begin();
466           it != m_debugModules.end();
467           ++it )
468     {
469         if ( *it == &debugModule ) {
470             m_debugModules.erase( it );
471             return true;
472         }
473     }
474
475     cerr << "DebugModuleManager::unregisterModule: Could not unregister "
476          << "DebugModule (" << debugModule.getName() << ")" << endl;
477     return false;
478 }
479
480 bool
481 DebugModuleManager::setMgrDebugLevel( std::string name, debug_level_t level )
482 {
483     for ( DebugModuleVectorIterator it = m_debugModules.begin();
484           it != m_debugModules.end();
485           ++it )
486     {
487         if ( (*it)->getName() == name ) {
488             return (*it)->setLevel( level );
489         }
490     }
491
492     cerr << "setDebugLevel: Did not find DebugModule ("
493          << name << ")" << endl;
494     return false;
495 }
496
497 void
498 DebugModuleManager::flush()
499 {
500 #if DEBUG_USE_MESSAGE_BUFFER
501     mb_flush();
502 #else
503     fflush(stderr);
504 #endif
505 }
506
507 #if DEBUG_USE_MESSAGE_BUFFER
508 void
509 DebugModuleManager::mb_flush()
510 {
511     /* called WITHOUT the mb_write_lock */
512    
513     /* the flush lock is to allow a flush from multiple threads
514      * this allows a code section that outputs a lot of debug messages
515      * and that can be blocked to flush the buffer itself such that it
516      * does not overflow.
517      */
518     DebugModuleManager *m=DebugModuleManager::instance();
519     pthread_mutex_lock(&m->mb_flush_lock);
520     while (mb_outbuffer != mb_inbuffer) {
521         fputs(mb_buffers[mb_outbuffer], stderr);
522         mb_outbuffer = MB_NEXT(mb_outbuffer);
523     }
524     fflush(stderr);
525     pthread_mutex_unlock(&m->mb_flush_lock);
526 }
527
528 void *
529 DebugModuleManager::mb_thread_func(void *arg)
530 {
531
532     DebugModuleManager *m=static_cast<DebugModuleManager *>(arg);
533
534     while (m->mb_initialized) {
535         sem_wait(&m->mb_writes);
536         m->mb_flush();
537     }
538
539     return NULL;
540 }
541 #endif
542
543 #if DEBUG_BACKLOG_SUPPORT
544 void
545 DebugModuleManager::showBackLog()
546 {
547      DebugModuleManager *m=DebugModuleManager::instance();
548     // locking the flush lock ensures that the backlog is
549     // printed as one entity
550     pthread_mutex_lock(&m->mb_flush_lock);
551     fprintf(stderr, "=====================================================\n");
552     fprintf(stderr, "* BEGIN OF BACKLOG PRINT\n");
553     fprintf(stderr, "=====================================================\n");
554
555     for (unsigned int i=0; i<BACKLOG_MB_BUFFERS;i++) {
556         unsigned int idx=(i+bl_mb_inbuffer)%BACKLOG_MB_BUFFERS;
557         fputs("BL: ", stderr);
558         fputs(bl_mb_buffers[idx], stderr);
559     }
560     fprintf(stderr, "BL: \n");
561
562     fprintf(stderr, "=====================================================\n");
563     fprintf(stderr, "* END OF BACKLOG PRINT\n");
564     fprintf(stderr, "=====================================================\n");
565     pthread_mutex_unlock(&m->mb_flush_lock);
566 }
567
568 void
569 DebugModuleManager::showBackLog(int nblines)
570 {
571      DebugModuleManager *m=DebugModuleManager::instance();
572     // locking the flush lock ensures that the backlog is
573     // printed as one entity
574     pthread_mutex_lock(&m->mb_flush_lock);
575     fprintf(stderr, "=====================================================\n");
576     fprintf(stderr, "* BEGIN OF BACKLOG PRINT\n");
577     fprintf(stderr, "=====================================================\n");
578
579     int lines_to_skip = BACKLOG_MB_BUFFERS - nblines;
580     if (lines_to_skip < 0) lines_to_skip = 0;
581     for (unsigned int i=0; i<BACKLOG_MB_BUFFERS;i++) {
582         if (lines_to_skip-- < 0) {
583             unsigned int idx=(i+bl_mb_inbuffer)%BACKLOG_MB_BUFFERS;
584             fputs("BL: ", stderr);
585             fputs(bl_mb_buffers[idx], stderr);
586         }
587     }
588     fprintf(stderr, "BL: \n");
589
590     fprintf(stderr, "=====================================================\n");
591     fprintf(stderr, "* END OF BACKLOG PRINT\n");
592     fprintf(stderr, "=====================================================\n");
593     pthread_mutex_unlock(&m->mb_flush_lock);
594 }
595
596 void
597 DebugModuleManager::backlog_print(const char *msg)
598 {
599     unsigned int ntries;
600     struct timespec wait = {0, DEBUG_MESSAGE_BUFFER_COLLISION_WAIT_NSEC};
601     // the backlog
602     ntries=DEBUG_MESSAGE_BUFFER_COLLISION_WAIT_NTRIES;
603     while (ntries) { // try a few times
604         if (pthread_mutex_trylock(&bl_mb_write_lock) == 0) {
605             strncpy(bl_mb_buffers[bl_mb_inbuffer], msg, MB_BUFFERSIZE);
606             bl_mb_inbuffer = BACKLOG_MB_NEXT(bl_mb_inbuffer);
607             pthread_mutex_unlock(&bl_mb_write_lock);
608             break;
609         } else {
610             nanosleep(&wait, NULL);
611             ntries--;
612         }
613     }
614     // just bail out should it have failed
615 }
616 #endif
617
618 void
619 DebugModuleManager::print(const char *msg)
620 {
621 #if DEBUG_USE_MESSAGE_BUFFER
622     unsigned int ntries;
623     struct timespec wait = {0,50000};
624
625     if (!mb_initialized) {
626         /* Unable to print message with realtime safety.
627          * Complain and print it anyway. */
628         fprintf(stderr, "ERROR: messagebuffer not initialized: %s",
629             msg);
630         return;
631     }
632
633     ntries=6;
634     while (ntries) { // try a few times
635         if (pthread_mutex_trylock(&mb_write_lock) == 0) {
636             strncpy(mb_buffers[mb_inbuffer], msg, MB_BUFFERSIZE);
637             mb_inbuffer = MB_NEXT(mb_inbuffer);
638             sem_post(&mb_writes);
639             pthread_mutex_unlock(&mb_write_lock);
640             break;
641         } else {
642             nanosleep(&wait, NULL);
643             ntries--;
644         }
645     }
646     if (ntries==0) {  /* lock collision */
647         //         atomic_add(&mb_overruns, 1);
648         // FIXME: atomicity
649         mb_overruns++; // skip the atomicness for now
650     }
651 #else
652     fprintf(stderr,msg);
653 #endif
654 }
655
656 #if DEBUG_BACKTRACE_SUPPORT
657 void
658 DebugModuleManager::printBacktrace(int len)
659 {
660     int nptrs;
661     int chars_written=0;
662
663     if(len > DEBUG_MAX_BACKTRACE_LENGTH) {
664         len = DEBUG_MAX_BACKTRACE_LENGTH;
665     }
666
667     pthread_mutex_lock(&m_backtrace_lock);
668     nptrs = backtrace(m_backtrace_buffer, len);
669     chars_written += snprintf(m_backtrace_strbuffer, MB_BUFFERSIZE-chars_written, "BACKTRACE (%d/%d): ", nptrs, len);
670
671     for (int j = 0; j < nptrs; j++) {
672         char name[64];
673         name[0]=0;
674         getFunctionName(m_backtrace_buffer[j], name, 64);
675         chars_written += snprintf(m_backtrace_strbuffer + chars_written, MB_BUFFERSIZE-chars_written, "%s\n", name);
676     }
677     chars_written += snprintf(m_backtrace_strbuffer + chars_written, MB_BUFFERSIZE-chars_written, "\n");
678
679     // make sure the string is terminated properly
680     m_backtrace_strbuffer[MB_BUFFERSIZE-2] = '\n';
681     m_backtrace_strbuffer[MB_BUFFERSIZE-1] = 0;
682    
683     // save the pointers to the pointers-seen list such that we can
684     // dump their info later on
685     bool seen;
686     for (int i=0; i<nptrs; i++) {
687         seen = false;
688         int j;
689         for (j=0; j<m_backtrace_buffer_nb_seen && j < DEBUG_MAX_BACKTRACE_FUNCTIONS_SEEN; j++) {
690             if(m_backtrace_buffer_seen[j] == m_backtrace_buffer[i]) {
691                 seen = true;
692                 break;
693             }
694         }
695         if (!seen
696            && j < DEBUG_MAX_BACKTRACE_FUNCTIONS_SEEN) {
697             m_backtrace_buffer_seen[j] = m_backtrace_buffer[i];
698             m_backtrace_buffer_nb_seen++;
699         }
700     }
701
702     print(m_backtrace_strbuffer);
703
704     pthread_mutex_unlock(&m_backtrace_lock);
705 }
706
707 void *
708 DebugModuleManager::getBacktracePtr(int id)
709 {
710     int nptrs;
711     void *retval = NULL;
712
713     if(id >= DEBUG_MAX_BACKTRACE_LENGTH) {
714         return NULL;
715     }
716
717     pthread_mutex_lock(&m_backtrace_lock);
718     nptrs = backtrace(m_backtrace_buffer, id+1);
719     if(id >= nptrs) {
720         id = nptrs-1;
721     }
722     retval = m_backtrace_buffer[id];
723     // save the pointers to the pointers-seen list such that we can
724     // dump their info later on
725     bool seen = false;
726     int j;
727     for (j=0; j<m_backtrace_buffer_nb_seen && j < DEBUG_MAX_BACKTRACE_FUNCTIONS_SEEN; j++) {
728         if(m_backtrace_buffer_seen[j] == m_backtrace_buffer[id]) {
729             seen = true;
730             break;
731         }
732     }
733     if (!seen
734        && j < DEBUG_MAX_BACKTRACE_FUNCTIONS_SEEN) {
735         m_backtrace_buffer_seen[j] = m_backtrace_buffer[id];
736         m_backtrace_buffer_nb_seen++;
737     }
738     pthread_mutex_unlock(&m_backtrace_lock);
739
740     return retval;
741 }
742
743 void
744 DebugModuleManager::getFunctionName(void *ptr, char *buff, int len)
745 {
746     char* outbuf = NULL;
747     size_t length;
748     int status;
749     Dl_info info;
750     if (dladdr(ptr, &info) != 0) {
751         outbuf = abi::__cxa_demangle(info.dli_sname, outbuf, &length, &status);
752         if(outbuf && status == 0) {
753             if(len < (int)length) {
754                 strncpy(buff, outbuf, len);
755             } else {
756                 strncpy(buff, outbuf, length);
757             }
758         } else {
759             snprintf(buff, len, "%p (%s)", ptr, info.dli_sname);
760         }
761     } else {
762         snprintf(buff, len, "%p (I-ERR)", ptr);
763     }
764     if (outbuf) free(outbuf);
765 }
766
767 #endif
768
769 //----------------------------------------
770
771 unsigned char
772 toAscii( unsigned char c )
773 {
774     if ( ( c > 31 ) && ( c < 126) ) {
775         return c;
776     } else {
777         return '.';
778     }
779 }
780
781 /* converts a quadlet to a uchar * buffer
782  * not implemented optimally, but clear
783  */
784 void
785 quadlet2char( quadlet_t quadlet, unsigned char* buff )
786 {
787     *(buff)   = (quadlet>>24)&0xFF;
788     *(buff+1) = (quadlet>>16)&0xFF;
789     *(buff+2) = (quadlet>> 8)&0xFF;
790     *(buff+3) = (quadlet)    &0xFF;
791 }
792
793 void
794 hexDump( unsigned char *data_start, unsigned int length )
795 {
796     unsigned int i=0;
797     unsigned int byte_pos;
798     unsigned int bytes_left;
799
800     if ( length <= 0 ) {
801         return;
802     }
803     if ( length >= 7 ) {
804         for ( i = 0; i < (length-7); i += 8 ) {
805             printf( "%04X: %02X %02X %02X %02X %02X %02X %02X %02X "
806                     "- [%c%c%c%c%c%c%c%c]\n",
807
808                     i,
809
810                     *(data_start+i+0),
811                     *(data_start+i+1),
812                     *(data_start+i+2),
813                     *(data_start+i+3),
814                     *(data_start+i+4),
815                     *(data_start+i+5),
816                     *(data_start+i+6),
817                     *(data_start+i+7),
818
819                     toAscii( *(data_start+i+0) ),
820                     toAscii( *(data_start+i+1) ),
821                     toAscii( *(data_start+i+2) ),
822                     toAscii( *(data_start+i+3) ),
823                     toAscii( *(data_start+i+4) ),
824                     toAscii( *(data_start+i+5) ),
825                     toAscii( *(data_start+i+6) ),
826                     toAscii( *(data_start+i+7) )
827                 );
828         }
829     }
830     byte_pos = i;
831     bytes_left = length - byte_pos;
832
833     printf( "%04X:" ,i );
834     for ( i = byte_pos; i < length; i += 1 ) {
835         printf( " %02X", *(data_start+i) );
836     }
837     for ( i=0; i < 8-bytes_left; i+=1 ) {
838         printf( "   " );
839     }
840
841     printf( " - [" );
842     for ( i = byte_pos; i < length; i += 1) {
843         printf( "%c", toAscii(*(data_start+i)));
844     }
845     for ( i = 0; i < 8-bytes_left; i += 1) {
846         printf( " " );
847     }
848
849     printf( "]" );
850     printf( "\n" );
851 }
852
853 void
854 hexDumpQuadlets( quadlet_t *data, unsigned int length )
855 {
856     unsigned int i=0;
857
858     if ( length <= 0 ) {
859         return;
860     }
861     for (i = 0; i< length; i += 1) {
862         fprintf(stderr, "%02d %04X: %08X (%08X)"
863                 "\n", i, i*4, data[i],CondSwapFromBus32(data[i]));
864     }
865 }
866
867
Note: See TracBrowser for help on using the browser.