Coverage Report

Created: 2025-11-02 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Python/traceback.c
Line
Count
Source
1
2
/* Traceback implementation */
3
4
#include "Python.h"
5
#include "pycore_call.h"          // _PyObject_CallMethodFormat()
6
#include "pycore_fileutils.h"     // _Py_BEGIN_SUPPRESS_IPH
7
#include "pycore_frame.h"         // PyFrameObject
8
#include "pycore_interp.h"        // PyInterpreterState.gc
9
#include "pycore_interpframe.h"   // _PyFrame_GetCode()
10
#include "pycore_pyerrors.h"      // _PyErr_GetRaisedException()
11
#include "pycore_pystate.h"       // _PyThreadState_GET()
12
#include "pycore_traceback.h"     // EXCEPTION_TB_HEADER
13
14
#include "frameobject.h"          // PyFrame_New()
15
16
#include "osdefs.h"               // SEP
17
#ifdef HAVE_UNISTD_H
18
#  include <unistd.h>             // lseek()
19
#endif
20
21
#if (defined(HAVE_EXECINFO_H) && defined(HAVE_DLFCN_H) && defined(HAVE_LINK_H))
22
#  define _PY_HAS_BACKTRACE_HEADERS 1
23
#endif
24
25
#if (defined(__APPLE__) && defined(HAVE_EXECINFO_H) && defined(HAVE_DLFCN_H))
26
#  define _PY_HAS_BACKTRACE_HEADERS 1
27
#endif
28
29
#ifdef _PY_HAS_BACKTRACE_HEADERS
30
#  include <execinfo.h>           // backtrace(), backtrace_symbols()
31
#  include <dlfcn.h>              // dladdr1()
32
#ifdef HAVE_LINK_H
33
#    include <link.h>               // struct DL_info
34
#endif
35
#  if defined(__APPLE__) && defined(HAVE_BACKTRACE) && defined(HAVE_DLADDR)
36
#    define CAN_C_BACKTRACE
37
#  elif defined(HAVE_BACKTRACE) && defined(HAVE_DLADDR1)
38
#    define CAN_C_BACKTRACE
39
#  endif
40
#endif
41
42
#if defined(__STDC_NO_VLA__) && (__STDC_NO_VLA__ == 1)
43
/* Use alloca() for VLAs. */
44
#  define VLA(type, name, size) type *name = alloca(size)
45
#elif !defined(__STDC_NO_VLA__) || (__STDC_NO_VLA__ == 0)
46
/* Use actual C VLAs.*/
47
0
#  define VLA(type, name, size) type name[size]
48
#elif defined(CAN_C_BACKTRACE)
49
/* VLAs are not possible. Disable C stack trace functions. */
50
#  undef CAN_C_BACKTRACE
51
#endif
52
53
#define OFF(x) offsetof(PyTracebackObject, x)
54
0
#define PUTS(fd, str) (void)_Py_write_noraise(fd, str, strlen(str))
55
56
0
#define MAX_STRING_LENGTH 500
57
0
#define MAX_FRAME_DEPTH 100
58
0
#define MAX_NTHREADS 100
59
60
/* Function from Parser/tokenizer/file_tokenizer.c */
61
extern char* _PyTokenizer_FindEncodingFilename(int, PyObject *);
62
63
/*[clinic input]
64
class traceback "PyTracebackObject *" "&PyTraceback_Type"
65
[clinic start generated code]*/
66
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=cf96294b2bebc811]*/
67
68
31.4M
#define _PyTracebackObject_CAST(op)   ((PyTracebackObject *)(op))
69
70
#include "clinic/traceback.c.h"
71
72
73
#ifdef MS_WINDOWS
74
typedef HRESULT (WINAPI *PF_GET_THREAD_DESCRIPTION)(HANDLE, PCWSTR*);
75
static PF_GET_THREAD_DESCRIPTION pGetThreadDescription = NULL;
76
#endif
77
78
79
static PyObject *
80
tb_create_raw(PyTracebackObject *next, PyFrameObject *frame, int lasti,
81
              int lineno)
82
31.4M
{
83
31.4M
    PyTracebackObject *tb;
84
31.4M
    if ((next != NULL && !PyTraceBack_Check(next)) ||
85
31.4M
                    frame == NULL || !PyFrame_Check(frame)) {
86
0
        PyErr_BadInternalCall();
87
0
        return NULL;
88
0
    }
89
31.4M
    tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type);
90
31.4M
    if (tb != NULL) {
91
31.4M
        tb->tb_next = (PyTracebackObject*)Py_XNewRef(next);
92
31.4M
        tb->tb_frame = (PyFrameObject*)Py_XNewRef(frame);
93
31.4M
        tb->tb_lasti = lasti;
94
31.4M
        tb->tb_lineno = lineno;
95
31.4M
        PyObject_GC_Track(tb);
96
31.4M
    }
97
31.4M
    return (PyObject *)tb;
98
31.4M
}
99
100
/*[clinic input]
101
@classmethod
102
traceback.__new__ as tb_new
103
104
  tb_next: object
105
  tb_frame: object(type='PyFrameObject *', subclass_of='&PyFrame_Type')
106
  tb_lasti: int
107
  tb_lineno: int
108
109
Create a new traceback object.
110
[clinic start generated code]*/
111
112
static PyObject *
113
tb_new_impl(PyTypeObject *type, PyObject *tb_next, PyFrameObject *tb_frame,
114
            int tb_lasti, int tb_lineno)
