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