~ubuntu-branches/ubuntu/trusty/librep/trusty

« back to all changes in this revision

Viewing changes to src/debug-buffer.c

  • Committer: Bazaar Package Importer
  • Author(s): Christian Marillat
  • Date: 2001-11-13 15:06:22 UTC
  • Revision ID: james.westby@ubuntu.com-20011113150622-vgmgmk6srj3kldr3
Tags: upstream-0.15.2
ImportĀ upstreamĀ versionĀ 0.15.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* debug-buffer.c -- Trace recording
 
2
   Copyright (C) 1997 John Harper <john@dcs.warwick.ac.uk>
 
3
   $Id: debug-buffer.c,v 1.15 2000/01/07 14:41:38 john Exp $
 
4
 
 
5
   This file is part of Jade.
 
6
 
 
7
   Jade is free software; you can redistribute it and/or modify it
 
8
   under the terms of the GNU General Public License as published by
 
9
   the Free Software Foundation; either version 2, or (at your option)
 
10
   any later version.
 
11
 
 
12
   Jade is distributed in the hope that it will be useful, but
 
13
   WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
   GNU General Public License for more details.
 
16
 
 
17
   You should have received a copy of the GNU General Public License
 
18
   along with Jade; see the file COPYING.       If not, write to
 
19
   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
20
 
 
21
#define _GNU_SOURCE
 
22
 
 
23
#include "repint.h"
 
24
 
 
25
#include <stdarg.h>
 
26
#include <stdlib.h>
 
27
#include <string.h>
 
28
#ifdef NEED_MEMORY_H
 
29
# include <memory.h>
 
30
#endif
 
31
 
 
32
struct debug_buf {
 
33
    struct debug_buf *next;
 
34
    char *name;
 
35
    int size, ptr;
 
36
    rep_bool wrapped;
 
37
    char data[1];
 
38
};
 
39
 
 
40
#define DB_SIZE(n) (sizeof(struct debug_buf) + (n) - 1)
 
41
 
 
42
static struct debug_buf *db_chain;
 
43
 
 
44
void *
 
45
rep_db_alloc(char *name, int size)
 
46
{
 
47
    struct debug_buf *db = rep_alloc(DB_SIZE(size));
 
48
    if(db == NULL)
 
49
    {
 
50
        perror("create_debug_buf");
 
51
        abort();
 
52
    }
 
53
    db->name = name;
 
54
    db->size = size;
 
55
    db->ptr = 0;
 
56
    db->wrapped = rep_FALSE;
 
57
    db->next = db_chain;
 
58
    db_chain = db;
 
59
 
 
60
    return db;
 
61
}
 
62
 
 
63
void
 
64
rep_db_free(void *_db)
 
65
{
 
66
    struct debug_buf *db = _db;
 
67
    struct debug_buf **x = &db_chain;
 
68
    while(*x != NULL)
 
69
    {
 
70
        if(*x == db)
 
71
        {
 
72
            *x = db->next;
 
73
            break;
 
74
        }
 
75
        x = &((*x)->next);
 
76
    }
 
77
    rep_free(db);
 
78
}
 
79
 
 
80
void
 
81
rep_db_vprintf(void *_db, char *fmt, va_list args)
 
82
{
 
83
    char buf[256];
 
84
    int length;
 
85
    struct debug_buf *db = _db;
 
86
 
 
87
#ifdef HAVE_SNPRINTF
 
88
    vsnprintf(buf, sizeof(buf), fmt, args);
 
89
#else
 
90
    vsprintf(buf, fmt, args);
 
91
#endif
 
92
    length = strlen(buf);
 
93
    if(length > db->size - db->ptr)
 
94
    {
 
95
        int before = db->size - db->ptr;
 
96
        int after = MIN(length - before, db->size - before);
 
97
        memcpy(db->data + db->ptr, buf, before);
 
98
        memcpy(db->data, buf + before, after);
 
99
        db->ptr = after;
 
100
        db->wrapped = rep_TRUE;
 
101
    }
 
102
    else
 
103
    {
 
104
        memcpy(db->data + db->ptr, buf, length);
 
105
        db->ptr += length;
 
106
    }
 
107
}
 
108
 
 
109
void
 
110
rep_db_printf(void *_db, char *fmt, ...)
 
111
{
 
112
    va_list args;
 
113
    va_start(args, fmt);
 
114
    rep_db_vprintf(_db, fmt, args);
 
115
    va_end(args);
 
116
}
 
