gh-149202: Fix frame pointer unwinding on s390x and ARM (GH-149362) · python/cpython@4ed4014

GitHub

@@ -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