115
/*[clinic end generated code: output=fa077debd72d861a input=b88143145454cb59]*/
116
0
{
117
0
    if (tb_next == Py_None) {
118
0
        tb_next = NULL;
119
0
    } else if (!PyTraceBack_Check(tb_next)) {
120
0
        return PyErr_Format(PyExc_TypeError,
121
0
                            "expected traceback object or None, got '%s'",
122
0
                            Py_TYPE(tb_next)->tp_name);
123
0
    }
124
125
0
    return tb_create_raw((PyTracebackObject *)tb_next, tb_frame, tb_lasti,
126
0
                         tb_lineno);
127
0
}
128
129
static PyObject *
130
tb_dir(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
131
0
{
132
0
    return Py_BuildValue("[ssss]", "tb_frame", "tb_next",
133
0
                                   "tb_lasti", "tb_lineno");
134
0
}
135
136
/*[clinic input]
137
@critical_section
138
@getter
139
traceback.tb_next
140
[clinic start generated code]*/
141
142
static PyObject *
143
traceback_tb_next_get_impl(PyTracebackObject *self)
144
/*[clinic end generated code: output=963634df7d5fc837 input=8f6345f2b73cb965]*/
145
0
{
146
0
    PyObject* ret = (PyObject*)self->tb_next;
147
0
    if (!ret) {
148
0
        ret = Py_None;
149
0
    }
150
0
    return Py_NewRef(ret);
151
0
}
152
153
static int
154
tb_get_lineno(PyObject *op)
155
0
{
156
0
    PyTracebackObject *tb = _PyTracebackObject_CAST(op);
157
0
    _PyInterpreterFrame* frame = tb->tb_frame->f_frame;
158
0
    assert(frame != NULL);
159
0
    return PyCode_Addr2Line(_PyFrame_GetCode(frame), tb->tb_lasti);
160
0
}
161
162
static PyObject *
163
tb_lineno_get(PyObject *op, void *Py_UNUSED(_))
164
0
{
165
0
    PyTracebackObject *self = _PyTracebackObject_CAST(op);
166
0
    int lineno = self->tb_lineno;
167
0
    if (lineno == -1) {
168
0
        lineno = tb_get_lineno(op);
169
0
        if (lineno < 0) {
170
0
            Py_RETURN_NONE;
171
0
        }
172
0
    }
173
0
    return PyLong_FromLong(lineno);
174
0
}
175
176
/*[clinic input]
177
@critical_section
178
@setter
179
traceback.tb_next
180
[clinic start generated code]*/
181
182
static int
183
traceback_tb_next_set_impl(PyTracebackObject *self, PyObject *value)
184
/*[clinic end generated code: output=d4868cbc48f2adac input=ce66367f85e3c443]*/
185
0
{
186
0
    if (!value) {
187
0
        PyErr_Format(PyExc_TypeError, "can't delete tb_next attribute");
188
0
        return -1;
189
0
    }
190
191
    /* We accept None or a traceback object, and map None -> NULL (inverse of
192
       tb_next_get) */
193
0
    if (value == Py_None) {
194
0
        value = NULL;
195
0
    } else if (!PyTraceBack_Check(value)) {
196
0
        PyErr_Format(PyExc_TypeError,
197
0
                     "expected traceback object, got '%s'",
198
0
                     Py_TYPE(value)->tp_name);
199
0
        return -1;
200
0
    }
201
202
    /* Check for loops */
203
0
    PyTracebackObject *cursor = (PyTracebackObject *)value;
204
0
    Py_XINCREF(cursor);
205
0
    while (cursor) {
206
0
        if (cursor == self) {
207
0
            PyErr_Format(PyExc_ValueError, "traceback loop detected");
208
0
            Py_DECREF(cursor);
209
0
            return -1;
210
0
        }
211
0
        Py_BEGIN_CRITICAL_SECTION(cursor);
212
0
        Py_XINCREF(cursor->tb_next);
213
0
        Py_SETREF(cursor, cursor->tb_next);
214
0
        Py_END_CRITICAL_SECTION();
215
0
    }
216
217
0
    Py_XSETREF(self->tb_next, (PyTracebackObject *)Py_XNewRef(value));
218
219
0
    return 0;
220
0
}
221
222
223
static PyMethodDef tb_methods[] = {
224
   {"__dir__", tb_dir, METH_NOARGS, NULL},
225
   {NULL, NULL, 0, NULL},
226
};
227
228
static PyMemberDef tb_memberlist[] = {
229
    {"tb_frame",        _Py_T_OBJECT,       OFF(tb_frame),  Py_READONLY|Py_AUDIT_READ},
230
    {"tb_lasti",        Py_T_INT,          OFF(tb_lasti),  Py_READONLY},
231
    {NULL}      /* Sentinel */
232
};
233
234
static PyGetSetDef tb_getsetters[] = {
235
    TRACEBACK_TB_NEXT_GETSETDEF
236
    {"tb_lineno", tb_lineno_get, NULL, NULL, NULL},
237
    {NULL}      /* Sentinel */
238
};
239
240
static void
241
tb_dealloc(PyObject *op)
242
31.4M
{
243
31.4M
    PyTracebackObject *tb = _PyTracebackObject_CAST(op);
244
31.4M
    PyObject_GC_UnTrack(tb);
245
31.4M
    Py_XDECREF(tb->tb_next);
246
31.4M
    Py_XDECREF(tb->tb_frame);
247
31.4M
    PyObject_GC_Del(tb);
248
31.4M
}
249
250
static int
251
tb_traverse(PyObject *op, visitproc visit, void *arg)
252
31.9k
{
253
31.9k
    PyTracebackObject *tb = _PyTracebackObject_CAST(op);
254
31.9k
    Py_VISIT(tb->tb_next);
255
31.9k
    Py_VISIT(tb->tb_frame);
256
31.9k
    return 0;
257
31.9k
}
258
259
static int
260
tb_clear(PyObject *op)
261
0
{
262
0
    PyTracebackObject *tb = _PyTracebackObject_CAST(op);
263
0
    Py_CLEAR(tb->tb_next);
264
0
    Py_CLEAR(tb->tb_frame);
265
0
    return 0;
266
0
}
267
268
PyTypeObject PyTraceBack_Type = {
269
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
270
    "traceback",
271
    sizeof(PyTracebackObject),
272
    0,
273
    tb_dealloc,         /*tp_dealloc*/
274
    0,                  /*tp_vectorcall_offset*/
275
    0,    /*tp_getattr*/
276
    0,                  /*tp_setattr*/
277
    0,                  /*tp_as_async*/
278
    0,                  /*tp_repr*/
279
    0,                  /*tp_as_number*/
280
    0,                  /*tp_as_sequence*/
281
    0,                  /*tp_as_mapping*/
282
    0,                  /* tp_hash */
283
    0,                  /* tp_call */
284
    0,                  /* tp_str */
285
    PyObject_GenericGetAttr,                    /* tp_getattro */
286
    0,                  /* tp_setattro */
287
    0,                                          /* tp_as_buffer */
288
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
289
    tb_new__doc__,                              /* tp_doc */
290
    tb_traverse,                                /* tp_traverse */
291
    tb_clear,                                   /* tp_clear */
292
    0,                                          /* tp_richcompare */
293
    0,                                          /* tp_weaklistoffset */
294
    0,                                          /* tp_iter */
295
    0,                                          /* tp_iternext */
296
    tb_methods,         /* tp_methods */
297
    tb_memberlist,      /* tp_members */
298
    tb_getsetters,                              /* tp_getset */
299
    0,                                          /* tp_base */
300
    0,                                          /* tp_dict */
301
    0,                                          /* tp_descr_get */
302
    0,                                          /* tp_descr_set */
303
    0,                                          /* tp_dictoffset */
304
    0,                                          /* tp_init */
305
    0,                                          /* tp_alloc */
306
    tb_new,                                     /* tp_new */
307
};
308
309
310
PyObject*
311
_PyTraceBack_FromFrame(PyObject *tb_next, PyFrameObject *frame)
312
31.4M
{
313
31.4M
    assert(tb_next == NULL || PyTraceBack_Check(tb_next));
314
31.4M
    assert(frame != NULL);
315
31.4M
    int addr = _PyInterpreterFrame_LASTI(frame->f_frame) * sizeof(_Py_CODEUNIT);
316
31.4M
    return tb_create_raw((PyTracebackObject *)tb_next, frame, addr, -1);
317
31.4M
}
318
319
320
int
321
PyTraceBack_Here(PyFrameObject *frame)
322
31.4M
{
323
31.4M
    PyObject *exc = PyErr_GetRaisedException();
324
31.4M
    assert(PyExceptionInstance_Check(exc));
325
31.4M
    PyObject *tb = PyException_GetTraceback(exc);
326
31.4M
    PyObject *newtb = _PyTraceBack_FromFrame(tb, frame);
327
31.4M
    Py_XDECREF(tb);
328
31.4M
    if (newtb == NULL) {
329
0
        _PyErr_ChainExceptions1(exc);
330
0
        return -1;
331
0
    }
332
31.4M
    PyException_SetTraceback(exc, newtb);
333
31.4M
    Py_XDECREF(newtb);
334
31.4M
    PyErr_SetRaisedException(exc);
335
31.4M
    return 0;
336
31.4M
}
337
338
/* Insert a frame into the traceback for (funcname, filename, lineno). */
339
void _PyTraceback_Add(const char *funcname, const char *filename, int lineno)
340
0
{
341
0
    PyObject *globals;
342
0
    PyCodeObject *code;
343
0
    PyFrameObject *frame;
344
0
    PyThreadState *tstate = _PyThreadState_GET();
345
346
    /* Save and clear the current exception. Python functions must not be
347
       called with an exception set. Calling Python functions happens when
348
       the codec of the filesystem encoding is implemented in pure Python. */
349
0
    PyObject *exc = _PyErr_GetRaisedException(tstate);
350
351
0
    globals = PyDict_New();
352
0
    if (!globals)
353
0
        goto error;
354
0
    code = PyCode_NewEmpty(filename, funcname, lineno);
355
0
    if (!code) {
356
0
        Py_DECREF(globals);
357
0
        goto error;
358
0
    }
359
0
    frame = PyFrame_New(tstate, code, globals, NULL);
360
0
    Py_DECREF(globals);
361
0
    Py_DECREF(code);
362
0
    if (!frame)
363
0
        goto error;
364
0
    frame->f_lineno = lineno;
365
366
0
    _PyErr_SetRaisedException(tstate, exc);
367
0
    PyTraceBack_Here(frame);
368
0
    Py_DECREF(frame);
369
0
    return;
370
371
0
error:
372
0
    _PyErr_ChainExceptions1(exc);
373
0
}
374
375
static PyObject *
376
_Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject *io)
377
0
{
378
0
    Py_ssize_t i;
379
0
    PyObject *binary;
380
0
    PyObject *v;
381
0
    Py_ssize_t npath;
382
0
    size_t taillen;
383
0
    PyObject *syspath;
384
0
    PyObject *path;
385
0
    const char* tail;
386
0
    PyObject *filebytes;
387
0
    const char* filepath;
388
0
    Py_ssize_t len;
389
0
    PyObject* result;
390
0
    PyObject *open = NULL;
391
392
0
    filebytes = PyUnicode_EncodeFSDefault(filename);
393
0
    if (filebytes == NULL) {
394
0
        PyErr_Clear();
395
0
        return NULL;
396
0
    }
397
0
    filepath = PyBytes_AS_STRING(filebytes);
398
399
    /* Search tail of filename in sys.path before giving up */
400
0
    tail = strrchr(filepath, SEP);
401
0
    if (tail == NULL)
402
0
        tail = filepath;
403
0
    else
404
0
        tail++;
405
0
    taillen = strlen(tail);
406
407
0
    PyThreadState *tstate = _PyThreadState_GET();
408
0
    if (PySys_GetOptionalAttr(&_Py_ID(path), &syspath) < 0) {
409
0
        PyErr_Clear();
410
0
        goto error;
411
0
    }
412
0
    if (syspath == NULL || !PyList_Check(syspath)) {
413
0
        goto error;
414
0
    }
415
0
    npath = PyList_Size(syspath);
416
417
0
    open = PyObject_GetAttr(io, &_Py_ID(open));
418
0
    for (i = 0; i < npath; i++) {
419
0
        v = PyList_GetItem(syspath, i);
420
0
        if (v == NULL) {
421
0
            PyErr_Clear();
422
0
            break;
423
0
        }
424
0
        if (!PyUnicode_Check(v))
425
0
            continue;
426
0
        path = PyUnicode_EncodeFSDefault(v);
427
0
        if (path == NULL) {
428
0
            PyErr_Clear();
429
0
            continue;
430
0
        }
431
0
        len = PyBytes_GET_SIZE(path);
432
0
        if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1) {
433
0
            Py_DECREF(path);
434
0
            continue; /* Too long */
435
0
        }
436
0
        strcpy(namebuf, PyBytes_AS_STRING(path));
437
0
        Py_DECREF(path);
438
0
        if (strlen(namebuf) != (size_t)len)
439
0
            continue; /* v contains '\0' */
440
0
        if (len > 0 && namebuf[len-1] != SEP)
441
0
            namebuf[len++] = SEP;
442
0
        strcpy(namebuf+len, tail);
443
444
0
        binary = _PyObject_CallMethodFormat(tstate, open, "ss", namebuf, "rb");
445
0
        if (binary != NULL) {
446
0
            result = binary;
447
0
            goto finally;
448
0
        }
449
0
        PyErr_Clear();
450
0
    }
