27#include "kdebugdcopiface.h" 
   29#include "tdeapplication.h" 
   31#include "tdeinstance.h" 
   32#include "tdestandarddirs.h" 
   34#include <tqmessagebox.h> 
   39#include <tqdatetime.h> 
   43#include <tqstringlist.h> 
   58#include "kstaticdeleter.h" 
   68#ifdef HAVE_ABI_CXA_DEMANGLE 
   76#define PACKAGE tdelibs 
   77#define PACKAGE_VERSION TDE_VERSION 
  101    KDebugEntry (
int n, 
const TQCString& d) {number=n; descr=d;}
 
  106static TQIntDict<KDebugEntry> *KDebugCache;
 
  110static TQCString getDescrFromNum(
unsigned int _num)
 
  113    kdd.setObject(KDebugCache, 
new TQIntDict<KDebugEntry>( 601 ));
 
  116    KDebugCache->setAutoDelete(
true);
 
  119  KDebugEntry *ent = KDebugCache->find( _num );
 
  123  if ( !KDebugCache->isEmpty() ) 
 
  126  TQString filename(
locate(
"config",
"kdebug.areas"));
 
  127  if (filename.isEmpty())
 
  130  TQFile file(filename);
 
  131  if (!file.open(IO_ReadOnly)) {
 
  132    tqWarning(
"Couldn't open %s", filename.local8Bit().data());
 
  138  TQCString line(1024);
 
  141  while (( len = file.readLine(line.data(),line.size()-1) ) > 0) {
 
  145      while (line[i] && line[i] <= 
' ')
 
  148      unsigned char ch=line[i];
 
  150      if ( !ch || ch ==
'#' || ch ==
'\n')
 
  153      if (ch < '0' && ch > 
'9') {
 
  154          tqWarning(
"Syntax error: no number (line %u)",lineNumber);
 
  158      const int numStart=i;
 
  161      } 
while ( ch >= 
'0' && ch <= 
'9');
 
  163      const TQ_ULONG number =line.mid(numStart,i).toULong();
 
  165      while (line[i] && line[i] <= 
' ')
 
  168      KDebugCache->insert(number, 
new KDebugEntry(number, line.mid(i, len-i-1)));
 
  172  ent = KDebugCache->find( _num );
 
  187struct kDebugPrivate {
 
  189    oldarea(0), config(0) { }
 
  191  ~kDebugPrivate() { 
delete config; }
 
  194  unsigned int oldarea;
 
  198static kDebugPrivate *kDebug_data = 0;
 
  203static void kDebugBackend( 
unsigned short nLevel, 
unsigned int nArea, 
const char *data)
 
  207      pcd.setObject(kDebug_data, 
new kDebugPrivate());
 
  212      if (!kDebugDCOPIface)
 
  214          kDebugDCOPIface = dcopsd.setObject(kDebugDCOPIface, 
new KDebugDCOPIface);
 
  218  if (!kDebug_data->config && TDEGlobal::_instance )
 
  220      kDebug_data->config = 
new TDEConfig(
"kdebugrc", 
false, 
false);
 
  221      kDebug_data->config->setGroup(
"0");
 
  225      if ( TDEGlobal::_instance )
 
  229  if ( kDebug_data->oldarea != nArea ) {
 
  230    kDebug_data->oldarea = nArea;
 
  231    if( TDEGlobal::_instance ) {
 
  233        kDebug_data->aAreaName = getDescrFromNum(nArea);
 
  235      if ( nArea == 0 || kDebug_data->aAreaName.isEmpty() ) {
 
  252      nPriority = LOG_INFO;
 
  256      aCaption = 
"Warning";
 
  257      nPriority = LOG_WARNING;
 
  261      aCaption = 
"Fatal Error";
 
  262      nPriority = LOG_CRIT;
 
  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);
 
  286  if ( nOutput == -1 ) {
 
  292  if ( nOutput == 1 && ( !tdeApp || !tdeApp->guiEnabled()) ) {
 
  294  } 
else if ( nOutput == 4 && nLevel != KDEBUG_FATAL ) {
 
  298  const int BUF_SIZE = 4096;
 
  299  const int BUF_PID_SIZE = 20;
 
  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())
 
  305    strlcat( buf, 
"[", BUF_SIZE );
 
  306    strlcat( buf, kDebug_data->aAreaName.data(), BUF_SIZE );
 
  307    strlcat( buf, 
"] ", BUF_SIZE );
 
  309  snprintf(buf_pid, BUF_PID_SIZE, 
"[%d] ", getpid());
 
  310  strlcat(buf, buf_pid, BUF_SIZE);
 
  311  strlcat(buf, data, BUF_SIZE);
 
  322          aKey = 
"InfoFilename";
 
  325          aKey = 
"WarnFilename";
 
  328          aKey = 
"FatalFilename";
 
  332          aKey = 
"ErrorFilename";
 
  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 ) );
 
  345      if ( !kDebug_data->aAreaName.isEmpty() )
 
  346          aCaption += TQString(
"(%1)").arg( TQString(kDebug_data->aAreaName) );
 
  347      TQMessageBox::warning( 0L, aCaption, data, 
i18n(
"&OK") );
 
  352      if (write( 2, buf, strlen( buf ) ) < 0) {  
 
  359      syslog( nPriority, 
"%s", buf);
 
  365  if( ( nLevel == KDEBUG_FATAL )
 
  366      && ( !kDebug_data->config || kDebug_data->config->readNumEntry( 
"AbortFatal", 1 ) ) )
 
  370kdbgstream& perror( 
kdbgstream &s) { 
return s << TQString(TQString::fromLocal8Bit(strerror(errno))); }
 
  382 : output(str.output), area(str.area), level(str.level), print(str.print) 
 
  384    str.output.truncate(0); 
 
  388    if (output.isEmpty() || !print)
 
  390    kDebugBackend( level, area, output.local8Bit().data() );
 
  391    output = TQString::null;
 
  398    va_start( arguments, format );
 
  399    vsnprintf( buf, 
sizeof(buf), format, arguments );
 
  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());
 
  418  if (!print) 
return *
this;
 
  420    output += 
"\\x" + TQString::number( 
static_cast<uint
>( ch ), 16 ).rightJustify(2, 
'0');
 
  423    if (ch == 
'\n') 
flush();
 
  430  if (!print) 
return *
this;
 
  432    output += 
"\\x" + TQString::number( ch.unicode(), 16 ).rightJustify(2, 
'0');
 
  435    if (ch == TQChar(
'\n')) 
flush();
 
  442    return *this << const_cast< const TQWidget* >( widget );
 
  447  TQString string, temp;
 
  451      string=(TQString)
"[Null pointer]";
 
  453      temp.setNum((ulong)widget, 16);
 
  454      string=(TQString)
"["+widget->className()+
" pointer " 
  455    + 
"(0x" + temp + 
")";
 
  456      if(widget->name(0)==0)
 
  458      string += 
" to unnamed widget, ";
 
  460      string += (TQString)
" to widget " + widget->name() + 
", ";
 
  462      string += 
"geometry=" 
  463    + TQString().setNum(widget->width())
 
  464    + 
"x"+TQString().setNum(widget->height())
 
  465    + 
"+"+TQString().setNum(widget->x())
 
  466    + 
"+"+TQString().setNum(widget->y())
 
  474  if (output.at(output.length() -1 ) == TQChar(
'\n'))
 
  486    *
this << time.toString();
 
  490    *
this << TQString(date.toString());
 
  495    *
this << TQString(time.toString());
 
  499    *
this << 
"(" << p.x() << 
", " << p.y() << 
")";
 
  503    *
this << 
"[" << s.width() << 
"x" << s.height() << 
"]";
 
  507    *
this << 
"[" << r.x() << 
"," << r.y() << 
" - " << r.width() << 
"x" << r.height() << 
"]";
 
  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() )) ;
 
  526    *
this << l.join(
",");
 
  533        *
this << TQString(c.name());
 
  535        *
this << 
"(invalid/default)";
 
  539    static const char* 
const s_penStyles[] = {
 
  540        "NoPen", 
"SolidLine", 
"DashLine", 
"DotLine", 
"DashDotLine",
 
  542    static const char* 
const s_capStyles[] = {
 
  543        "FlatCap", 
"SquareCap", 
"RoundCap" };
 
  545    *
this << s_penStyles[ p.style() ];
 
  549    if ( p.color().isValid() )
 
  550        *
this << TQString(p.color().name());
 
  552        *
this <<
"(invalid/default)";
 
  555        *
this << 
" capstyle:";
 
  556        *
this << s_capStyles[ p.capStyle() >> 4 ];
 
  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" };
 
  570    *
this <<s_brushStyles[ b.style() ];
 
  573    if ( b.color().isValid() )
 
  574        *
this << TQString(b.color().name()) ;
 
  576        *
this <<
"(invalid/default)";
 
  578        *
this <<
" has a pixmap";
 
  584    *
this << 
"[variant: ";
 
  585    *
this << v.typeName();
 
  588    *
this << 
" toString=";
 
  589    *
this << v.toString();
 
  595    if (!print) 
return *
this;
 
  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');
 
  604    if ( sz < data.size() )
 
  611struct BacktraceFunctionInfo {
 
  613    const char* fileName;  
 
  616    TQString functionName; 
 
  625asymbol** bfdLoadSymtab (bfd *abfd) {
 
  629    bool dynamic = 
false;
 
  632    if ((bfd_get_file_flags (abfd) & HAS_SYMS) == 0){
 
  637    symtab_sz = bfd_get_symtab_upper_bound (abfd);
 
  638    if (symtab_sz == 0) {
 
  639        symtab_sz = bfd_get_dynamic_symtab_upper_bound (abfd);
 
  647    rv = (asymbol **) malloc(symtab_sz); 
 
  654        symCount = bfd_canonicalize_dynamic_symtab (abfd, rv);
 
  656        symCount = bfd_canonicalize_symtab (abfd, rv);
 
  669void bfdFillAdditionalFunctionsInfo(BacktraceFunctionInfo &func) {
 
  670    static bool inited=0;
 
  676    bfd *abfd = bfd_openr(func.fileName, 0); 
 
  682    if( !bfd_check_format(abfd, bfd_object) ) {
 
  688    asymbol **syms= bfdLoadSymtab(abfd);    
 
  695    for (asection *sect = abfd->sections; sect != NULL; sect = sect->next) {
 
  696#ifdef HAVE_LIBBFD_2_34_API 
  697        if (bfd_section_flags(sect) & SEC_ALLOC) {
 
  698            bfd_vma sectStart = bfd_section_vma(sect);
 
  699            bfd_vma sectEnd   = sectStart + bfd_section_size(sect);
 
  701        if (bfd_get_section_flags(abfd, sect) & SEC_ALLOC) {
 
  702            bfd_vma sectStart = bfd_get_section_vma(abfd, sect);
 
  703            bfd_vma sectEnd   = sectStart + bfd_section_size(abfd, sect);
 
  705            if (sectStart <= func.offset && func.offset < sectEnd) {
 
  706                bfd_vma sectOffset = func.offset - sectStart;
 
  707                const char* functionName;
 
  708                const char* sourceName;
 
  710                if (bfd_find_nearest_line(abfd, sect, syms, sectOffset, 
 
  711                            &sourceName, &functionName, &sourceLine))
 
  713                    func.sourceName   = sourceName;
 
  714                    func.sourceLine   = sourceLine;
 
  715                    if(func.functionName.isEmpty()) {
 
  716                        func.functionName = TQString::fromAscii(functionName);
 
  723#ifdef HAVE_DEMANGLE_H   
  724    if(func.prettyName.isEmpty() && !func.functionName.isEmpty()) {
 
  725        char *demangled = bfd_demangle(abfd, func.functionName.ascii(), DMGL_AUTO | DMGL_PARAMS);
 
  727            func.prettyName = demangled;
 
  741void fillAdditionalFunctionsInfo(BacktraceFunctionInfo &func) {
 
  743    bfdFillAdditionalFunctionsInfo(func);
 
  746#ifdef HAVE_ABI_CXA_DEMANGLE 
  747    if(func.prettyName.isEmpty() && !func.functionName.isEmpty()) {
 
  749        char *demangled = abi::__cxa_demangle(func.functionName.ascii(), 0, 0, &status);
 
  751            func.prettyName = demangled;
 
  759TQString formatBacktrace(
void *addr) {
 
  761    BacktraceFunctionInfo func;
 
  770    dladdr((
void *)func.addr, &info);
 
  772    dladdr(func.addr, &info);
 
  775    func.fileName = info.dli_fname;
 
  776    func.base = info.dli_fbase;
 
  777    func.offset = (uintptr_t)func.addr - (uintptr_t)func.base;
 
  778    func.functionName = TQString::fromAscii(info.dli_sname);
 
  781    fillAdditionalFunctionsInfo(func);
 
  783    rv.sprintf(
"0x%0*lx", (
int) 
sizeof(
void*)*2, (uintptr_t) func.addr);
 
  786    if (!func.prettyName.isEmpty()) {
 
  787        rv += func.prettyName;
 
  788    } 
else if (!func.functionName.isEmpty()) {
 
  789        rv += func.functionName;
 
  794    if (!func.sourceName.isEmpty()) {
 
  796        rv += func.sourceName;
 
  798        rv += func.sourceLine ? TQString::number(func.sourceLine) : 
"??";
 
  799    } 
else if (func.fileName && func.fileName[0]) {
 
  800        rv += TQString().sprintf(
" from %s:0x%08lx",func.fileName, func.offset);
 
  814    if (levels < 0 || levels > 256 ) {
 
  822        void** trace = (
void**)alloca(levels * 
sizeof(
void*));
 
  826        levels = backtrace(trace, levels);
 
  829            for (
int i = 0; i < levels; ++i) {
 
  830                rv += TQString().sprintf(
"#%-2d ", i);
 
  831                rv += formatBacktrace(trace[i]);
 
  835            rv += 
"backtrace() failed\n";
 
  856    levels = backtrace(trace, 256);
 
  858        backtrace_symbols_fd(trace, levels, fd);
 
  865        delete kDebug_data->config;
 
  866        kDebug_data->config = 0;
 
  873#define kdDebug kndDebug 
DCOP interface to KDebug.
 
Little helper class to clean up static objects that are held as pointer.
 
Represents and parses a URL.
 
TQString prettyURL(int _trailing=0) const
Returns the URL as string in human-friendly format.
 
Access KDE Configuration entries.
 
static void unregisterStaticDeleter(KStaticDeleterBase *d)
Unregisters a static deleter.
 
static TDEInstance * instance()
Returns the global instance.
 
TQCString instanceName() const
Returns the name of the instance.
 
TQString i18n(const char *text)
i18n is the function that does everything you need to translate a string.
 
kdbgstream is a text stream that allows you to print debug messages.
 
void flush()
Flushes the output.
 
kdbgstream & operator<<(bool i)
Prints the given value.
 
kdbgstream & form(const char *format,...)
Prints the string format which can contain printf-style formatted values.
 
kdbgstream kdFatal(int area=0)
Returns a fatal error stream.
 
void kdBacktraceFD(int fd=2)
Writes a backtrace to the given file descriptor.
 
TQString kdBacktrace(int levels=-1)
Returns a backtrace.
 
kdbgstream kdWarning(int area=0)
Returns a warning stream.
 
void kdClearDebugConfig()
Deletes the kdebugrc cache and therefore forces KDebug to reread the config file.
 
kdbgstream kdError(int area=0)
Returns an error stream.
 
kdbgstream kdDebug(int area=0)
Returns a debug stream.
 
TQString locate(const char *type, const TQString &filename, const TDEInstance *instance=TDEGlobal::instance())