Coverage Report

Created: 2025-11-24 06:11

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
56.2M
#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
56.1M
{
83
56.1M
    PyTracebackObject *tb;
84
56.1M
    if ((next != NULL && !PyTraceBack_Check(next)) ||
85
56.1M
                    frame == NULL || !PyFrame_Check(frame)) {
86
0
        PyErr_BadInternalCall();
87
0
        return NULL;
88
0
    }
89
56.1M
    tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type);
90
56.1M
    if (tb != NULL) {
91
56.1M
        tb->tb_next = (PyTracebackObject*)Py_XNewRef(next);
92
56.1M
        tb->tb_frame = (PyFrameObject*)Py_XNewRef(frame);
93
56.1M
        tb->tb_lasti = lasti;
94
56.1M
        tb->tb_lineno = lineno;
95
56.1M
        PyObject_GC_Track(tb);
96
56.1M
    }
97
56.1M
    return (PyObject *)tb;
98
56.1M
}
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
56.1M
{
243
56.1M
    PyTracebackObject *tb = _PyTracebackObject_CAST(op);
244
56.1M
    PyObject_GC_UnTrack(tb);
245
56.1M
    Py_XDECREF(tb->tb_next);
246
56.1M
    Py_XDECREF(tb->tb_frame);
247
56.1M
    PyObject_GC_Del(tb);
248
56.1M
}
249
250
static int
251
tb_traverse(PyObject *op, visitproc visit, void *arg)
252
59.7k
{
253
59.7k
    PyTracebackObject *tb = _PyTracebackObject_CAST(op);
254
59.7k
    Py_VISIT(tb->tb_next);
255
59.7k
    Py_VISIT(tb->tb_frame);
256
59.7k
    return 0;
257
59.7k
}
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
56.1M
{
313
56.1M
    assert(tb_next == NULL || PyTraceBack_Check(tb_next));
314
56.1M
    assert(frame != NULL);
315
56.1M
    int addr = _PyInterpreterFrame_LASTI(frame->f_frame) * sizeof(_Py_CODEUNIT);
316
56.1M
    return tb_create_raw((PyTracebackObject *)tb_next, frame, addr, -1);
317
56.1M
}
318
319
320
int
321
PyTraceBack_Here(PyFrameObject *frame)
322
56.1M
{
323
56.1M
    PyObject *exc = PyErr_GetRaisedException();
324
56.1M
    assert(PyExceptionInstance_Check(exc));
325
56.1M
    PyObject *tb = PyException_GetTraceback(exc);
326
56.1M
    PyObject *newtb = _PyTraceBack_FromFrame(tb, frame);
327
56.1M
    Py_XDECREF(tb);
328
56.1M
    if (newtb == NULL) {
329
0
        _PyErr_ChainExceptions1(exc);
330
0
        return -1;
331
0
    }
332
56.1M
    PyException_SetTraceback(exc, newtb);
333
56.1M
    Py_XDECREF(newtb);
334
56.1M
    PyErr_SetRaisedException(exc);
335
56.1M
    return 0;
336
56.1M
}
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
20
{
341
20
    PyObject *globals;
342
20
    PyCodeObject *code;
343
20
    PyFrameObject *frame;
344
20
    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
20
    PyObject *exc = _PyErr_GetRaisedException(tstate);
350
351
20
    globals = PyDict_New();
352
20
    if (!globals)
353
0
        goto error;
354
20
    code = PyCode_NewEmpty(filename, funcname, lineno);
355
20
    if (!code) {
356
0
        Py_DECREF(globals);
357
0
        goto error;
358
0
    }
359
20
    frame = PyFrame_New(tstate, code, globals, NULL);
360
20
    Py_DECREF(globals);
361
20
    Py_DECREF(code);
362
20
    if (!frame)
363
0
        goto error;
364
20
    frame->f_lineno = lineno;
365
366
20
    _PyErr_SetRaisedException(tstate, exc);
367
20
    PyTraceBack_Here(frame);
368
20
    Py_DECREF(frame);
369
20
    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
   Return 0 on success. Return -1 if the frame is invalid. */
1034
1035
static int
1036
dump_frame(int fd, _PyInterpreterFrame *frame)
1037
0
{
1038
0
    if (frame->owner == FRAME_OWNED_BY_INTERPRETER) {
1039
        /* Ignore trampoline frame */
1040
0
        return 0;
1041
0
    }
1042
1043
0
    PyCodeObject *code = _PyFrame_SafeGetCode(frame);
1044
0
    if (code == NULL) {
1045
0
        return -1;
1046
0
    }
1047
1048
0
    int res = 0;
1049
0
    PUTS(fd, "  File ");
1050
0
    if (code->co_filename != NULL
1051
0
        && PyUnicode_Check(code->co_filename))
1052
0
    {
1053
0
        PUTS(fd, "\"");
1054
0
        _Py_DumpASCII(fd, code->co_filename);
1055
0
        PUTS(fd, "\"");
1056
0
    }
1057
0
    else {
1058
0
        PUTS(fd, "???");
1059
0
        res = -1;
1060
0
    }
1061
1062
0
    PUTS(fd, ", line ");
1063
0
    int lasti = _PyFrame_SafeGetLasti(frame);
1064
0
    int lineno = -1;
1065
0
    if (lasti >= 0) {
1066
0
        lineno = _PyCode_SafeAddr2Line(code, lasti);
1067
0
    }
1068
0
    if (lineno >= 0) {
1069
0
        _Py_DumpDecimal(fd, (size_t)lineno);
1070
0
    }
1071
0
    else {
1072
0
        PUTS(fd, "???");
1073
0
        res = -1;
1074
0
    }
1075
1076
0
    PUTS(fd, " in ");
1077
0
    if (code->co_name != NULL && PyUnicode_Check(code->co_name)) {
1078
0
        _Py_DumpASCII(fd, code->co_name);
1079
0
    }
1080
0
    else {
1081
0
        PUTS(fd, "???");
1082
0
        res = -1;
1083
0
    }
1084
0
    PUTS(fd, "\n");
1085
0
    return res;
1086
0
}
1087
1088
static int
1089
tstate_is_freed(PyThreadState *tstate)
1090
0
{
1091
0
    if (_PyMem_IsPtrFreed(tstate)) {
1092
0
        return 1;
1093
0
    }
1094
0
    if (_PyMem_IsPtrFreed(tstate->interp)) {
1095
0
        return 1;
1096
0
    }
1097
0
    return 0;
1098
0
}
1099
1100
1101
static int
1102
interp_is_freed(PyInterpreterState *interp)
1103
0
{
1104
0
    return _PyMem_IsPtrFreed(interp);
1105
0
}
1106
1107
1108
static void
1109
dump_traceback(int fd, PyThreadState *tstate, int write_header)
1110
0
{
1111
0
    if (write_header) {
1112
0
        PUTS(fd, "Stack (most recent call first):\n");
1113
0
    }
1114
1115
0
    if (tstate_is_freed(tstate)) {
1116
0
        PUTS(fd, "  <tstate is freed>\n");
1117
0
        return;
1118
0
    }
1119
1120
0
    _PyInterpreterFrame *frame = tstate->current_frame;
1121
0
    if (frame == NULL) {
1122
0
        PUTS(fd, "  <no Python frame>\n");
1123
0
        return;
1124
0
    }
1125
1126
0
    unsigned int depth = 0;
1127
0
    while (1) {
1128
0
        if (MAX_FRAME_DEPTH <= depth) {
1129
0
            if (MAX_FRAME_DEPTH < depth) {
1130
0
                PUTS(fd, "plus ");
1131
0
                _Py_DumpDecimal(fd, depth);
1132
0
                PUTS(fd, " frames\n");
1133
0
            }
1134
0
            break;
1135
0
        }
1136
1137
0
        if (_PyMem_IsPtrFreed(frame)) {
1138
0
            PUTS(fd, "  <freed frame>\n");
1139
0
            break;
1140
0
        }
1141
0
        if (dump_frame(fd, frame) < 0) {
1142
0
            PUTS(fd, "  <invalid frame>\n");
1143
0
            break;
1144
0
        }
1145
1146
0
        frame = frame->previous;
1147
0
        if (frame == NULL) {
1148
0
            break;
1149
0
        }
1150
0
        depth++;
1151
0
    }
1152
0
}
1153
1154
/* Dump the traceback of a Python thread into fd. Use write() to write the
1155
   traceback and retry if write() is interrupted by a signal (failed with
1156
   EINTR), but don't call the Python signal handler.
1157
1158
   The caller is responsible to call PyErr_CheckSignals() to call Python signal
1159
   handlers if signals were received. */
1160
void
1161
_Py_DumpTraceback(int fd, PyThreadState *tstate)
1162
0
{
1163
0
    dump_traceback(fd, tstate, 1);
1164
0
}
1165
1166
#if defined(HAVE_PTHREAD_GETNAME_NP) || defined(HAVE_PTHREAD_GET_NAME_NP)
1167
# if defined(__OpenBSD__)
1168
    /* pthread_*_np functions, especially pthread_{get,set}_name_np().
1169
       pthread_np.h exists on both OpenBSD and FreeBSD but the latter declares
1170
       pthread_getname_np() and pthread_setname_np() in pthread.h as long as
1171
       __BSD_VISIBLE remains set.
1172
     */
1173
#   include <pthread_np.h>
1174
# endif
1175
#endif
1176
1177
1178
// Write the thread name
1179
static void
1180
write_thread_name(int fd, PyThreadState *tstate)
1181
0
{
1182
0
#ifndef MS_WINDOWS
1183
0
#if defined(HAVE_PTHREAD_GETNAME_NP) || defined(HAVE_PTHREAD_GET_NAME_NP)
1184
0
    char name[100];
1185
0
    pthread_t thread = (pthread_t)tstate->thread_id;
1186
0
#ifdef HAVE_PTHREAD_GETNAME_NP
1187
0
    int rc = pthread_getname_np(thread, name, Py_ARRAY_LENGTH(name));
1188
#else /* defined(HAVE_PTHREAD_GET_NAME_NP) */
1189
    int rc = 0; /* pthread_get_name_np() returns void */
1190
    pthread_get_name_np(thread, name, Py_ARRAY_LENGTH(name));
1191
#endif
1192
0
    if (!rc) {
1193
0
        size_t len = strlen(name);
1194
0
        if (len) {
1195
0
            PUTS(fd, " [");
1196
0
            (void)_Py_write_noraise(fd, name, len);
1197
0
            PUTS(fd, "]");
1198
0
        }
1199
0
    }
1200
0
#endif
1201
#else
1202
    // Windows implementation
1203
    if (pGetThreadDescription == NULL) {
1204
        return;
1205
    }
1206
1207
    HANDLE thread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, tstate->thread_id);
1208
    if (thread == NULL) {
1209
        return;
1210
    }
1211
1212
    wchar_t *name;
1213
    HRESULT hr = pGetThreadDescription(thread, &name);
1214
    if (!FAILED(hr)) {
1215
        if (name[0] != 0) {
1216
            PUTS(fd, " [");
1217
            _Py_DumpWideString(fd, name);
1218
            PUTS(fd, "]");
1219
        }
1220
        LocalFree(name);
1221
    }
1222
    CloseHandle(thread);
1223
#endif
1224
0
}
1225
1226
1227
/* Write the thread identifier into the file 'fd': "Current thread 0xHHHH:\" if
1228
   is_current is true, "Thread 0xHHHH:\n" otherwise.
1229
1230
   This function is signal safe (except on Windows). */