451
0
    goto error;
452
453
0
error:
454
0
    result = NULL;
455
0
finally:
456
0
    Py_XDECREF(open);
457
0
    Py_XDECREF(syspath);
458
0
    Py_DECREF(filebytes);
459
0
    return result;
460
0
}
461
462
/* Writes indent spaces. Returns 0 on success and non-zero on failure.
463
 */
464
int
465
_Py_WriteIndent(int indent, PyObject *f)
466
0
{
467
0
    char buf[11] = "          ";
468
0
    assert(strlen(buf) == 10);
469
0
    while (indent > 0) {
470
0
        if (indent < 10) {
471
0
            buf[indent] = '\0';
472
0
        }
473
0
        if (PyFile_WriteString(buf, f) < 0) {
474
0
            return -1;
475
0
        }
476
0
        indent -= 10;
477
0
    }
478
0
    return 0;
479
0
}
480
481
static int
482
display_source_line(PyObject *f, PyObject *filename, int lineno, int indent,
483
                    int *truncation, PyObject **line)
484
0
{
485
0
    int fd;
486
0
    int i;
487
0
    char *found_encoding;
488
0
    const char *encoding;
489
0
    PyObject *io;
490
0
    PyObject *binary;
491
0
    PyObject *fob = NULL;
492
0
    PyObject *lineobj = NULL;
493
0
    PyObject *res;
494
0
    char buf[MAXPATHLEN+1];
495
0
    int kind;
496
0
    const void *data;
497
498
    /* open the file */
499
0
    if (filename == NULL)
500
0
        return 0;
501
502
    /* Do not attempt to open things like <string> or <stdin> */
503
0
    assert(PyUnicode_Check(filename));
504
0
    if (PyUnicode_READ_CHAR(filename, 0) == '<') {
505
0
        Py_ssize_t len = PyUnicode_GET_LENGTH(filename);
506
0
        if (len > 0 && PyUnicode_READ_CHAR(filename, len - 1) == '>') {
507
0
            return 0;
508
0
        }
509
0
    }
510
511
0
    io = PyImport_ImportModule("io");
512
0
    if (io == NULL) {
513
0
        return -1;
514
0
    }
515
516
0
    binary = _PyObject_CallMethod(io, &_Py_ID(open), "Os", filename, "rb");
517
0
    if (binary == NULL) {
518
0
        PyErr_Clear();
519
520
0
        binary = _Py_FindSourceFile(filename, buf, sizeof(buf), io);
521
0
        if (binary == NULL) {
522
0
            Py_DECREF(io);
523
0
            return -1;
524
0
        }
525
0
    }
526
527
    /* use the right encoding to decode the file as unicode */
528
0
    fd = PyObject_AsFileDescriptor(binary);
529
0
    if (fd < 0) {
530
0
        Py_DECREF(io);
531
0
        Py_DECREF(binary);
532
0
        return 0;
533
0
    }
534
0
    found_encoding = _PyTokenizer_FindEncodingFilename(fd, filename);
535
0
    if (found_encoding == NULL)
536
0
        PyErr_Clear();
537
0
    encoding = (found_encoding != NULL) ? found_encoding : "utf-8";
538
    /* Reset position */
539
0
    if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
540
0
        Py_DECREF(io);
541
0
        Py_DECREF(binary);
542
0
        PyMem_Free(found_encoding);
543
0
        return 0;
544
0
    }
