Coverage Report

Created: 2026-10-17 06:15

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