1231
1232
static void
1233
write_thread_id(int fd, PyThreadState *tstate, int is_current)
1234
0
{
1235
0
    if (is_current)
1236
0
        PUTS(fd, "Current thread 0x");
1237
0
    else
1238
0
        PUTS(fd, "Thread 0x");
1239
0
    _Py_DumpHexadecimal(fd,
1240
0
                        tstate->thread_id,
1241
0
                        sizeof(unsigned long) * 2);
1242
1243
0
    write_thread_name(fd, tstate);
1244
1245
0
    PUTS(fd, " (most recent call first):\n");
1246
0
}
1247
1248
/* Dump the traceback of all Python threads into fd. Use write() to write the
1249
   traceback and retry if write() is interrupted by a signal (failed with
1250
   EINTR), but don't call the Python signal handler.
1251
1252
   The caller is responsible to call PyErr_CheckSignals() to call Python signal
1253
   handlers if signals were received. */
1254
const char*
1255
_Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
1256
                         PyThreadState *current_tstate)
1257
0
{
1258
0
    if (current_tstate == NULL) {
1259
        /* _Py_DumpTracebackThreads() is called from signal handlers by
1260
           faulthandler.
1261
1262
           SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals
1263
           and are thus delivered to the thread that caused the fault. Get the
1264
           Python thread state of the current thread.
1265
1266
           PyThreadState_Get() doesn't give the state of the thread that caused
1267
           the fault if the thread released the GIL, and so
1268
           _PyThreadState_GET() cannot be used. Read the thread specific
1269
           storage (TSS) instead: call PyGILState_GetThisThreadState(). */
1270
0
        current_tstate = PyGILState_GetThisThreadState();
1271
0
    }
1272
1273
0
    if (current_tstate != NULL && tstate_is_freed(current_tstate)) {
1274
0
        return "tstate is freed";
1275
0
    }
1276
1277
0
    if (interp == NULL) {
1278
0
        if (current_tstate == NULL) {
1279
0
            interp = _PyGILState_GetInterpreterStateUnsafe();
1280
0
            if (interp == NULL) {
1281
                /* We need the interpreter state to get Python threads */
1282
0
                return "unable to get the interpreter state";
1283
0
            }
1284
0
        }
1285
0
        else {
1286
0
            interp = current_tstate->interp;
1287
0
        }
1288
0
    }
1289
0
    assert(interp != NULL);
1290
1291
0
    if (interp_is_freed(interp)) {
1292
0
        return "interp is freed";
1293
0
    }
1294
1295
    /* Get the current interpreter from the current thread */
1296
0
    PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
1297
0
    if (tstate == NULL)
1298
0
        return "unable to get the thread head state";
1299
1300
    /* Dump the traceback of each thread */
1301
0
    tstate = PyInterpreterState_ThreadHead(interp);
1302
0
    unsigned int nthreads = 0;
1303
0
    _Py_BEGIN_SUPPRESS_IPH
1304
0
    do
1305
0
    {
1306
0
        if (nthreads != 0)
1307
0
            PUTS(fd, "\n");
1308
0
        if (nthreads >= MAX_NTHREADS) {
1309
0
            PUTS(fd, "...\n");
1310
0
            break;
1311
0
        }
1312
0
        write_thread_id(fd, tstate, tstate == current_tstate);
1313
0
        if (tstate == current_tstate && tstate->interp->gc.collecting) {
1314
0
            PUTS(fd, "  Garbage-collecting\n");
1315
0
        }
1316
0
        dump_traceback(fd, tstate, 0);
1317
0
        tstate = PyThreadState_Next(tstate);
1318
0
        nthreads++;
1319
0
    } while (tstate != NULL);
1320
0
    _Py_END_SUPPRESS_IPH
1321
1322
0
    return NULL;
1323
0
}
1324
1325
#ifdef CAN_C_BACKTRACE
1326
/* Based on glibc's implementation of backtrace_symbols(), but only uses stack memory. */
1327
void
1328
_Py_backtrace_symbols_fd(int fd, void *const *array, Py_ssize_t size)
1329
0
{
1330
0
    VLA(Dl_info, info, size);
1331
0
    VLA(int, status, size);
1332
    /* Fill in the information we can get from dladdr() */
1333
0
    for (Py_ssize_t i = 0; i < size; ++i) {
1334
#ifdef __APPLE__
1335
        status[i] = dladdr(array[i], &info[i]);
1336
#else
1337
0
        struct link_map *map;
1338
0
        status[i] = dladdr1(array[i], &info[i], (void **)&map, RTLD_DL_LINKMAP);
1339
0
        if (status[i] != 0
1340
0
            && info[i].dli_fname != NULL
1341
0
            && info[i].dli_fname[0] != '\0') {
1342
            /* The load bias is more useful to the user than the load
1343
               address. The use of these addresses is to calculate an
1344
               address in the ELF file, so its prelinked bias is not
1345
               something we want to subtract out */
1346
0
            info[i].dli_fbase = (void *) map->l_addr;
1347
0
        }
1348
0
#endif
1349
0
    }
1350
0
    for (Py_ssize_t i = 0; i < size; ++i) {
1351
0
        if (status[i] == 0
1352
0
            || info[i].dli_fname == NULL
1353
0
            || info[i].dli_fname[0] == '\0'
1354
0
        ) {
1355
0
            PUTS(fd, "  Binary file '<unknown>' [");
1356
0
            dump_pointer(fd, array[i]);
1357
0
            PUTS(fd, "]\n");
1358
0
            continue;
1359
0
        }
1360
1361
0
        if (info[i].dli_sname == NULL) {
1362
            /* We found no symbol name to use, so describe it as
1363
               relative to the file. */
1364
0
            info[i].dli_saddr = info[i].dli_fbase;
1365
0
        }
1366
1367
0
        if (info[i].dli_sname == NULL && info[i].dli_saddr == 0) {
1368
0
            PUTS(fd, "  Binary file \"");
1369
0
            PUTS(fd, info[i].dli_fname);
1370
0
            PUTS(fd, "\" [");
1371
0
            dump_pointer(fd, array[i]);
1372
0
            PUTS(fd, "]\n");
1373
0
        }
1374
0
        else {
1375
0
            char sign;
1376
0
            ptrdiff_t offset;
1377
0
            if (array[i] >= (void *) info[i].dli_saddr) {
1378
0
                sign = '+';
1379
0
                offset = array[i] - info[i].dli_saddr;
1380
0
            }
1381
0
            else {
1382
0
                sign = '-';
1383
0
                offset = info[i].dli_saddr - array[i];
1384
0
            }
1385
0
            const char *symbol_name = info[i].dli_sname != NULL ? info[i].dli_sname : "";
1386
0
            PUTS(fd, "  Binary file \"");
1387
0
            PUTS(fd, info[i].dli_fname);
1388
0
            PUTS(fd, "\", at ");
1389
0
            PUTS(fd, symbol_name);
1390
0
            dump_char(fd, sign);
1391
0
            PUTS(fd, "0x");
1392
0
            dump_hexadecimal(fd, offset, sizeof(offset), 1);
1393
0
            PUTS(fd, " [");
1394
0
            dump_pointer(fd, array[i]);
1395
0
            PUTS(fd, "]\n");
1396
0
        }
1397
0
    }
1398
0
}
1399
1400
void
1401
_Py_DumpStack(int fd)
1402
0
{
1403
0
#define BACKTRACE_SIZE 32
1404
0
    PUTS(fd, "Current thread's C stack trace (most recent call first):\n");
1405
0
    VLA(void *, callstack, BACKTRACE_SIZE);
1406
0
    int frames = backtrace(callstack, BACKTRACE_SIZE);
1407
0
    if (frames == 0) {
1408
        // Some systems won't return anything for the stack trace
1409
0
        PUTS(fd, "  <system returned no stack trace>\n");
1410
0
        return;
1411
0
    }
1412
1413
0
    _Py_backtrace_symbols_fd(fd, callstack, frames);
1414
0
    if (frames == BACKTRACE_SIZE) {
1415
0
        PUTS(fd, "  <truncated rest of calls>\n");
1416
0
    }
1417
1418
0
#undef BACKTRACE_SIZE
1419
0
}
1420
#else
1421
void
1422
_Py_DumpStack(int fd)
1423
{
1424
    PUTS(fd, "Current thread's C stack trace (most recent call first):\n");
1425
    PUTS(fd, "  <cannot get C stack on this system>\n");
1426
}
1427
#endif
1428
1429
void
1430
_Py_InitDumpStack(void)
1431
0
{
1432
0
#ifdef CAN_C_BACKTRACE
1433
    // gh-137185: Call backtrace() once to force libgcc to be loaded early.
1434
0
    void *callstack[1];
1435
0
    (void)backtrace(callstack, 1);
1436
0
#endif
1437
0
}
1438
1439
1440
void
1441
_Py_DumpTraceback_Init(void)
1442
28
{
1443
#ifdef MS_WINDOWS
1444
    if (pGetThreadDescription != NULL) {
1445
        return;
1446
    }
1447
1448
    HMODULE kernelbase = GetModuleHandleW(L"kernelbase.dll");
1449
    if (kernelbase != NULL) {
1450
        pGetThreadDescription = (PF_GET_THREAD_DESCRIPTION)GetProcAddress(
1451
                                    kernelbase, "GetThreadDescription");
1452
    }
1453
#endif
1454
28
}