117
 
 
118
void
 
119
rep_db_print_backtrace(void *_db, char *fun)
 
120
{
 
121
#if defined(__GNUC__) && ! defined(BROKEN_ALPHA_GCC)
 
122
 
 
123
#define BT_BASE 1
 
124
#define BT_DEPTH 8
 
125
 
 
126
    void *stack[BT_BASE+BT_DEPTH];
 
127
    int i;
 
128
 
 
129
    /* It seems that in Linux/egcs-1.1 __builtin_return_address()
 
130
       will segfault when reaching the top of the stack frame.
 
131
       The work-around is to see if we can get the frame address,
 
132
       if so it should be safe to go for the return address. */
 
133
# define STACK_PROBE(i)                                         \
 
134
    do {                                                        \
 
135
        if(i == BT_BASE || stack[i-1] != 0)                     \
 
136
        {                                                       \
 
137
            void *frame = __builtin_frame_address(i);           \
 
138
            if(frame != 0)                                      \
 
139
                stack[i] = __builtin_return_address(i);         \
 
140
            else                                                \
 
141
                stack[i] = 0;                                   \
 
142
        }                                                       \
 
143
        else                                                    \
 
144
            stack[i] = 0;                                       \
 
145
    } while(0)
 
146
 
 
147
    /* Should be from BT_BASE to BT_BASE+BT_DEPTH-1 */
 
148
    STACK_PROBE(1);  STACK_PROBE(2);  STACK_PROBE(3);  STACK_PROBE(4);
 
149
    STACK_PROBE(5);  STACK_PROBE(6);  STACK_PROBE(7);  STACK_PROBE(8);
 
150
 
 
151
    rep_db_printf(_db, "\nBacktrace in `%s':\n", fun);
 
152
    for(i = BT_BASE; i < BT_BASE+BT_DEPTH && stack[i] != 0; i++)
 
153
    {
 
154
#ifdef DB_RESOLVE_SYMBOLS
 
155
        if(stack[i] == 0)
 
156
            rep_db_printf(_db, "\t(nil)\n");
 
157
        else
 
158
        {
 
159
            char *name;
 
160
            void *addr;
 
161
            if(rep_find_c_symbol(stack[i], &name, &addr))
 
162
            {
 
163
                rep_db_printf(_db, "\t<%s+%d>\n", name,
 
164
                              ((char *)stack[i]) - ((char *)addr));
 
165
            }
 
166
            else
 
167
                rep_db_printf(_db, "\t0x%08lx\n", stack[i]);
 
168
        }
 
169
#else
 
170
        rep_db_printf(_db, "\t0x%08lx\n", stack[i]);
 
171
#endif
 
172
    }
 
173
#endif
 
174
}
 
175
 
 
176
void *
 
177
rep_db_return_address(void)
 
178
{
 
179
#if defined(__GNUC__) && ! defined(BROKEN_ALPHA_GCC)
 
180
    return __builtin_return_address(1);
 
181
#else
 
182
    return 0;
 
183
#endif
 
184
}
 
185
 
 
186
void
 
187
rep_db_spew(void *_db)
 
188
{
 
189
     struct debug_buf *db = _db;
 
190
 
 
191
     if(db->wrapped || db->ptr > 0)
 
192
     {
 
193
         fprintf(stderr, "\nstruct debug_buf %s:\n", db->name);
 
194
         if(db->wrapped)
 
195
         {
 
196
             fwrite(db->data + db->ptr, 1, db->size - db->ptr, stderr);
 
197
             fwrite(db->data, 1, db->ptr, stderr);
 
198
         }
 
199
         else
 
200
             fwrite(db->data, 1, db->ptr, stderr);
 
201
     }
 
202
}
 
203
 
 
204
void
 
205
rep_db_spew_all(void)
 
206
{
 
207
    struct debug_buf *db = db_chain;
 
208
    while(db != NULL)
 
209
    {
 
210
        rep_db_spew(db);
 
211
        db = db->next;
 
212
    }
 
213
}
 
214
 
 
215
void
 
216
rep_db_kill(void)
 
217
{
 
218
    struct debug_buf *db = db_chain;
 
219
    rep_db_spew_all();
 
220
    db_chain = NULL;
 
221
    while(db != NULL)
 
222
    {
 
223
        struct debug_buf *next = db->next;
 
224
        rep_free(db);
 
225
        db = next;
 
226
    }
 
227
}