From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 23015 invoked by alias); 29 May 2003 19:54:26 -0000 Mailing-List: contact gdb-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sources.redhat.com Received: (qmail 23003 invoked from network); 29 May 2003 19:54:25 -0000 Received: from unknown (HELO localhost.redhat.com) (207.219.125.131) by sources.redhat.com with SMTP; 29 May 2003 19:54:25 -0000 Received: from redhat.com (localhost [127.0.0.1]) by localhost.redhat.com (Postfix) with ESMTP id 8FB942B2F; Thu, 29 May 2003 15:54:12 -0400 (EDT) Message-ID: <3ED66564.1020506@redhat.com> Date: Thu, 29 May 2003 19:54:00 -0000 From: Andrew Cagney User-Agent: Mozilla/5.0 (X11; U; NetBSD macppc; en-US; rv:1.0.2) Gecko/20030223 X-Accept-Language: en-us, en MIME-Version: 1.0 To: Mark Kettenis Cc: mludvig@suse.cz, gdb@sources.redhat.com Subject: Re: dwarf-frame.c question References: <3ED381CB.5050207@suse.cz> <200305291544.h4TFi7aL031832@elgar.kettenis.dyndns.org> Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit X-SW-Source: 2003-05/txt/msg00401.txt.bz2 > Date: Tue, 27 May 2003 17:18:35 +0200 > From: Michal Ludvig > > Hi Mark, > > why do you decrement unwound PC in dwarf_frame_cache() before using it? > > The unwound PC is the return address, i.e. the instruction that will > be executed when the function returns. Yes, the resume address, or the next instruction that will be executed when the frame resumes. frame_address_in_block() also tries to handle this. > This is the instruction after > the call instruction. The problem is that if the call instruction is > the last instruction of a function, the return address might point to > the next function: > foo: > ... > call abort > > bar: > push %ebp > mov %esp, %ebp > ... > > That's why the GCC unwinder does the same thing. Note that the > decrementing the PC is wrong for "interrupt frames", which is why the > if-statement is there in the code fragment you cite: > > dwarf-frame.c: > 478 /* Unwind the PC. */ > 479 fs->pc = frame_pc_unwind (next_frame); > 480 if (get_frame_type (next_frame) == NORMAL_FRAME > 481 && frame_relative_level (next_frame) >= 0) > 482 fs->pc--; > > This makes a problem for a signal trampoline. > If it is sitting on addresses say 0x40000140-0x40000150, the return > address from signal handler is 0x40000140, but dwarf_frame_cache() says > it is 0x4000013f and couldn't find it's CFI... > > Do you have signal trampolnes with CFI? If the CFI is hand-generated, > you should probably "cheat" by adding a nop before the trampoline and > include it in the address range of the FDE (see the > arch/i386/kernel/vsyscall-sigreturn.S in the Linux kernel sources). > > This has a tragic consequence few lines below were you look for FDE but > don't check if you find one. If you don't, line 488 segfaults. > 484 /* Find the correct FDE. */ > 485 fde = dwarf_frame_find_fde (&fs->pc); > > Hmm, a gdb_assert() is in order here. > > 487 /* Extract any interesting information from the CIE. */ > 488 fs->data_align = fde->cie->data_alignment_factor; > 489 fs->code_align = fde->cie->code_alignment_factor; > 490 fs->retaddr_column = fde->cie->return_address_register; > > The problem is, that dwarf_frame_p() looks for the real return address > and says that there is a debug info and sets unwinder to use dwarf2 > methods for this farme. > > Hmm, it should do something similar as dwarf_frame_cache(). > > But the in unwinder itself in dwarf_frame_cache() looks for the > decreased one and of course doesn't find it. > > That defenitely is a bug. It isn't immediately obvious to me how to > solve this :-(. First an FYI. CFI has that return-address column. I'm left wondering if frame_pc_unwind() should try the frame for the unwound pc before trying for registers. However, there has so far been zero evidence supporting this need so I think, until there is, let it be. It also wouldn't help with this case - it to would still point back to beyond the function :-( Second, another FYI. This isn't just a CFI problem. There have been earlier posts about how GDB, already gets confused by this - printing out the wrong function address for instance. This problem is generic. Anyway, is it safe to always decrement the resume address before looking for the CFI info? Given a more complex sequence like: 1: setup call 2: call xxx with lots of side effects 3: delay slot saved r0++ 4: discard call then the CFI info for 4 could be very different to that for 2/3. > Andrew, it seems that we should tweak the frame code > to make sure that frame_unwind_by_pc is always passed a PC *within* the > function. True, but how? It would effectively be frame_unwind_address_in_block() but how reliably/where could it be used? Andrew