545
0
    fob = _PyObject_CallMethod(io, &_Py_ID(TextIOWrapper),
546
0
                               "Os", binary, encoding);
547
0
    Py_DECREF(io);
548
0
    PyMem_Free(found_encoding);
549
550
0
    if (fob == NULL) {
551
0
        PyErr_Clear();
552
553
0
        res = PyObject_CallMethodNoArgs(binary, &_Py_ID(close));
554
0
        Py_DECREF(binary);
555
0
        if (res)
556
0
            Py_DECREF(res);
557
0
        else
558
0
            PyErr_Clear();
559
0
        return 0;
560
0
    }
561
0
    Py_DECREF(binary);
562
563
    /* get the line number lineno */
564
0
    for (i = 0; i < lineno; i++) {
565
0
        Py_XDECREF(lineobj);
566
0
        lineobj = PyFile_GetLine(fob, -1);
567
0
        if (!lineobj) {
568
0
            PyErr_Clear();
569
0
            break;
570
0
        }
571
0
    }
572
0
    res = PyObject_CallMethodNoArgs(fob, &_Py_ID(close));
573
0
    if (res) {
574
0
        Py_DECREF(res);
575
0
    }
576
0
    else {
577
0
        PyErr_Clear();
578
0
    }
579
0
    Py_DECREF(fob);
580
0
    if (!lineobj || !PyUnicode_Check(lineobj)) {
581
0
        Py_XDECREF(lineobj);
582
0
        return -1;
583
0
    }
584
585
0
    if (line) {
586
0
        *line = Py_NewRef(lineobj);
587
0
    }
588
589
    /* remove the indentation of the line */
590
0
    kind = PyUnicode_KIND(lineobj);
591
0
    data = PyUnicode_DATA(lineobj);
592
0
    for (i=0; i < PyUnicode_GET_LENGTH(lineobj); i++) {
593
0
        Py_UCS4 ch = PyUnicode_READ(kind, data, i);
594
0
        if (ch != ' ' && ch != '\t' && ch != '\014')
595
0
            break;
596
0
    }
597
0
    if (i) {
598
0
        PyObject *truncated;
599
0
        truncated = PyUnicode_Substring(lineobj, i, PyUnicode_GET_LENGTH(lineobj));
600
0
        if (truncated) {
601
0
            Py_SETREF(lineobj, truncated);
602
0
        } else {
603
0
            PyErr_Clear();
604
0
        }
605
0
    }
606
607
0
    if (truncation != NULL) {
608
0
        *truncation = i - indent;
609
0
    }
610
611
    /* Write some spaces before the line */
612
0
    if (_Py_WriteIndent(indent, f) < 0) {
613
0
        goto error;
614
0
    }
615
616
    /* finally display the line */
617
0
    if (PyFile_WriteObject(lineobj, f, Py_PRINT_RAW) < 0) {
618
0
        goto error;
619
0
    }
620
621
0
    if (PyFile_WriteString("\n", f) < 0) {
622
0
        goto error;
623
0
    }
624
625
0
    Py_DECREF(lineobj);
626
0
    return 0;
627
0
error:
628
0
    Py_DECREF(lineobj);
629
0
    return -1;
630
0
}
631
632
int
633
_Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent,
634
                      int *truncation, PyObject **line)
635
0
{
636
0
    return display_source_line(f, filename, lineno, indent, truncation, line);
637
0
}
638
639
640
#define IS_WHITESPACE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\f'))
641
0
#define _TRACEBACK_SOURCE_LINE_INDENT 4
642
643
static inline int
644
0
ignore_source_errors(void) {
645
0
    if (PyErr_Occurred()) {
646
0
        if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
647
0
            return -1;
648
0
        }
649
0
        PyErr_Clear();
650
0
    }
651
0
    return 0;
652
0
}
653
654
static int
655
tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int lineno,
656
               PyFrameObject *frame, PyObject *name)
