Mirror of the gdb mailing list
 help / color / mirror / Atom feed
From: Joel Brobecker <brobecker@adacore.com>
To: Gordon Prieur <Gordon.Prieur@Sun.COM>
Cc: Eli Zaretskii <eliz@gnu.org>, gdb@sourceware.org
Subject: Re: Strange stack trace on Windows
Date: Mon, 01 Oct 2007 14:39:00 -0000	[thread overview]
Message-ID: <20071001143906.GL20912@adacore.com> (raw)
In-Reply-To: <4700FE1E.6040201@sun.com>

> Sometime yes, sometimes no. I implemented that solution abotu 6 months
> ago but backed it out because it was just as likely to crash gdb:-(
> or hang my IDE (netbeans).

We have experienced the same type of problem at AdaCore, and decided
to make some compromises: We decided to trust the %ebp registers when
unwinding frameless functions from a DLL. This comes with a price:
We miss a frame in the backtrace. But because tasking is so important
in Ada, we felt it was a better compromise than not being able to unwind
from tasks that are blocked waiting for a rendez-vous.

Which compromise is best actually depends on the user, which is why
this code, or a variation of it, never made it to the FSF tree.

This is what our i386_frame_cache() does in case of frameless routines:

  if (cache->locals < 0)
    {
      /* We didn't find a valid frame, which means that CACHE->base
         currently holds the frame pointer for our calling frame.  If
         we're at the start of a function, or somewhere half-way its
         prologue, the function's frame probably hasn't been fully
         setup yet.  Try to reconstruct the base address for the stack
         frame by looking at the stack pointer.  For truly "frameless"
         functions this might work too.  */

      if (i386_in_dll (cache->pc)
          && !i386_function_has_frame (cache->pc))
        {
          /* Functions in DLL for which do not seem to create a standard
             frame are unwound using %ebp.  This is actually the caller's
             frame base instead of our own, but there are some functions
             such as WaitForSingleObjectEx in one of the Windows system
             DLLs for which the frame base cannot possibly be determined
             from the stack pointer.  As a consequence, our caller will be
             missing from the backtrace, but this is better than having
             an aborted backtrace due to a bogus frame base.
             
             We use this approach only for functions in DLLs because
             this is the only place where we have seen the type of
             highly optimized code that cause us trouble.  In other
             cases, we expect the code to come with frame debugging
             information, making prologue scanning unnecessary.
             
             We also avoid blindly following %ebp if we are midway through
             setting up a standard frame.  In that case, we know how to
             determine the frame base using the stack pointer.  */

          cache->saved_regs[I386_EBP_REGNUM] = 0;
        }
      else
        {
          i386_frameless_adjust_cache_hack (cache, frame_pc_unwind (next_frame));

          if (cache->stack_align)
            {
              /* We're halfway aligning the stack.  */
              cache->base = ((cache->saved_sp - 4) & 0xfffffff0) - 4;
              cache->saved_regs[I386_EIP_REGNUM] = cache->saved_sp - 4;

              /* This will be added back below.  */ 
              cache->saved_regs[I386_EIP_REGNUM] -= cache->base;
            }
          else
            {
              frame_unwind_register (next_frame, I386_ESP_REGNUM, buf);
              cache->base = extract_unsigned_integer (buf, 4) + cache->sp_offset;
            }
        }
    }

And the two helper functions are defined as:

/* Return non-zero if the function starting at START_PC has a prologue
   that sets up a standard frame.  */

static int
i386_function_has_frame (CORE_ADDR start_pc)
{
  struct i386_frame_cache cache;

  cache.locals = -1;
  i386_analyze_prologue (start_pc, 0xffffffff, &cache);

  return (cache.locals >= 0);
}

/* Return non-zero if PC is inside one of the inferior's DLLs.  */

static int
i386_in_dll (CORE_ADDR pc)
{
   char *so_name = solib_address (pc);
   int len;

   if (so_name == NULL)
     return 0;

   len = strlen (so_name);
   if (len < 5)
     return 0;

   return ((so_name[len - 1] == 'l' || so_name[len - 1] == 'L')
           && (so_name[len - 2] == 'l' || so_name[len - 2] == 'L')
           && (so_name[len - 3] == 'd' || so_name[len - 3] == 'D')
           && so_name[len - 4] == '.');
}



-- 
Joel


  reply	other threads:[~2007-10-01 14:39 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-09-29 22:01 Gordon Prieur
2007-09-30  3:00 ` Daniel Jacobowitz
2007-09-30 18:13 ` Eli Zaretskii
2007-10-01 14:03   ` Gordon Prieur
2007-10-01 14:39     ` Joel Brobecker [this message]
2009-03-17 11:58 Roland Schwingel
2009-03-17 13:19 ` Joel Brobecker
2009-03-17 13:49 Roland Schwingel
2009-03-17 14:27 ` Pedro Alves
2009-03-17 15:08 ` Joel Brobecker
2009-03-17 15:26 Roland Schwingel
2009-03-17 15:39 Roland Schwingel
2009-03-17 19:43 ` Joel Brobecker
2009-03-18  9:26 Roland Schwingel
2009-03-19 14:18 ` Joel Brobecker
2009-03-23 13:12 Roland Schwingel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20071001143906.GL20912@adacore.com \
    --to=brobecker@adacore.com \
    --cc=Gordon.Prieur@Sun.COM \
    --cc=eliz@gnu.org \
    --cc=gdb@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox