• 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 
97 class KDebugEntry;
98 
99 class KDebugEntry
100 {
101 public:
102  KDebugEntry (int n, const TQCString& d) {number=n; descr=d;}
103  unsigned int number;
104  TQCString descr;
105 };
106 
107 static TQIntDict<KDebugEntry> *KDebugCache;
108 
109 static KStaticDeleter< TQIntDict<KDebugEntry> > kdd;
110 
111 static 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 
180 enum DebugLevels {
181  KDEBUG_INFO= 0,
182  KDEBUG_WARN= 1,
183  KDEBUG_ERROR= 2,
184  KDEBUG_FATAL= 3
185 };
186 
187 
188 struct 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 
199 static kDebugPrivate *kDebug_data = 0;
200 static KStaticDeleter<kDebugPrivate> pcd;
201 static KStaticDeleter<KDebugDCOPIface> dcopsd;
202 static KDebugDCOPIface* kDebugDCOPIface = 0;
203 
204 static 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 
371 kdbgstream& perror( kdbgstream &s) { return s << TQString(TQString::fromLocal8Bit(strerror(errno))); }
372 kdbgstream kdDebug(int area) { return kdbgstream(area, KDEBUG_INFO); }
373 kdbgstream kdDebug(bool cond, int area) { if (cond) return kdbgstream(area, KDEBUG_INFO); else return kdbgstream(0, 0, false); }
374 
375 kdbgstream kdError(int area) { return kdbgstream("ERROR: ", area, KDEBUG_ERROR); }
376 kdbgstream kdError(bool cond, int area) { if (cond) return kdbgstream("ERROR: ", area, KDEBUG_ERROR); else return kdbgstream(0,0,false); }
377 kdbgstream kdWarning(int area) { return kdbgstream("WARNING: ", area, KDEBUG_WARN); }
378 kdbgstream kdWarning(bool cond, int area) { if (cond) return kdbgstream("WARNING: ", area, KDEBUG_WARN); else return kdbgstream(0,0,false); }
379 kdbgstream kdFatal(int area) { return kdbgstream("FATAL: ", area, KDEBUG_FATAL); }
380 kdbgstream kdFatal(bool cond, int area) { if (cond) return kdbgstream("FATAL: ", area, KDEBUG_FATAL); else return kdbgstream(0,0,false); }
381 
382 kdbgstream::kdbgstream(kdbgstream &str)
383  : output(str.output), area(str.area), level(str.level), print(str.print)
384 {
385  str.output.truncate(0);
386 }
387 
388 void kdbgstream::flush() {
389  if (output.isEmpty() || !print)
390  return;
391  kDebugBackend( level, area, output.local8Bit().data() );
392  output = TQString::null;
393 }
394 
395 kdbgstream &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 
406 kdbgstream::~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 
417 kdbgstream& 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 
429 kdbgstream& 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 
441 kdbgstream& kdbgstream::operator<< (TQWidget* widget)
442 {
443  return *this << const_cast< const TQWidget* >( widget );
444 }
445 
446 kdbgstream& 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  */
486 kdbgstream& kdbgstream::operator<<( const TQDateTime& time) {
487  *this << time.toString();
488  return *this;
489 }
490 kdbgstream& kdbgstream::operator<<( const TQDate& date) {
491  *this << TQString(date.toString());
492 
493  return *this;
494 }
495 kdbgstream& kdbgstream::operator<<( const TQTime& time ) {
496  *this << TQString(time.toString());
497  return *this;
498 }
499 kdbgstream& kdbgstream::operator<<( const TQPoint& p ) {
500  *this << "(" << p.x() << ", " << p.y() << ")";
501  return *this;
502 }
503 kdbgstream& kdbgstream::operator<<( const TQSize& s ) {
504  *this << "[" << s.width() << "x" << s.height() << "]";
505  return *this;
506 }
507 kdbgstream& kdbgstream::operator<<( const TQRect& r ) {
508  *this << "[" << r.x() << "," << r.y() << " - " << r.width() << "x" << r.height() << "]";
509  return *this;
510 }
511 kdbgstream& 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 }
521 kdbgstream& kdbgstream::operator<<( const KURL& u ) {
522  *this << u.prettyURL();
523  return *this;
524 }
525 kdbgstream& kdbgstream::operator<<( const TQStringList& l ) {
526  *this << "(";
527  *this << l.join(",");
528  *this << ")";
529 
530  return *this;
531 }
532 kdbgstream& kdbgstream::operator<<( const TQColor& c ) {
533  if ( c.isValid() )
534  *this << TQString(c.name());
535  else
536  *this << "(invalid/default)";
537  return *this;
538 }
539 kdbgstream& 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 }
563 kdbgstream& 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 
584 kdbgstream& 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 
595 kdbgstream& 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
612 struct 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
626 asymbol** 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 
670 void 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 
742 void 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 
760 TQString 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 
811 TQString 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)
847 TQString kdBacktrace()
848 {
849  return kdBacktrace(-1 /*all*/);
850 }
851 
852 void 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 }
863 void 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.1
This website is maintained by Timothy Pearson.