657
0
{
658
0
    if (filename == NULL || name == NULL) {
659
0
        return -1;
660
0
    }
661
662
0
    PyObject *line = PyUnicode_FromFormat("  File \"%U\", line %d, in %U\n",
663
0
                                          filename, lineno, name);
664
0
    if (line == NULL) {
665
0
        return -1;
666
0
    }
667
668
0
    int res = PyFile_WriteObject(line, f, Py_PRINT_RAW);
669
0
    Py_DECREF(line);
670
0
    if (res < 0) {
671
0
        return -1;
672
0
    }
673
674
0
    int err = 0;
675
676
0
    int truncation = _TRACEBACK_SOURCE_LINE_INDENT;
677
0
    PyObject* source_line = NULL;
678
0
    int rc = display_source_line(
679
0
            f, filename, lineno, _TRACEBACK_SOURCE_LINE_INDENT,
680
0
            &truncation, &source_line);
681
0
    if (rc != 0 || !source_line) {
682
        /* ignore errors since we can't report them, can we? */
683
0
        err = ignore_source_errors();
684
0
    }
685
0
    Py_XDECREF(source_line);
686
0
    return err;
687
0
}
688
689
static const int TB_RECURSIVE_CUTOFF = 3; // Also hardcoded in traceback.py.
690
691
static int
692
tb_print_line_repeated(PyObject *f, long cnt)
693
0
{
694
0
    cnt -= TB_RECURSIVE_CUTOFF;
695
0
    PyObject *line = PyUnicode_FromFormat(
696
0
        (cnt > 1)
697
0
          ? "  [Previous line repeated %ld more times]\n"
698
0
          : "  [Previous line repeated %ld more time]\n",
699
0
        cnt);
700
0
    if (line == NULL) {
701
0
        return -1;
702
0
    }
703
0
    int err = PyFile_WriteObject(line, f, Py_PRINT_RAW);
704
0
    Py_DECREF(line);
705
0
    return err;
706
0
}
707
708
static int
709
tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
710
0
{
711
0
    PyCodeObject *code = NULL;
712
0
    Py_ssize_t depth = 0;
713
0
    PyObject *last_file = NULL;
714
0
    int last_line = -1;
715
0
    PyObject *last_name = NULL;
716
0
    long cnt = 0;
717
0
    PyTracebackObject *tb1 = tb;
718
0
    while (tb1 != NULL) {
719
0
        depth++;
720
0
        tb1 = tb1->tb_next;
721
0
    }
722
0
    while (tb != NULL && depth > limit) {
723
0
        depth--;
724
0
        tb = tb->tb_next;
725
0
    }
726
0
    while (tb != NULL) {
727
0
        code = PyFrame_GetCode(tb->tb_frame);
728
0
        int tb_lineno = tb->tb_lineno;
729
0
        if (tb_lineno == -1) {
730
0
            tb_lineno = tb_get_lineno((PyObject *)tb);
731
0
        }
732
0
        if (last_file == NULL ||
733
0
            code->co_filename != last_file ||
734
0
            last_line == -1 || tb_lineno != last_line ||
735
0
            last_name == NULL || code->co_name != last_name) {
736
0
            if (cnt > TB_RECURSIVE_CUTOFF) {
737
0
                if (tb_print_line_repeated(f, cnt) < 0) {
738
0
                    goto error;
739
0
                }
740
0
            }
741
0
            last_file = code->co_filename;
742
0
            last_line = tb_lineno;
743
0
            last_name = code->co_name;
744
0
            cnt = 0;
745
0
        }
746
0
        cnt++;
747
0
        if (cnt <= TB_RECURSIVE_CUTOFF) {
748
0
            if (tb_displayline(tb, f, code->co_filename, tb_lineno,
749
0
                               tb->tb_frame, code->co_name) < 0) {
750
0
                goto error;
751
0
            }
752
753
0
            if (PyErr_CheckSignals() < 0) {
754
0
                goto error;
755
0
            }
756
0
        }
757
0
        Py_CLEAR(code);
758
0
        tb = tb->tb_next;
759
0
    }
760
0
    if (cnt > TB_RECURSIVE_CUTOFF) {
761
0
        if (tb_print_line_repeated(f, cnt) < 0) {
762
0
            goto error;
763
0
        }
764
0
    }
765
0
    return 0;
766
0
error:
767
0
    Py_XDECREF(code);
768
0
    return -1;
769
0
}
770
771
0
#define PyTraceBack_LIMIT 1000
772
773
int
774
_PyTraceBack_Print(PyObject *v, const char *header, PyObject *f)
775
0
{
776
0
    PyObject *limitv;
777
0
    long limit = PyTraceBack_LIMIT;
778
779
0
    if (v == NULL) {
780
0
        return 0;
781
0
    }
782
0
    if (!PyTraceBack_Check(v)) {
783
0
        PyErr_BadInternalCall();
784
0
        return -1;
785
0
    }
786
0
    if (PySys_GetOptionalAttrString("tracebacklimit", &limitv) < 0) {
787
0
        return -1;
788
0
    }
789
0
    else if (limitv != NULL && PyLong_Check(limitv)) {
790
0
        int overflow;
791
0
        limit = PyLong_AsLongAndOverflow(limitv, &overflow);
792
0
        if (overflow > 0) {
793
0
            limit = LONG_MAX;
794
0
        }
795
0
        else if (limit <= 0) {
796
0
            Py_DECREF(limitv);
797
0
            return 0;
798
0
        }
799
0
    }
800
0
    Py_XDECREF(limitv);
801
802
0
    if (PyFile_WriteString(header, f) < 0) {
803
0
        return -1;
804
0
    }
805
806
0
    if (tb_printinternal((PyTracebackObject *)v, f, limit) < 0) {
807
0
        return -1;
808
0
    }
809
810
0
    return 0;
811
0
}
812
813
int
814
PyTraceBack_Print(PyObject *v, PyObject *f)
815
0
{
816
0
    const char *header = EXCEPTION_TB_HEADER;
817
0
    return _PyTraceBack_Print(v, header, f);
818
0
}
819
820
/* Format an integer in range [0; 0xffffffff] to decimal and write it
821
   into the file fd.
822
823
   This function is signal safe. */
824
825
void
826
_Py_DumpDecimal(int fd, size_t value)
827
0
{
828
    /* maximum number of characters required for output of %lld or %p.
829
       We need at most ceil(log10(256)*SIZEOF_LONG_LONG) digits,
830
       plus 1 for the null byte.  53/22 is an upper bound for log10(256). */
831
0
    char buffer[1 + (sizeof(size_t)*53-1) / 22 + 1];
832
0
    char *ptr, *end;
833
834
0
    end = &buffer[Py_ARRAY_LENGTH(buffer) - 1];
835
0
    ptr = end;
836
0
    *ptr = '\0';
837
0
    do {
838
0
        --ptr;
839
0
        assert(ptr >= buffer);
840
0
        *ptr = '0' + (value % 10);
841
0
        value /= 10;
842
0
    } while (value);
843
844
0
    (void)_Py_write_noraise(fd, ptr, end - ptr);
845
0
}
846
847
/* Format an integer as hexadecimal with width digits into fd file descriptor.
848
   The function is signal safe. */
