exelib.exp contains a (currently disabled) testcase. # BUG! non-default arch breaks ustack tests. #switch -regexp $::tcl_platform(machine) { # {^(x86_64|ppc64)$} { lappend arches "-m32" } # {^s390x$} { lappend arches "-m31" } #}
The reason is that the runtime/unwind.c unwinder hard codes the assumption that it is using the native (64 bit) register set, it even "sanity checks" that register widths are equal to sizeof(unsigned long)...
The original unwinder was written for in-kernel unwinding, so it hard codes assumptions about register wides. The reg_info struct that defines the knowledge about offsets and widths of registers is defined in runtime/unwind/unwind.h. This file includes an architecture specific header file (only i386.h and x86_64.h) that defines the actual UNW_REGISTER_INFO used. Make sure to check the EXTRA_INFO and PTREGS_INFO defines in unwind.h that extract the information as compile time constants from architecture struct pt_regs in the unwind_frame_info struct. The unwinder works by initializing a architecture specific struct unwind_frame_info with a pt_regs struct which the unwinder then adjusts to show the state for previous frame (you can then feed that back into the unwinder to unwind further). The runtime/unwinder.c has some "sanity checks" like: unsigned long value = 0; #ifdef CONFIG_64BIT BUILD_BUG_ON(sizeof(u64) != sizeof(value)); #else BUILD_BUG_ON(sizeof(u32) != sizeof(value)); #endif And checks for registers widths like: if (reg_info[retAddrReg].width != sizeof(unsigned long)) goto err; It als uses compile time constant sizeofs to initialize and copy stuff: memcpy(&state->cfa, &badCFA, sizeof(state->cfa)); memset(state->regs, 0, sizeof(state->regs)); tableSize = sizeof(unsigned long); To update the actual registers it has code like: #define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs]) #ifndef CONFIG_64BIT # define CASES CASE(8); CASE(16); CASE(32) #else # define CASES CASE(8); CASE(16); CASE(32); CASE(64) #endif case Register: switch (reg_info[i].width) { #define CASE(n) case sizeof(u##n): \ FRAME_REG(i, u##n) = state.regs[i].value; \ break CASES; #undef CASE
Fixed in commit e9068f4d3ccc4f505258834d069d377ce19b328d