This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Revamp sniffer; Was: [obish?sym;rfa:doc] Wire up vsyscall


Ok,

I just figured out why amd64 GNU/Linux signal trampolines don't work correctly and the reason is scary!

After signal delivery (e.x., sigaltstack testcase) the stack looks like:

  sentinel: SENTINEL_FRAME
  catcher: NORMAL_FRAME, dwarf2 unwinder
  <sigtramp>: SIGTRAMP_FRAME, sigtramp unwinder
  thrower: NORMAL_FRAME, dwarf2 unwinder

while later after catcher has "finish"ed it looks like:

  sentinel: SENTINEL_FRAME
  __restore_rt: NORMAL_FRAME, dwarf2 unwinder
  <corrupt stack>

Notice how the first time round the trampoline was correctly identified but not the second. What happened?

In the first case:

- linux jumps to catcher setting it's return address to <sigtramp>'s entry point
- gdb correctly identifies catcher as a callee or normal frame
- gdb goes to unwind catcher and starts sniffing <sigtramp>
- the dwarf2 sniffer, when sniffing <sigtramp>, asks for that frame's address-in-block, since the catcher is a normal frame, that translates to <catcher's-return-address>-1
- <catcher's-return-address>-1 translates into <sigtramp>-1
- since <sigtramp>-1 doesn't have any CFI (lucky eh?) dwarf2 dismisses the frame
- the sigtramp unwinder gets to take a wiff and identifies the frame


while in the second case (no catcher):

- the dwarf2 sniffer, when sniffing <sigtramp>, asks for that frame's address-in-block, since the next frame is a sentinel that translates into <catcher's-return-address>
- <catcher's-return-address> translates into <sigtramp>
- <sigtramp> does have CFI so dwarf2 claims the frame marking it "normal", outch!


So for the moment, I think the sigtramp frame should always be sniffed before the dwarf2 frame. We can revisit the possability of modifing dwarf2 later, much later.

Andrew
--- Begin Message --- ping
--- Begin Message --- Mark,

Want do you want to do here? Commit daniel's patch for the short term while I clean this up proper over the medium term (appending it to the vsyscall list)?

Andrew
--- Begin Message ---
  • From: Andrew Cagney <cagney at gnu dot org>
  • To: Mark Kettenis <kettenis at chello dot nl>
  • Cc: drow at false dot org, gdb-patches at sources dot redhat dot com, roland at redhat dot com
  • Date: Mon, 17 May 2004 13:14:48 -0400
  • Subject: Revamp sniffer; Was: [obish?sym;rfa:doc] Wire up vsyscall
  • Delivery-date: Mon, 17 May 2004 14:17:10 -0400
  • Envelope-to: cagney@gnu.org
  • References: <409A8C2A.2010605@gnu.org> <409AA61F.8050807@gnu.org> <20040507012549.GA30182@nevyn.them.org> <409FF3D7.5000106@gnu.org> <200405102140.i4ALe13A001092@elgar.kettenis.dyndns.org> <20040511145344.GA15501@nevyn.them.org> <40A0FFB1.8030407@gnu.org> <20040511172619.GA19487@nevyn.them.org> <40A16FA1.9060506@gnu.org> <200405152057.i4FKvdt2000817@elgar.kettenis.dyndns.org>
2004-01-25 Daniel Jacobowitz <drow@mvista.com>

	* i386-tdep.c (i386_gdbarch_init): Check for signal frame first.
	* i386-linux-tdep.c (i386_linux_pc_in_sigtramp): Handle
	__kernel_sigreturn.

[...]
I'm somewhat reluctant to throw the CFI completely overboard.

Yes.


How
about extending the DWARF2 unwinder such that we can set the
[SIGTRAMP_FRAME] attribute based on the function's name?

The frame attributes (tramp et.al.) in many cases are orthogonal to the unwind mechanism, but sometimes they are not).


At present the frame sniffer is focused solely on identifying and returning an unwinder. The frame's type being identified as an unexpected sid effect. I think this should be inverted vis:

frame_sniffer () ->
	- attributes
	- unwinder (or NULL, indicating sniff for unwinder)
	- base (or NULL, indicating sniff for base)
	- ...

so while the type is determined up front, other things are optional. That way here the tramp code would look like:

  if (name == _kernel_sigreturn)
    if (cfi at address)
      return { attribute=TRAMP; unwinder=cfi_unwinder; base=NULL };
    else
      return { attribute=TRAMP; unwinder=alt_unwinder; base=NULL };

this also opens the way for us doing:

  if (name == solib-trampoline)
    return { attribute=TRAMP|CALLEE; unwinder=NULL; base=NULL }

i.e., it's a trampoline (need to skip it) but let something more generic identify the unwinder.

Andrew





--- End Message ---

--- End Message ---

--- End Message ---

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]