849
static void
850
dump_hexadecimal(int fd, uintptr_t value, Py_ssize_t width, int strip_zeros)
851
0
{
852
0
    char buffer[sizeof(uintptr_t) * 2 + 1], *ptr, *end;
853
0
    Py_ssize_t size = Py_ARRAY_LENGTH(buffer) - 1;
854
855
0
    if (width > size)
856
0
        width = size;
857
    /* it's ok if width is negative */
858
859
0
    end = &buffer[size];
860
0
    ptr = end;
861
0
    *ptr = '\0';
862
0
    do {
863
0
        --ptr;
864
0
        assert(ptr >= buffer);
865
0
        *ptr = Py_hexdigits[value & 15];
866
0
        value >>= 4;
867
0
    } while ((end - ptr) < width || value);
868
869
0
    size = end - ptr;
870
0
    if (strip_zeros) {
871
0
        while (*ptr == '0' && size >= 2) {
872
0
            ptr++;
873
0
            size--;
874
0
        }
875
0
    }
876
877
0
    (void)_Py_write_noraise(fd, ptr, size);
878
0
}
879
880
void
881
_Py_DumpHexadecimal(int fd, uintptr_t value, Py_ssize_t width)
882
0
{
883
0
    dump_hexadecimal(fd, value, width, 0);
884
0
}
885
886
#ifdef CAN_C_BACKTRACE
887
static void
888
dump_pointer(int fd, void *ptr)
889
0
{
890
0
    PUTS(fd, "0x");
891
0
    dump_hexadecimal(fd, (uintptr_t)ptr, sizeof(void*), 1);
892
0
}
893
#endif
894
895
static void
896
dump_char(int fd, char ch)
897
0
{
898
0
    char buf[1] = {ch};
899
0
    (void)_Py_write_noraise(fd, buf, 1);
900
0
}
901
902
void
903
_Py_DumpASCII(int fd, PyObject *text)
904
0
{
905
0
    PyASCIIObject *ascii = _PyASCIIObject_CAST(text);
906
0
    Py_ssize_t i, size;
907
0
    int truncated;
908
0
    int kind;
909
0
    void *data = NULL;
910
0
    Py_UCS4 ch;
911
912
0
    if (!PyUnicode_Check(text))
913
0
        return;
914
915
0
    size = ascii->length;
916
0
    kind = ascii->state.kind;
917
0
    if (ascii->state.compact) {
918
0
        if (ascii->state.ascii)
919
0
            data = ascii + 1;
920
0
        else
921
0
            data = _PyCompactUnicodeObject_CAST(text) + 1;
922
0
    }
923
0
    else {
924
0
        data = _PyUnicodeObject_CAST(text)->data.any;
925
0
        if (data == NULL)
926
0
            return;
927
0
    }
928
929
0
    if (MAX_STRING_LENGTH < size) {
930
0
        size = MAX_STRING_LENGTH;
931
0
        truncated = 1;
932
0
    }
933
0
    else {
934
0
        truncated = 0;
935
0
    }
936
937
    // Is an ASCII string?
938
0
    if (ascii->state.ascii) {
939
0
        assert(kind == PyUnicode_1BYTE_KIND);
940
0
        char *str = data;
941
942
0
        int need_escape = 0;
943
0
        for (i=0; i < size; i++) {
944
0
            ch = str[i];
945
0
            if (!(' ' <= ch && ch <= 126)) {
946
0
                need_escape = 1;
947
0
                break;
948
0
            }
949
0
        }
950
0
        if (!need_escape) {
951
            // The string can be written with a single write() syscall
952
0
            (void)_Py_write_noraise(fd, str, size);
953
0
            goto done;
954
0
        }
955
0
    }
956
957
0
    for (i=0; i < size; i++) {
958
0
        ch = PyUnicode_READ(kind, data, i);
959
0
        if (' ' <= ch && ch <= 126) {
960
            /* printable ASCII character */
961
0
            dump_char(fd, (char)ch);
962
0
        }
963
0
        else if (ch <= 0xff) {
964
0
            PUTS(fd, "\\x");
965
0
            _Py_DumpHexadecimal(fd, ch, 2);
966
0
        }
967
0
        else if (ch <= 0xffff) {
968
0
            PUTS(fd, "\\u");
969
0
            _Py_DumpHexadecimal(fd, ch, 4);
970
0
        }
971
0
        else {
972
0
            PUTS(fd, "\\U");
973
0
            _Py_DumpHexadecimal(fd, ch, 8);
974
0
        }
975
0
    }
976
977
0
done:
978
0
    if (truncated) {
979
0
        PUTS(fd, "...");
980
0
    }
981
0
}
982
983
984
#ifdef MS_WINDOWS
985
static void
986
_Py_DumpWideString(int fd, wchar_t *str)
987
{
988
    Py_ssize_t size = wcslen(str);
989
    int truncated;
990
    if (MAX_STRING_LENGTH < size) {
991
        size = MAX_STRING_LENGTH;
992
        truncated = 1;
993
    }
994
    else {
995
        truncated = 0;
996
    }
997
998
    for (Py_ssize_t i=0; i < size; i++) {
999
        Py_UCS4 ch = str[i];
1000
        if (' ' <= ch && ch <= 126) {
1001
            /* printable ASCII character */
1002
            dump_char(fd, (char)ch);
1003
        }
1004
        else if (ch <= 0xff) {
1005
            PUTS(fd, "\\x");
1006
            _Py_DumpHexadecimal(fd, ch, 2);
1007
        }
1008
        else if (Py_UNICODE_IS_HIGH_SURROGATE(ch)
1009
                 && Py_UNICODE_IS_LOW_SURROGATE(str[i+1])) {
1010
            ch = Py_UNICODE_JOIN_SURROGATES(ch, str[i+1]);
1011
            i++;  // Skip the low surrogate character
1012
            PUTS(fd, "\\U");
1013
            _Py_DumpHexadecimal(fd, ch, 8);
1014
        }
1015
        else {
1016
            Py_BUILD_ASSERT(sizeof(wchar_t) == 2);
1017
            PUTS(fd, "\\u");
1018
            _Py_DumpHexadecimal(fd, ch, 4);
1019
        }
1020
    }
1021
1022
    if (truncated) {
1023
        PUTS(fd, "...");
1024
    }
1025
}
1026
#endif
1027
1028
1029
/* Write a frame into the file fd: "File "xxx", line xxx in xxx".
1030
1031
   This function is signal safe. */
1032
1033
static void
1034
dump_frame(int fd, _PyInterpreterFrame *frame)
1035
0
{
1036
0
    assert(frame->owner < FRAME_OWNED_BY_INTERPRETER);
1037
1038
0
    PyCodeObject *code =_PyFrame_GetCode(frame);
1039
0
    PUTS(fd, "  File ");
1040
0
    if (code->co_filename != NULL
1041
0
        && PyUnicode_Check(code->co_filename))
1042
0
    {
1043
0
        PUTS(fd, "\"");
1044
0
        _Py_DumpASCII(fd, code->co_filename);
1045
0
        PUTS(fd, "\"");
1046
0
    } else {
1047
0
        PUTS(fd, "???");
1048
0
    }
1049
0
    int lasti = PyUnstable_InterpreterFrame_GetLasti(frame);
1050
0
    int lineno = _PyCode_Addr2LineNoTstate(code, lasti);
1051
0
    PUTS(fd, ", line ");
1052
0
    if (lineno >= 0) {
1053
0
        _Py_DumpDecimal(fd, (size_t)lineno);
1054
0
    }
1055
0
    else {
1056
0
        PUTS(fd, "???");
1057
0
    }
1058
0
    PUTS(fd, " in ");
1059
1060
0
    if (code->co_name != NULL
1061
0
       && PyUnicode_Check(code->co_name)) {
1062
0
        _Py_DumpASCII(fd, code->co_name);
1063
0
    }
1064
0
    else {
1065
0
        PUTS(fd, "???");
1066
0
    }
1067
1068
0
    PUTS(fd, "\n");
1069
0
}
1070
1071
static int
1072
tstate_is_freed(PyThreadState *tstate)
1073
0
{
1074
0
    if (_PyMem_IsPtrFreed(tstate)) {
1075
0
        return 1;
1076
0
    }
1077
0
    if (_PyMem_IsPtrFreed(tstate->interp)) {
1078
0
        return 1;
1079
0
    }
1080
0
    return 0;
1081
0
}
1082
1083
1084
static int
1085
interp_is_freed(PyInterpreterState *interp)
1086
0
{
1087
0
    return _PyMem_IsPtrFreed(interp);
1088
0
}
1089
1090
1091
static void
1092
dump_traceback(int fd, PyThreadState *tstate, int write_header)
1093
0
{
1094
0
    if (write_header) {
1095
0
        PUTS(fd, "Stack (most recent call first):\n");
1096
0
    }
1097
1098
0
    if (tstate_is_freed(tstate)) {
1099
0
        PUTS(fd, "  <tstate is freed>\n");
1100
0
        return;
1101
0
    }
1102
1103
0
    _PyInterpreterFrame *frame = tstate->current_frame;
1104
0
    if (frame == NULL) {
1105
0
        PUTS(fd, "  <no Python frame>\n");
1106
0
        return;
1107
0
    }
1108
1109
0
    unsigned int depth = 0;
1110
0
    while (1) {
1111
0
        if (frame->owner == FRAME_OWNED_BY_INTERPRETER) {
1112
            /* Trampoline frame */
1113
0
            frame = frame->previous;
1114
0
            if (frame == NULL) {
1115
0
                break;
1116
0
            }
1117
1118
            /* Can't have more than one shim frame in a row */
1119
0
            assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
1120
0
        }
1121
1122
0
        if (MAX_FRAME_DEPTH <= depth) {
1123
0
            if (MAX_FRAME_DEPTH < depth) {
1124
0
                PUTS(fd, "plus ");
1125
0
                _Py_DumpDecimal(fd, depth);
1126
0
                PUTS(fd, " frames\n");
1127
0
            }
1128
0
            break;
1129
0
        }
1130
1131
0
        dump_frame(fd, frame);
1132
0
        frame = frame->previous;
1133
0
        if (frame == NULL) {
1134
0
            break;
1135
0
        }
1136
0
        depth++;
1137
0
    }
1138
0
}
1139
1140
/* Dump the traceback of a Python thread into fd. Use write() to write the
1141
   traceback and retry if write() is interrupted by a signal (failed with
1142
   EINTR), but don't call the Python signal handler.
1143
1144
   The caller is responsible to call PyErr_CheckSignals() to call Python signal
1145
   handlers if signals were received. */
