• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdecore
 

tdecore

  • tdecore
kdebug.cpp
1/* This file is part of the KDE libraries
2 Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
3 2002 Holger Freyther (freyther@kde.org)
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21#include "kdebug.h"
22
23#ifdef NDEBUG
24#undef kdDebug
25#endif
26
27#include "kdebugdcopiface.h"
28
29#include "tdeapplication.h"
30#include "tdeglobal.h"
31#include "tdeinstance.h"
32#include "tdestandarddirs.h"
33
34#include <tqmessagebox.h>
35#include <tdelocale.h>
36#include <tqfile.h>
37#include <tqintdict.h>
38#include <tqstring.h>
39#include <tqdatetime.h>
40#include <tqpoint.h>
41#include <tqrect.h>
42#include <tqregion.h>
43#include <tqstringlist.h>
44#include <tqpen.h>
45#include <tqbrush.h>
46#include <tqsize.h>
47
48#include <kurl.h>
49
50#include <stdlib.h> // abort
51#include <unistd.h> // getpid
52#include <stdarg.h> // vararg stuff
53#include <ctype.h> // isprint
54#include <syslog.h>
55#include <errno.h>
56#include <cstdio>
57#include <cstring>
58#include <tdeconfig.h>
59#include "kstaticdeleter.h"
60#include <config.h>
61
62#ifdef HAVE_BACKTRACE
63#include BACKTRACE_H
64
65#ifdef HAVE_DLFCN_H
66#include <dlfcn.h>
67#endif
68
69#ifdef HAVE_ABI_CXA_DEMANGLE
70#include <cxxabi.h>
71#endif
72
73#include <link.h>
74#ifdef WITH_LIBBFD
75/* newer versions of libbfd require some autotools-specific macros to be defined */
76/* see binutils Bug 14243 and 14072 */
77#define PACKAGE tdelibs
78#define PACKAGE_VERSION TDE_VERSION
79
80#include <bfd.h>
81
82#ifdef HAVE_DEMANGLE_H
83#include <demangle.h>
84#endif // HAVE_DEMANGLE_H
85#endif // WITH_LIBBFD
86
87#endif // HAVE_BACKTRACE
88
89#ifdef HAVE_ALLOCA_H
90#include <alloca.h>
91#endif // HAVE_ALLOCA_H
92
93#ifdef HAVE_STDINT_H
94#include <stdint.h>
95#endif // HAVE_STDINT_H
96
97class KDebugEntry;
98
99class KDebugEntry
100{
101public:
102 KDebugEntry (int n, const TQCString& d) {number=n; descr=d;}
103 unsigned int number;
104 TQCString descr;
105};
106
107static TQIntDict<KDebugEntry> *KDebugCache;
108
109static KStaticDeleter< TQIntDict<KDebugEntry> > kdd;
110
111static TQCString getDescrFromNum(unsigned int _num)
112{
113 if (!KDebugCache) {
114 kdd.setObject(KDebugCache, new TQIntDict<KDebugEntry>( 601 ));
115 // Do not call this deleter from ~TDEApplication
116 TDEGlobal::unregisterStaticDeleter(&kdd);
117 KDebugCache->setAutoDelete(true);
118 }
119
120 KDebugEntry *ent = KDebugCache->find( _num );
121 if ( ent )
122 return ent->descr;
123
124 if ( !KDebugCache->isEmpty() ) // areas already loaded
125 return TQCString();
126
127 TQString filename(locate("config","kdebug.areas"));
128 if (filename.isEmpty())
129 return TQCString();
130
131 TQFile file(filename);
132 if (!file.open(IO_ReadOnly)) {
133 tqWarning("Couldn't open %s", filename.local8Bit().data());
134 file.close();
135 return TQCString();
136 }
137
138 uint lineNumber=0;
139 TQCString line(1024);
140 int len;
141
142 while (( len = file.readLine(line.data(),line.size()-1) ) > 0) {
143 int i=0;
144 ++lineNumber;
145
146 while (line[i] && line[i] <= ' ')
147 i++;
148
149 unsigned char ch=line[i];
150
151 if ( !ch || ch =='#' || ch =='\n')
152 continue; // We have an eof, a comment or an empty line
153
154 if (ch < '0' && ch > '9') {
155 tqWarning("Syntax error: no number (line %u)",lineNumber);
156 continue;
157 }
158
159 const int numStart=i;
160 do {
161 ch=line[++i];
162 } while ( ch >= '0' && ch <= '9');
163
164 const TQ_ULONG number =line.mid(numStart,i).toULong();
165
166 while (line[i] && line[i] <= ' ')
167 i++;
168
169 KDebugCache->insert(number, new KDebugEntry(number, line.mid(i, len-i-1)));
170 }
171 file.close();
172
173 ent = KDebugCache->find( _num );
174 if ( ent )
175 return ent->descr;
176
177 return TQCString();
178}
179
180enum DebugLevels {
181 KDEBUG_INFO= 0,
182 KDEBUG_WARN= 1,
183 KDEBUG_ERROR= 2,
184 KDEBUG_FATAL= 3
185};
186
187
188struct kDebugPrivate {
189 kDebugPrivate() :
190 oldarea(0), config(0) { }
191
192 ~kDebugPrivate() { delete config; }
193
194 TQCString aAreaName;
195 unsigned int oldarea;
196 TDEConfig *config;
197};
198
199static kDebugPrivate *kDebug_data = 0;
200static KStaticDeleter<kDebugPrivate> pcd;
201static KStaticDeleter<KDebugDCOPIface> dcopsd;
202static KDebugDCOPIface* kDebugDCOPIface = 0;
203
204static void kDebugBackend( unsigned short nLevel, unsigned int nArea, const char *data)
205{
206 if ( !kDebug_data )
207 {
208 pcd.setObject(kDebug_data, new kDebugPrivate());
209 // Do not call this deleter from ~TDEApplication
210 TDEGlobal::unregisterStaticDeleter(&pcd);
211
212 // create the dcop interface if it has not been created yet
213 if (!kDebugDCOPIface)
214 {
215 kDebugDCOPIface = dcopsd.setObject(kDebugDCOPIface, new KDebugDCOPIface);
216 }
217 }
218
219 if (!kDebug_data->config && TDEGlobal::_instance )
220 {
221 kDebug_data->config = new TDEConfig("kdebugrc", false, false);
222 kDebug_data->config->setGroup("0");
223
224 //AB: this is necessary here, otherwise all output with area 0 won't be
225 //prefixed with anything, unless something with area != 0 is called before
226 if ( TDEGlobal::_instance )
227 kDebug_data->aAreaName = TDEGlobal::instance()->instanceName();
228 }
229
230 if ( kDebug_data->oldarea != nArea ) {
231 kDebug_data->oldarea = nArea;
232 if( TDEGlobal::_instance ) {
233 if ( nArea > 0 ) {
234 kDebug_data->aAreaName = getDescrFromNum(nArea);
235 }
236 if ( nArea == 0 || kDebug_data->aAreaName.isEmpty() ) {
237 kDebug_data->aAreaName = TDEGlobal::instance()->instanceName();
238 }
239 }
240 }
241
242 int nPriority = 0;
243 TQString aCaption;
244
245 /* Determine output */
246
247 TQString key;
248 switch( nLevel )
249 {
250 case KDEBUG_INFO:
251 key = "InfoOutput";
252 aCaption = "Info";
253 nPriority = LOG_INFO;
254 break;
255 case KDEBUG_WARN:
256 key = "WarnOutput";
257 aCaption = "Warning";
258 nPriority = LOG_WARNING;
259 break;
260 case KDEBUG_FATAL:
261 key = "FatalOutput";
262 aCaption = "Fatal Error";
263 nPriority = LOG_CRIT;
264 break;
265 case KDEBUG_ERROR:
266 default:
267 /* Programmer error, use "Error" as default */
268 key = "ErrorOutput";
269 aCaption = "Error";
270 nPriority = LOG_ERR;
271 break;
272 }
273
274 short nOutput = -1;
275 if ( kDebug_data->config ) {
276 kDebug_data->config->setGroup( TQString::number(static_cast<int>(nArea)) );
277 nOutput = kDebug_data->config->readNumEntry(key, -1);
278 if( nOutput == -1 ) {
279 kDebug_data->config->setGroup( TQString::fromAscii("Default") );
280 nOutput = kDebug_data->config->readNumEntry(key, -1);
281 }
282 }
283 // if no output mode is specified default to no stderr output
284 // NOTE: don't set this to 4 (no output) because in that case you won't be
285 // able to get any output from applications which don't create
286 // TDEApplication objects.
287 if ( nOutput == -1 ) {
288 nOutput = 2;
289 }
290
291 // If the application doesn't have a TQApplication object it can't use
292 // a messagebox, as well as in case of GUI is disabled.
293 if ( nOutput == 1 && ( !tdeApp || !tdeApp->guiEnabled()) ) {
294 nOutput = 2;
295 } else if ( nOutput == 4 && nLevel != KDEBUG_FATAL ) {
296 return;
297 }
298
299 const int BUF_SIZE = 4096;
300 const int BUF_PID_SIZE = 20;
301 char buf[BUF_SIZE];
302 char buf_pid[BUF_PID_SIZE];
303 strlcpy(buf, TQDateTime::currentDateTime().toString("[yyyy/MM/dd hh:mm:ss.zzz] ").ascii(), BUF_SIZE);
304 if (!kDebug_data->aAreaName.isEmpty())
305 {
306 strlcat( buf, "[", BUF_SIZE );
307 strlcat( buf, kDebug_data->aAreaName.data(), BUF_SIZE );
308 strlcat( buf, "] ", BUF_SIZE );
309 }
310 snprintf(buf_pid, BUF_PID_SIZE, "[%d] ", getpid());
311 strlcat(buf, buf_pid, BUF_SIZE);
312 strlcat(buf, data, BUF_SIZE);
313
314 // Output
315 switch( nOutput )
316 {
317 case 0: // File
318 {
319 const char* aKey;
320 switch( nLevel )
321 {
322 case KDEBUG_INFO:
323 aKey = "InfoFilename";
324 break;
325 case KDEBUG_WARN:
326 aKey = "WarnFilename";
327 break;
328 case KDEBUG_FATAL:
329 aKey = "FatalFilename";
330 break;
331 case KDEBUG_ERROR:
332 default:
333 aKey = "ErrorFilename";
334 break;
335 }
336 TQFile aOutputFile( kDebug_data->config->readPathEntry(aKey, "kdebug.dbg") );
337 aOutputFile.open( IO_WriteOnly | IO_Append | IO_Raw );
338 aOutputFile.writeBlock( buf, strlen( buf ) );
339 aOutputFile.close();
340 break;
341 }
342 case 1: // Message Box
343 {
344 // Since we are in tdecore here, we cannot use KMsgBox and use
345 // TQMessageBox instead
346 if ( !kDebug_data->aAreaName.isEmpty() )
347 aCaption += TQString("(%1)").arg( TQString(kDebug_data->aAreaName) );
348 TQMessageBox::warning( 0L, aCaption, data, i18n("&OK") );
349 break;
350 }
351 case 2: // Shell
352 {
353 if (write( 2, buf, strlen( buf ) ) < 0) { //fputs( buf, stderr );
354 // ERROR
355 }
356 break;
357 }
358 case 3: // syslog
359 {
360 syslog( nPriority, "%s", buf);
361 break;
362 }
363 }
364
365 // check if we should abort
366 if( ( nLevel == KDEBUG_FATAL )
367 && ( !kDebug_data->config || kDebug_data->config->readNumEntry( "AbortFatal", 1 ) ) )
368 abort();
369}
370
371kdbgstream& perror( kdbgstream &s) { return s << TQString(TQString::fromLocal8Bit(strerror(errno))); }
372kdbgstream kdDebug(int area) { return kdbgstream(area, KDEBUG_INFO); }
373kdbgstream kdDebug(bool cond, int area) { if (cond) return kdbgstream(area, KDEBUG_INFO); else return kdbgstream(0, 0, false); }
374
375kdbgstream kdError(int area) { return kdbgstream("ERROR: ", area, KDEBUG_ERROR); }
376kdbgstream kdError(bool cond, int area) { if (cond) return kdbgstream("ERROR: ", area, KDEBUG_ERROR); else return kdbgstream(0,0,false); }
377kdbgstream kdWarning(int area) { return kdbgstream("WARNING: ", area, KDEBUG_WARN); }
378kdbgstream kdWarning(bool cond, int area) { if (cond) return kdbgstream("WARNING: ", area, KDEBUG_WARN); else return kdbgstream(0,0,false); }
379kdbgstream kdFatal(int area) { return kdbgstream("FATAL: ", area, KDEBUG_FATAL); }
380kdbgstream kdFatal(bool cond, int area) { if (cond) return kdbgstream("FATAL: ", area, KDEBUG_FATAL); else return kdbgstream(0,0,false); }
381
382kdbgstream::kdbgstream(kdbgstream &str)
383 : output(str.output), area(str.area), level(str.level), print(str.print)
384{
385 str.output.truncate(0);
386}
387
388void kdbgstream::flush() {
389 if (output.isEmpty() || !print)
390 return;
391 kDebugBackend( level, area, output.local8Bit().data() );
392 output = TQString::null;
393}
394
395kdbgstream &kdbgstream::form(const char *format, ...)
396{
397 char buf[4096];
398 va_list arguments;
399 va_start( arguments, format );
400 vsnprintf( buf, sizeof(buf), format, arguments );
401 va_end(arguments);
402 *this << buf;
403 return *this;
404}
405
406kdbgstream::~kdbgstream() {
407 if (!output.isEmpty()) {
408 fprintf(stderr, "ASSERT: debug output not ended with \\n\n");
409 TQString backtrace = kdBacktrace();
410 if (backtrace.ascii() != NULL) {
411 fprintf(stderr, "%s", backtrace.latin1());
412 }
413 *this << '\n';
414 }
415}
416
417kdbgstream& kdbgstream::operator<< (char ch)
418{
419 if (!print) return *this;
420 if (!isprint(ch))
421 output += "\\x" + TQString::number( static_cast<uint>( ch ), 16 ).rightJustify(2, '0');
422 else {
423 output += ch;
424 if (ch == '\n') flush();
425 }
426 return *this;
427}
428
429kdbgstream& kdbgstream::operator<< (TQChar ch)
430{
431 if (!print) return *this;
432 if (!ch.isPrint())
433 output += "\\x" + TQString::number( ch.unicode(), 16 ).rightJustify(2, '0');
434 else {
435 output += ch;
436 if (ch == TQChar('\n')) flush();
437 }
438 return *this;
439}
440
441kdbgstream& kdbgstream::operator<< (TQWidget* widget)
442{
443 return *this << const_cast< const TQWidget* >( widget );
444}
445
446kdbgstream& kdbgstream::operator<< (const TQWidget* widget)
447{
448 TQString string, temp;
449 // -----
450 if(widget==0)
451 {
452 string=(TQString)"[Null pointer]";
453 } else {
454 temp.setNum((ulong)widget, 16);
455 string=(TQString)"["+widget->className()+" pointer "
456 + "(0x" + temp + ")";
457 if(widget->name(0)==0)
458 {
459 string += " to unnamed widget, ";
460 } else {
461 string += (TQString)" to widget " + widget->name() + ", ";
462 }
463 string += "geometry="
464 + TQString().setNum(widget->width())
465 + "x"+TQString().setNum(widget->height())
466 + "+"+TQString().setNum(widget->x())
467 + "+"+TQString().setNum(widget->y())
468 + "]";
469 }
470 if (!print)
471 {
472 return *this;
473 }
474 output += string;
475 if (output.at(output.length() -1 ) == TQChar('\n'))
476 {
477 flush();
478 }
479 return *this;
480}
481/*
482 * either use 'output' directly and do the flush if needed
483 * or use the TQString operator which calls the char* operator
484 *
485 */
486kdbgstream& kdbgstream::operator<<( const TQDateTime& time) {
487 *this << time.toString();
488 return *this;
489}
490kdbgstream& kdbgstream::operator<<( const TQDate& date) {
491 *this << TQString(date.toString());
492
493 return *this;
494}
495kdbgstream& kdbgstream::operator<<( const TQTime& time ) {
496 *this << TQString(time.toString());
497 return *this;
498}
499kdbgstream& kdbgstream::operator<<( const TQPoint& p ) {
500 *this << "(" << p.x() << ", " << p.y() << ")";
501 return *this;
502}
503kdbgstream& kdbgstream::operator<<( const TQSize& s ) {
504 *this << "[" << s.width() << "x" << s.height() << "]";
505 return *this;
506}
507kdbgstream& kdbgstream::operator<<( const TQRect& r ) {
508 *this << "[" << r.x() << "," << r.y() << " - " << r.width() << "x" << r.height() << "]";
509 return *this;
510}
511kdbgstream& kdbgstream::operator<<( const TQRegion& reg ) {
512 *this<< "[ ";
513
514 TQMemArray<TQRect>rs=reg.rects();
515 for (uint i=0;i<rs.size();++i)
516 *this << TQString(TQString("[%1,%2 - %3x%4] ").arg(rs[i].x()).arg(rs[i].y()).arg(rs[i].width()).arg(rs[i].height() )) ;
517
518 *this <<"]";
519 return *this;
520}
521kdbgstream& kdbgstream::operator<<( const KURL& u ) {
522 *this << u.prettyURL();
523 return *this;
524}
525kdbgstream& kdbgstream::operator<<( const TQStringList& l ) {
526 *this << "(";
527 *this << l.join(",");
528 *this << ")";
529
530 return *this;
531}
532kdbgstream& kdbgstream::operator<<( const TQColor& c ) {
533 if ( c.isValid() )
534 *this << TQString(c.name());
535 else
536 *this << "(invalid/default)";
537 return *this;
538}
539kdbgstream& kdbgstream::operator<<( const TQPen& p ) {
540 static const char* const s_penStyles[] = {
541 "NoPen", "SolidLine", "DashLine", "DotLine", "DashDotLine",
542 "DashDotDotLine" };
543 static const char* const s_capStyles[] = {
544 "FlatCap", "SquareCap", "RoundCap" };
545 *this << "[ style:";
546 *this << s_penStyles[ p.style() ];
547 *this << " width:";
548 *this << p.width();
549 *this << " color:";
550 if ( p.color().isValid() )
551 *this << TQString(p.color().name());
552 else
553 *this <<"(invalid/default)";
554 if ( p.width() > 0 ) // cap style doesn't matter, otherwise
555 {
556 *this << " capstyle:";
557 *this << s_capStyles[ p.capStyle() >> 4 ];
558 // join style omitted
559 }
560 *this <<" ]";
561 return *this;
562}
563kdbgstream& kdbgstream::operator<<( const TQBrush& b) {
564 static const char* const s_brushStyles[] = {
565 "NoBrush", "SolidPattern", "Dense1Pattern", "Dense2Pattern", "Dense3Pattern",
566 "Dense4Pattern", "Dense5Pattern", "Dense6Pattern", "Dense7Pattern",
567 "HorPattern", "VerPattern", "CrossPattern", "BDiagPattern", "FDiagPattern",
568 "DiagCrossPattern" };
569
570 *this <<"[ style: ";
571 *this <<s_brushStyles[ b.style() ];
572 *this <<" color: ";
573 // can't use operator<<(str, b.color()) because that terminates a kdbgstream (flushes)
574 if ( b.color().isValid() )
575 *this << TQString(b.color().name()) ;
576 else
577 *this <<"(invalid/default)";
578 if ( b.pixmap() )
579 *this <<" has a pixmap";
580 *this <<" ]";
581 return *this;
582}
583
584kdbgstream& kdbgstream::operator<<( const TQVariant& v) {
585 *this << "[variant: ";
586 *this << v.typeName();
587 // For now we just attempt a conversion to string.
588 // Feel free to switch(v.type()) and improve the output.
589 *this << " toString=";
590 *this << v.toString();
591 *this << "]";
592 return *this;
593}
594
595kdbgstream& kdbgstream::operator<<( const TQByteArray& data) {
596 if (!print) return *this;
597 output += '[';
598 unsigned int i = 0;
599 unsigned int sz = TQMIN( data.size(), 64 );
600 for ( ; i < sz ; ++i ) {
601 output += TQString::number( (unsigned char) data[i], 16 ).rightJustify(2, '0');
602 if ( i < sz )
603 output += ' ';
604 }
605 if ( sz < data.size() )
606 output += "...";
607 output += ']';
608 return *this;
609}
610
611#ifdef HAVE_BACKTRACE
612struct BacktraceFunctionInfo {
613 const void *addr; //< the address of function returned by backtrace()
614 const char* fileName; //< the file of binary owning the function (e.g. shared library or current header)
615 const void *base; //< the base address there the binary is loaded to
616 uintptr_t offset; //< offset of the function in binary (base - address)
617 TQString functionName; //< mangled name of function
618 TQString prettyName; //< demangled name of function
619 TQString sourceName; //< name of source file function declared in
620 unsigned sourceLine; //< line where function defined
621};
622
623#ifdef WITH_LIBBFD
624
625// load symbol table from file
626asymbol** bfdLoadSymtab (bfd *abfd) {
627 long symCount; // count of entries in symbol table
628 long symtab_sz; // size of the table
629 asymbol** rv;
630 bool dynamic = false;
631
632 // make shure the file has symbol table
633 if ((bfd_get_file_flags (abfd) & HAS_SYMS) == 0){
634 return 0;
635 }
636
637 // determin the amount of space we'll need to store the table
638 symtab_sz = bfd_get_symtab_upper_bound (abfd);
639 if (symtab_sz == 0) {
640 symtab_sz = bfd_get_dynamic_symtab_upper_bound (abfd);
641 dynamic = true;
642 }
643 if (symtab_sz < 0) {
644 return 0;
645 }
646
647 // allocate memory
648 rv = (asymbol **) malloc(symtab_sz); // dunno, why not malloc
649 if ( !rv ) {
650 return 0;
651 }
652
653 // actually load the table
654 if (dynamic) {
655 symCount = bfd_canonicalize_dynamic_symtab (abfd, rv);
656 } else {
657 symCount = bfd_canonicalize_symtab (abfd, rv);
658 }
659
660 if (symCount < 0) {
661 if (rv) {
662 free(rv);
663 }
664 return 0;
665 }
666
667 return rv;
668}
669
670void bfdFillAdditionalFunctionsInfo(BacktraceFunctionInfo &func) {
671 static bool inited=0;
672 if (!inited) {
673 bfd_init();
674 inited=1;
675 }
676
677 bfd *abfd = bfd_openr(func.fileName, 0); // a bfd object
678 if( !abfd ) {
679 return;
680 }
681
682 // check format of the object
683 if( !bfd_check_format(abfd, bfd_object) ) {
684 bfd_close(abfd);
685 return;
686 }
687
688 // load symbol table
689 asymbol **syms= bfdLoadSymtab(abfd);
690 if(!syms) {
691 bfd_close(abfd);
692 return;
693 }
694
695 // found source file and line for given address
696 for (asection *sect = abfd->sections; sect != NULL; sect = sect->next) {
697#ifdef HAVE_LIBBFD_2_34_API
698 if (bfd_section_flags(sect) & SEC_ALLOC) {
699 bfd_vma sectStart = bfd_section_vma(sect);
700 bfd_vma sectEnd = sectStart + bfd_section_size(sect);
701#else // HAVE_LIBBFD_2_34_API
702 if (bfd_get_section_flags(abfd, sect) & SEC_ALLOC) {
703 bfd_vma sectStart = bfd_get_section_vma(abfd, sect);
704 bfd_vma sectEnd = sectStart + bfd_section_size(abfd, sect);
705#endif // HAVE_LIBBFD_2_34_API
706 if (sectStart <= func.offset && func.offset < sectEnd) {
707 bfd_vma sectOffset = func.offset - sectStart;
708 const char* functionName;
709 const char* sourceName;
710 unsigned sourceLine;
711 if (bfd_find_nearest_line(abfd, sect, syms, sectOffset,
712 &sourceName, &functionName, &sourceLine))
713 {
714 func.sourceName = sourceName;
715 func.sourceLine = sourceLine;
716 if(func.functionName.isEmpty()) {
717 func.functionName = TQString::fromAscii(functionName);
718 }
719 break;
720 }
721 }
722 }
723 }
724#ifdef HAVE_DEMANGLE_H
725 if(func.prettyName.isEmpty() && !func.functionName.isEmpty()) {
726 char *demangled = bfd_demangle(abfd, func.functionName.ascii(), DMGL_AUTO | DMGL_PARAMS);
727 if (demangled) {
728 func.prettyName = demangled;
729 free(demangled);
730 }
731 }
732#endif // HAVE_DEMANGLE_H
733
734 if( syms ) {
735 free(syms);
736 }
737 bfd_close(abfd);
738}
739
740#endif // WITH_LIBBFD
741
742void fillAdditionalFunctionsInfo(BacktraceFunctionInfo &func) {
743#ifdef WITH_LIBBFD
744 bfdFillAdditionalFunctionsInfo(func);
745#endif // WITH_LIBBFD
746
747#ifdef HAVE_ABI_CXA_DEMANGLE
748 if(func.prettyName.isEmpty() && !func.functionName.isEmpty()) {
749 int status=0;
750 char *demangled = abi::__cxa_demangle(func.functionName.ascii(), 0, 0, &status);
751 if (demangled) {
752 func.prettyName = demangled;
753 free(demangled);
754 }
755 }
756#endif // HAVE_ABI_CXA_DEMANGLE
757
758}
759
760TQString formatBacktrace(void *addr) {
761 TQString rv;
762 BacktraceFunctionInfo func;
763 func.addr = addr;
764
765 // NOTE: if somebody would compile for some non-linux-glibc platform
766 // check if dladdr function is avalible there
767 Dl_info info;
768
769 // obtain information about the function.
770#ifdef Q_OS_SOLARIS
771 dladdr((void *)func.addr, &info);
772#else
773 dladdr(func.addr, &info);
774#endif /* Solaris */
775
776 func.fileName = info.dli_fname;
777 func.base = info.dli_fbase;
778 func.offset = (uintptr_t)func.addr - (uintptr_t)func.base;
779 func.functionName = TQString::fromAscii(info.dli_sname);
780 func.sourceLine = 0;
781
782 fillAdditionalFunctionsInfo(func);
783
784 rv.sprintf("0x%0*lx", (int) sizeof(void*)*2, (uintptr_t) func.addr);
785
786 rv += " in ";
787 if (!func.prettyName.isEmpty()) {
788 rv += func.prettyName;
789 } else if (!func.functionName.isEmpty()) {
790 rv += func.functionName;
791 } else {
792 rv += "??";
793 }
794
795 if (!func.sourceName.isEmpty()) {
796 rv += " in ";
797 rv += func.sourceName;
798 rv += ":";
799 rv += func.sourceLine ? TQString::number(func.sourceLine) : "??";
800 } else if (func.fileName && func.fileName[0]) {
801 rv += TQString().sprintf(" from %s:0x%08lx",func.fileName, func.offset);
802 } else {
803 rv += " from ??";
804 }
805
806 return rv;
807}
808#endif // HAVE_BACKTRACE
809
810
811TQString kdBacktrace(int levels)
812{
813 TQString rv;
814#ifdef HAVE_BACKTRACE
815 if (levels < 0 || levels > 256 ) {
816 levels = 256;
817 }
818
819 rv = "[\n";
820
821 if (levels) {
822#ifdef HAVE_ALLOCA
823 void** trace = (void**)alloca(levels * sizeof(void*));
824#else // HAVE_ALLOCA
825 void* trace[256];
826#endif // HAVE_ALLOCA
827 levels = backtrace(trace, levels);
828
829 if (levels) {
830 for (int i = 0; i < levels; ++i) {
831 rv += TQString().sprintf("#%-2d ", i);
832 rv += formatBacktrace(trace[i]);
833 rv += '\n';
834 }
835 } else {
836 rv += "backtrace() failed\n";
837 }
838 }
839
840 rv += "]\n";
841#endif // HAVE_BACKTRACE
842 return rv;
843}
844
845// Keep for ABI compatability for some time
846// FIXME remove this (2013-08-18, 18:09, Fat-Zer)
847TQString kdBacktrace()
848{
849 return kdBacktrace(-1 /*all*/);
850}
851
852void kdBacktraceFD(int fd) {
853#ifdef HAVE_BACKTRACE
854 void *trace[256];
855 int levels;
856
857 levels = backtrace(trace, 256);
858 if (levels) {
859 backtrace_symbols_fd(trace, levels, fd);
860 }
861#endif // HAVE_BACKTRACE
862}
863void kdClearDebugConfig()
864{
865 if (kDebug_data) {
866 delete kDebug_data->config;
867 kDebug_data->config = 0;
868 }
869}
870
871
872// Needed for --enable-final
873#ifdef NDEBUG
874#define kdDebug kndDebug
875#endif
KDebugDCOPIface
DCOP interface to KDebug.
Definition: kdebugdcopiface.h:31
KStaticDeleter
Little helper class to clean up static objects that are held as pointer.
Definition: kstaticdeleter.h:74
KURL
Represents and parses a URL.
Definition: kurl.h:128
KURL::prettyURL
TQString prettyURL(int _trailing=0) const
Returns the URL as string in human-friendly format.
Definition: kurl.cpp:1559
TDEConfig
Access KDE Configuration entries.
Definition: tdeconfig.h:44
TDEGlobal::unregisterStaticDeleter
static void unregisterStaticDeleter(KStaticDeleterBase *d)
Unregisters a static deleter.
Definition: tdeglobal.cpp:198
TDEGlobal::instance
static TDEInstance * instance()
Returns the global instance.
Definition: tdeglobal.cpp:102
TDEInstance::instanceName
TQCString instanceName() const
Returns the name of the instance.
Definition: tdeinstance.cpp:342
TDELocale::i18n
TQString i18n(const char *text)
i18n is the function that does everything you need to translate a string.
Definition: tdelocale.cpp:1976
kdbgstream
kdbgstream is a text stream that allows you to print debug messages.
Definition: kdebug.h:80
kdbgstream::flush
void flush()
Flushes the output.
Definition: kdebug.cpp:388
kdbgstream::operator<<
kdbgstream & operator<<(bool i)
Prints the given value.
Definition: kdebug.h:99
kdbgstream::form
kdbgstream & form(const char *format,...)
Prints the string format which can contain printf-style formatted values.
Definition: kdebug.cpp:395
TDEGlobal::kdFatal
kdbgstream kdFatal(int area=0)
Returns a fatal error stream.
Definition: kdebug.cpp:379
TDEGlobal::kdBacktraceFD
void kdBacktraceFD(int fd=2)
Writes a backtrace to the given file descriptor.
Definition: kdebug.cpp:852
TDEGlobal::kdBacktrace
TQString kdBacktrace(int levels=-1)
Returns a backtrace.
Definition: kdebug.cpp:811
TDEGlobal::kdWarning
kdbgstream kdWarning(int area=0)
Returns a warning stream.
Definition: kdebug.cpp:377
TDEGlobal::kdClearDebugConfig
void kdClearDebugConfig()
Deletes the kdebugrc cache and therefore forces KDebug to reread the config file.
Definition: kdebug.cpp:863
TDEGlobal::kdError
kdbgstream kdError(int area=0)
Returns an error stream.
Definition: kdebug.cpp:375
TDEGlobal::kdDebug
kdbgstream kdDebug(int area=0)
Returns a debug stream.
Definition: kdebug.cpp:372
TDEStandardDirs::locate
TQString locate(const char *type, const TQString &filename, const TDEInstance *instance=TDEGlobal::instance())
Definition: tdestandarddirs.cpp:1689
TDEStdAccel::key
int key(StdAccel id)
Definition: tdestdaccel.cpp:383
tdelocale.h

tdecore

Skip menu "tdecore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.9.4
This website is maintained by Timothy Pearson.