libunwind-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Libunwind-devel] problem with ms_abi on x86-64


From: ariel . burton
Subject: [Libunwind-devel] problem with ms_abi on x86-64
Date: Tue, 24 May 2011 11:18:28 -0400
User-agent: nail 11.25 7/29/05

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 */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]