1146
void
1147
_Py_DumpTraceback(int fd, PyThreadState *tstate)
1148
0
{
1149
0
    dump_traceback(fd, tstate, 1);
1150
0
}
1151
1152
#if defined(HAVE_PTHREAD_GETNAME_NP) || defined(HAVE_PTHREAD_GET_NAME_NP)
1153
# if defined(__OpenBSD__)
1154
    /* pthread_*_np functions, especially pthread_{get,set}_name_np().
1155
       pthread_np.h exists on both OpenBSD and FreeBSD but the latter declares
1156
       pthread_getname_np() and pthread_setname_np() in pthread.h as long as
1157
       __BSD_VISIBLE remains set.
1158
     */
1159
#   include <pthread_np.h>
1160
# endif
1161
#endif
1162
1163
1164
// Write the thread name
1165
static void
1166
write_thread_name(int fd, PyThreadState *tstate)
1167
0
{
1168
0
#ifndef MS_WINDOWS
1169
0
#if defined(HAVE_PTHREAD_GETNAME_NP) || defined(HAVE_PTHREAD_GET_NAME_NP)
1170
0
    char name[100];
1171
0
    pthread_t thread = (pthread_t)tstate->thread_id;
1172
0
#ifdef HAVE_PTHREAD_GETNAME_NP
1173
0
    int rc = pthread_getname_np(thread, name, Py_ARRAY_LENGTH(name));
1174
#else /* defined(HAVE_PTHREAD_GET_NAME_NP) */
1175
    int rc = 0; /* pthread_get_name_np() returns void */
1176
    pthread_get_name_np(thread, name, Py_ARRAY_LENGTH(name));
1177
#endif
1178
0
    if (!rc) {
1179
0
        size_t len = strlen(name);
1180
0
        if (len) {
1181
0
            PUTS(fd, " [");
1182
0
            (void)_Py_write_noraise(fd, name, len);
1183
0
            PUTS(fd, "]");
1184
0
        }
1185
0
    }
1186
0
#endif
1187
#else
1188
    // Windows implementation
1189
    if (pGetThreadDescription == NULL) {
1190
        return;
1191
    }
1192
1193
    HANDLE thread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, tstate->thread_id);
1194
    if (thread == NULL) {
1195
        return;
1196
    }
1197
1198
    wchar_t *name;
1199
    HRESULT hr = pGetThreadDescription(thread, &name);
1200
    if (!FAILED(hr)) {
1201
        if (name[0] != 0) {
1202
            PUTS(fd, " [");
1203
            _Py_DumpWideString(fd, name);
1204
            PUTS(fd, "]");
1205
        }
1206
        LocalFree(name);
1207
    }
1208
    CloseHandle(thread);
1209
#endif
1210
0
}
1211
1212
1213
/* Write the thread identifier into the file 'fd': "Current thread 0xHHHH:\" if
1214
   is_current is true, "Thread 0xHHHH:\n" otherwise.
1215
1216
   This function is signal safe (except on Windows). */
1217
1218
static void
1219
write_thread_id(int fd, PyThreadState *tstate, int is_current)
1220
0
{
1221
0
    if (is_current)
1222
0
        PUTS(fd, "Current thread 0x");
1223
0
    else
1224
0
        PUTS(fd, "Thread 0x");
1225
0
    _Py_DumpHexadecimal(fd,
1226
0
                        tstate->thread_id,
1227
0
                        sizeof(unsigned long) * 2);
1228
1229
0
    write_thread_name(fd, tstate);
1230
1231
0
    PUTS(fd, " (most recent call first):\n");
1232
0
}
1233
1234
/* Dump the traceback of all Python threads into fd. Use write() to write the
1235
   traceback and retry if write() is interrupted by a signal (failed with
1236
   EINTR), but don't call the Python signal handler.
1237
1238
   The caller is responsible to call PyErr_CheckSignals() to call Python signal
1239
   handlers if signals were received. */
1240
const char*
1241
_Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
1242
                         PyThreadState *current_tstate)
