@@ -63,6 +63,40 @@
6363staticconstuintptr_tmin_frame_pointer_addr=0x1000;
6464#defineMAX_UNWIND_FRAMES 200
656566+#ifdef__s390x__
67+// Linux's s390 "Stack Frame Layout" table documents that z/Architecture
68+// backchain frames start with the backchain at offset 0 and store "saved r14
69+// of caller function" at offset 112. The same document's register table
70+// identifies r14 as the return-address register, so this backchain unwinder
71+// reads the return address from fp + 112.
72+// https://www.kernel.org/doc/html/v5.3/s390/debugging390.html#stack-frame-layout
73+//
74+// This is only for Linux s390x backchain frames. The s390x ELF ABI does not
75+// generally mandate where RA and FP are saved, or whether they are saved at all.
76+// https://sourceware.org/binutils/docs/sframe-spec.html#s390x
77+# defineS390X_FRAME_RETURN_ADDRESS_OFFSET 112
78+#endif
79+80+// The generic manual unwinder treats the frame pointer as a two-word record:
81+// fp[0] is the previous frame pointer and fp[1] is the return address. That is
82+// not true for every architecture, even with frame pointers enabled, so these
83+// offsets describe the actual slots used by each supported frame layout.
84+#if defined(__arm__) && !defined(__thumb__) && !defined(__clang__)
85+// GCC ARM mode keeps the caller's fp one word below fp and the saved LR at
86+// fp[0], so the return address is not in the generic fp[1] slot.
87+# defineFRAME_POINTER_NEXT_OFFSET (-1)
88+# defineFRAME_POINTER_RETURN_OFFSET 0
89+#elif defined(__s390x__)
90+// s390x backchain frames keep the previous frame pointer at fp[0], but save the
91+// return-address register in the ABI register save area rather than fp[1].
92+# defineFRAME_POINTER_NEXT_OFFSET 0
93+# defineFRAME_POINTER_RETURN_OFFSET \
94+ (S390X_FRAME_RETURN_ADDRESS_OFFSET / (Py_ssize_t)sizeof(uintptr_t))
95+#else
96+# defineFRAME_POINTER_NEXT_OFFSET 0
97+# defineFRAME_POINTER_RETURN_OFFSET 1
98+#endif
99+6610067101staticPyObject*
68102_get_current_module(void)
@@ -329,15 +363,96 @@ get_jit_backend(PyObject *self, PyObject *Py_UNUSED(args))
329363#endif
330364}
331365366+staticint
367+stack_address_is_valid(uintptr_taddr, uintptr_tstack_min, uintptr_tstack_max)
368+{
369+if (addr<min_frame_pointer_addr) {
370+return0;
371+ }
372+if (stack_min!=0&& (addr<stack_min||addr >= stack_max)) {
373+return0;
374+ }
375+return1;
376+}
377+378+staticint
379+frame_pointer_slot_is_valid(uintptr_t*frame_pointer, Py_ssize_toffset,
380+uintptr_tstack_min, uintptr_tstack_max)
381+{
382+uintptr_tfp_addr= (uintptr_t)frame_pointer;
383+uintptr_tslot_addr;
384+uintptr_tdelta= (uintptr_t)Py_ABS(offset) *sizeof(uintptr_t);
385+if (offset<0) {
386+if (fp_addr<delta) {
387+return0;
388+ }
389+slot_addr=fp_addr-delta;
390+ }
391+else {
392+if (fp_addr>UINTPTR_MAX-delta) {
393+return0;
394+ }
395+slot_addr=fp_addr+delta;
396+ }
397+if (!stack_address_is_valid(slot_addr, stack_min, stack_max)) {
398+return0;
399+ }
400+if (stack_max!=0) {
401+if (slot_addr>UINTPTR_MAX-sizeof(uintptr_t)) {
402+return0;
403+ }
404+if (slot_addr+sizeof(uintptr_t) >stack_max) {
405+return0;
406+ }
407+ }
408+return1;
409+}
410+411+staticint
412+next_frame_pointer_is_valid(uintptr_t*frame_pointer, uintptr_t*next_fp,
413+uintptr_tstack_min, uintptr_tstack_max)
414+{
415+uintptr_tfp_addr= (uintptr_t)frame_pointer;
416+uintptr_tnext_addr= (uintptr_t)next_fp;
417+if (!stack_address_is_valid(next_addr, stack_min, stack_max)) {
418+return0;
419+ }
420+if ((next_addr % sizeof(uintptr_t)) !=0) {
421+return0;
422+ }
423+#if_Py_STACK_GROWS_DOWN
424+returnnext_addr>fp_addr;
425+#else
426+returnnext_addr<fp_addr;
427+#endif
428+}
429+332430staticPyObject*
333431manual_unwind_from_fp(uintptr_t*frame_pointer)
334432{
335-intstack_grows_down=_Py_STACK_GROWS_DOWN;
433+uintptr_tstack_min=0;
434+uintptr_tstack_max=0;
435+436+#ifdef__s390x__
437+Py_BUILD_ASSERT(S390X_FRAME_RETURN_ADDRESS_OFFSET % sizeof(uintptr_t) ==0);
438+#endif
336439337440if (frame_pointer==NULL) {
338441returnPyList_New(0);
339442 }
340443444+PyThreadState*tstate=_PyThreadState_GET();
445+if (tstate!=NULL) {
446+_PyThreadStateImpl*tstate_impl= (_PyThreadStateImpl*)tstate;
447+#if_Py_STACK_GROWS_DOWN
448+stack_min=tstate_impl->c_stack_hard_limit;
449+stack_max=tstate_impl->c_stack_top;
450+#else
451+stack_min=tstate_impl->c_stack_top;
452+stack_max=tstate_impl->c_stack_hard_limit;
453+#endif
454+ }
455+341456PyObject*result=PyList_New(0);
342457if (result==NULL) {
343458returnNULL;
@@ -357,7 +472,21 @@ manual_unwind_from_fp(uintptr_t *frame_pointer)
357472MAX_UNWIND_FRAMES);
358473returnNULL;
359474 }
360-uintptr_treturn_addr=frame_pointer[1];
475+if (!stack_address_is_valid(fp_addr, stack_min, stack_max)) {
476+break;
477+ }
478+if (!frame_pointer_slot_is_valid(frame_pointer,
479+FRAME_POINTER_NEXT_OFFSET,
480+stack_min, stack_max)) {
481+break;
482+ }
483+if (!frame_pointer_slot_is_valid(frame_pointer,
484+FRAME_POINTER_RETURN_OFFSET,
485+stack_min, stack_max)) {
486+break;
487+ }
488+uintptr_t*next_fp= (uintptr_t*)frame_pointer[FRAME_POINTER_NEXT_OFFSET];
489+uintptr_treturn_addr=frame_pointer[FRAME_POINTER_RETURN_OFFSET];
361490362491PyObject*addr_obj=PyLong_FromUnsignedLongLong(return_addr);
363492if (addr_obj==NULL) {
@@ -372,22 +501,10 @@ manual_unwind_from_fp(uintptr_t *frame_pointer)
372501Py_DECREF(addr_obj);
373502depth++;
374503375-uintptr_t*next_fp= (uintptr_t*)frame_pointer[0];
376-// Stop if the frame pointer is extremely low.
377-if ((uintptr_t)next_fp<min_frame_pointer_addr) {
504+if (!next_frame_pointer_is_valid(frame_pointer, next_fp,
505+stack_min, stack_max)) {
378506break;
379507 }
380-uintptr_tnext_addr= (uintptr_t)next_fp;
381-if (stack_grows_down) {
382-if (next_addr <= fp_addr) {
383-break;
384- }
385- }
386-else {
387-if (next_addr >= fp_addr) {
388-break;
389- }
390- }
391508frame_pointer=next_fp;
392509 }
393510@@ -3170,6 +3287,12 @@ module_exec(PyObject *module)
31703287return1;
31713288 }
317232893290+#ifdef_Py_WITH_FRAME_POINTERS
3291+if (PyModule_AddIntMacro(module, _Py_WITH_FRAME_POINTERS) <0) {
3292+return1;
3293+ }
3294+#endif
3295+31733296return0;
31743297}
31753298