Summary ======= libunwind is not correctly unwinding through frames for functions annotated with the __attribute__((ms_abi)).
Platform ======== observed on x86-64, linux, and gcc How to reproduce ================ build a standard, vanilla, instance of libunwind 0.99 compile and link the program given below ensure that libunwind will be found at runtime note the difference in the backtraces shown this is an example: x86-64-linux-fedora14-x8664% ./t_repro calling f 0: 0x400852 1: 0x40090a 2: 0x40096d 3: 0x400966 4: 0x400966 5: 0x400966 6: 0x400966 7: 0x400966 8: 0x400966 9: 0x400a78 10: 0x315a61ee5d 11: 0x400769 calling f_ms_abi 0: 0x400852 1: 0x40090a 2: 0x4009dc Comments ======== f and f_ms_abi are identical with the exception that f_ms_abi is annoted with __attribute__((ms_abi)). This causes the compiler to emit code to save registers not otherwise saved. The DWARF thus also contains directives for these registers. Runnning the program with the UNW_DEBUG_LEVEL environment variable set to 1 generates debug output which includes the following: >run_cfi_program: Invalid register number 32 in DW_cfa_OFFSET Program which reproduces the problem ==================================== #include <stdio.h> #define UNW_LOCAL_ONLY #include <libunwind-x86_64.h> int backtrace ( void **pcs, int vector_length ) { int ret_val = 0; unw_context_t context; unw_cursor_t cursor; unw_word_t this_pc; ret_val = ( unw_getcontext ( &context ) || unw_init_local ( &cursor, &context ) ); if ( 0 == ret_val ) { do { unw_get_reg ( &cursor, UNW_REG_IP, &this_pc ); pcs [ ret_val ] = (void *) this_pc; ret_val++; } while ( (ret_val < vector_length) && (unw_step ( &cursor ) > 0) ); } return ret_val; } /* backtrace */ void do_backtrace (void) { void *pcs [ 64 ]; int max_pcs = sizeof ( pcs ) / sizeof ( pcs [ 0 ] ); int num_pcs = backtrace ( pcs, max_pcs ); int i; for ( i = 0; i < num_pcs; i ++ ) printf ( " %2d: %p\n", i, pcs [ i ] ); } /* do_backtrace */ void f ( int arg ) { if ( arg > 0 ) { f ( arg - 1 ); } else { do_backtrace (); } } /* f */ int __attribute__((ms_abi)) f_ms_abi ( int arg ) { if ( arg > 0 ) { f_ms_abi ( arg - 1 ); } else { do_backtrace (); } } /* f_ms_abi */ int main ( int argc, char *argv [] ) { setvbuf ( stdout, 0, _IONBF, 0 ); printf ( "calling f\n" ); f ( 6 ); printf ( "calling f_ms_abi\n" ); f_ms_abi ( 6 ); return 0; } /* main */ _______________________________________________ Libunwind-devel mailing list Libunwind-devel@nongnu.org https://lists.nongnu.org/mailman/listinfo/libunwind-devel