1243
0
{
1244
0
    if (current_tstate == NULL) {
1245
        /* _Py_DumpTracebackThreads() is called from signal handlers by
1246
           faulthandler.
1247
1248
           SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals
1249
           and are thus delivered to the thread that caused the fault. Get the
1250
           Python thread state of the current thread.
1251
1252
           PyThreadState_Get() doesn't give the state of the thread that caused
1253
           the fault if the thread released the GIL, and so
1254
           _PyThreadState_GET() cannot be used. Read the thread specific
1255
           storage (TSS) instead: call PyGILState_GetThisThreadState(). */
1256
0
        current_tstate = PyGILState_GetThisThreadState();
1257
0
    }
1258
1259
0
    if (current_tstate != NULL && tstate_is_freed(current_tstate)) {
1260
0
        return "tstate is freed";
1261
0
    }
1262
1263
0
    if (interp == NULL) {
1264
0
        if (current_tstate == NULL) {
1265
0
            interp = _PyGILState_GetInterpreterStateUnsafe();
1266
0
            if (interp == NULL) {
1267
                /* We need the interpreter state to get Python threads */
1268
0
                return "unable to get the interpreter state";
1269
0
            }
1270
0
        }
1271
0
        else {
1272
0
            interp = current_tstate->interp;
1273
0
        }
1274
0
    }
1275
0
    assert(interp != NULL);
1276
1277
0
    if (interp_is_freed(interp)) {
1278
0
        return "interp is freed";
1279
0
    }
1280
1281
    /* Get the current interpreter from the current thread */
1282
0
    PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
1283
0
    if (tstate == NULL)
1284
0
        return "unable to get the thread head state";
1285
1286
    /* Dump the traceback of each thread */
1287
0
    tstate = PyInterpreterState_ThreadHead(interp);
1288
0
    unsigned int nthreads = 0;
1289
0
    _Py_BEGIN_SUPPRESS_IPH
1290
0
    do
1291
0
    {
1292
0
        if (nthreads != 0)
1293
0
            PUTS(fd, "\n");
1294
0
        if (nthreads >= MAX_NTHREADS) {
1295
0
            PUTS(fd, "...\n");
1296
0
            break;
1297
0
        }
1298
0
        write_thread_id(fd, tstate, tstate == current_tstate);
1299
0
        if (tstate == current_tstate && tstate->interp->gc.collecting) {
1300
0
            PUTS(fd, "  Garbage-collecting\n");
1301
0
        }
1302
0
        dump_traceback(fd, tstate, 0);
1303
0
        tstate = PyThreadState_Next(tstate);
1304
0
        nthreads++;
1305
0
    } while (tstate != NULL);
1306
0
    _Py_END_SUPPRESS_IPH
1307
1308
0
    return NULL;
1309
0
}
1310
1311
#ifdef CAN_C_BACKTRACE
1312
/* Based on glibc's implementation of backtrace_symbols(), but only uses stack memory. */
1313
void
1314
_Py_backtrace_symbols_fd(int fd, void *const *array, Py_ssize_t size)
1315
0
{
1316
0
    VLA(Dl_info, info, size);
1317
0
    VLA(int, status, size);
1318
    /* Fill in the information we can get from dladdr() */
1319
0
    for (Py_ssize_t i = 0; i < size; ++i) {
1320
#ifdef __APPLE__
1321
        status[i] = dladdr(array[i], &info[i]);
1322
#else
1323
0
        struct link_map *map;
1324
0
        status[i] = dladdr1(array[i], &info[i], (void **)&map, RTLD_DL_LINKMAP);
1325
0
        if (status[i] != 0
1326
0
            && info[i].dli_fname != NULL
1327
0
            && info[i].dli_fname[0] != '\0') {
1328
            /* The load bias is more useful to the user than the load
1329
               address. The use of these addresses is to calculate an
1330
               address in the ELF file, so its prelinked bias is not
1331
               something we want to subtract out */
1332
0
            info[i].dli_fbase = (void *) map->l_addr;
1333
0
        }
1334
0
#endif
1335
0
    }
1336
0
    for (Py_ssize_t i = 0; i < size; ++i) {
1337
0
        if (status[i] == 0
1338
0
            || info[i].dli_fname == NULL
1339
0
            || info[i].dli_fname[0] == '\0'
1340
0
        ) {
1341
0
            PUTS(fd, "  Binary file '<unknown>' [");
1342
0
            dump_pointer(fd, array[i]);
1343
0
            PUTS(fd, "]\n");
1344
0
            continue;
1345
0
        }
1346
1347
0
        if (info[i].dli_sname == NULL) {
1348
            /* We found no symbol name to use, so describe it as
1349
               relative to the file. */
1350
0
            info[i].dli_saddr = info[i].dli_fbase;
1351
0
        }
1352
1353
0
        if (info[i].dli_sname == NULL && info[i].dli_saddr == 0) {
1354
0
            PUTS(fd, "  Binary file \"");
1355
0
            PUTS(fd, info[i].dli_fname);
1356
0
            PUTS(fd, "\" [");
1357
0
            dump_pointer(fd, array[i]);
1358
0
            PUTS(fd, "]\n");
1359
0
        }
1360
0
        else {
1361
0
            char sign;
1362
0
            ptrdiff_t offset;
1363
0
            if (array[i] >= (void *) info[i].dli_saddr) {
1364
0
                sign = '+';
1365
0
                offset = array[i] - info[i].dli_saddr;
1366
0
            }
1367
0
            else {
1368
0
                sign = '-';
1369
0
                offset = info[i].dli_saddr - array[i];
1370
0
            }
1371
0
            const char *symbol_name = info[i].dli_sname != NULL ? info[i].dli_sname : "";
1372
0
            PUTS(fd, "  Binary file \"");
1373
0
            PUTS(fd, info[i].dli_fname);
1374
0
            PUTS(fd, "\", at ");
1375
0
            PUTS(fd, symbol_name);
1376
0
            dump_char(fd, sign);
1377
0
            PUTS(fd, "0x");
1378
0
            dump_hexadecimal(fd, offset, sizeof(offset), 1);
1379
0
            PUTS(fd, " [");
1380
0
            dump_pointer(fd, array[i]);
1381
0
            PUTS(fd, "]\n");
1382
0
        }
1383
0
    }
1384
0
}
1385
1386
void
1387
_Py_DumpStack(int fd)
1388
0
{
1389
0
#define BACKTRACE_SIZE 32
1390
0
    PUTS(fd, "Current thread's C stack trace (most recent call first):\n");
1391
0
    VLA(void *, callstack, BACKTRACE_SIZE);
1392
0
    int frames = backtrace(callstack, BACKTRACE_SIZE);
1393
0
    if (frames == 0) {
1394
        // Some systems won't return anything for the stack trace
1395
0
        PUTS(fd, "  <system returned no stack trace>\n");
1396
0
        return;
1397
0
    }
1398
1399
0
    _Py_backtrace_symbols_fd(fd, callstack, frames);
1400
0
    if (frames == BACKTRACE_SIZE) {
1401
0
        PUTS(fd, "  <truncated rest of calls>\n");
1402
0
    }
1403
1404
0
#undef BACKTRACE_SIZE
1405
0
}
1406
#else
1407
void
1408
_Py_DumpStack(int fd)
1409
{
1410
    PUTS(fd, "Current thread's C stack trace (most recent call first):\n");
1411
    PUTS(fd, "  <cannot get C stack on this system>\n");
1412
}
1413
#endif
1414
1415
void
1416
_Py_InitDumpStack(void)
1417
0
{
1418
0
#ifdef CAN_C_BACKTRACE
1419
    // gh-137185: Call backtrace() once to force libgcc to be loaded early.
1420
0
    void *callstack[1];
1421
0
    (void)backtrace(callstack, 1);
1422
0
#endif
1423
0
}
1424
1425
1426
void
1427
_Py_DumpTraceback_Init(void)
1428
16
{
1429
#ifdef MS_WINDOWS
1430
    if (pGetThreadDescription != NULL) {
1431
        return;
1432
    }
1433
1434
    HMODULE kernelbase = GetModuleHandleW(L"kernelbase.dll");
1435
    if (kernelbase != NULL) {
1436
        pGetThreadDescription = (PF_GET_THREAD_DESCRIPTION)GetProcAddress(
1437
                                    kernelbase, "GetThreadDescription");
1438
    }
1439
#endif
1440
16
}