This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

PATCH: generate DWARF2 unwind information for epilogues


This patch adds epilogue handling capabilities to the DWARF2 unwind
information emission.  It also contains tweaks to the x86/x86-64
backend to smooth out the generation of such information.

Background: here at Rice, we have developed a low-overhead callstack
profiler for optimized code that can also record edge count information
at low cost (see our ICS'05 paper for details).  The basic idea is to
take callstack samples at timer interrupts; massaging the return address
at sample times ensures that the amount of unwinding is small and
provides edge count data as a bonus.  Our prototype was written for the
Alpha platform and made extensive use of the compiler-generated unwind
information.

When porting our profiler to the x86-64, we found that compilers did not
generate enough unwind information for our purposes.  In particular,
samples taken in the middle of epilogues would result in bogus
callstacks being collected.  We therefore needed to add two pieces of
infrastructure to GCC:

1) The ability to generate unwind information for procedure epilogues;
2) The ability to generate DWARF2_{remember,restore}_state pairs when
   appropriate.

As an example of each of these requirements, consider the following
x86-64 code:

    ...
A:
    add $0x48, %rsp
    [pop registers]
    retq
B:
    ...
    ...
C:
    add $x048, %rsp
    [pop registers]
    retq

Prior to our patch, if a sample was taken between 'C' and the following
'retq', the stack could not be properly unwound, as the adjustments to
the stack pointer were not recorded.  This motivates requirement 1).
Additionally, even with the adjustments recorded, taking a sample
between 'B' and 'C' would unwind the stack too much, since the effects
of the duplicated epilogue between 'A' and 'B' would not be discarded.
This motivates requirement 2).

This patch, therefore, adds the necessary bits to GCC.  At a high level,
we had to:

1) Add support in the DWARF2 generator;
2) Teach various parts of GCC to play nicely with multiple epilogues
   (there was always a single EPILOGUE_BEG note prior to our efforts
    and several functions relied on this);
3) Teach the x86 backend to mark instructions as RTX_FRAME_RELATED_P.

For proper functioning, this patch requires an earlier patch we sent
to the list ("PATCH: correctly handle the CFA in DWARF2 unwinding")
last month.  Otherwise, many tests in the test suite that require
unwinding will fail.

We haven't done extensive measurements on the increased disk space
necessary for binaries compiled with this patch.  As a data point, the
total size of the executables in gcc/ (cc1, jc1, g++, cpp, etc.)--
excluding the '-dummy' variants--after a full bootstrap was 146,234,914
bytes without our patch and 148,685,043 bytes with our patch--an
increase of ~1.7%.  We feel this is a small price to pay for on-demand
callstack profiles from optimized code--no recompilation necessary.

Tested with a bootstrap and `make -k check' on x86_64-pc-linux-gnu.  No
regressions.  OK for mainline?

2006-02-14  Nathan Froyd  <froydnj@cs.rice.edu>

	* gcc/rtl.h: Export record_epilogue_insn and forget_epilogue_insn.
	* gcc/cfglayout.c (duplicate_insn_chain): Recognize when we're
	  duplicating epilogues and record the duplicated instructions
	  as being part of the epilogue.  Don't strip EPILOGUE_BEG notes.
	* gcc/cfgrtl.c (can_delete_note_p): Delete EPILOGUE_BEG notes.
	* gcc/final.c (final_scan_insn): Pass BASIC_BLOCK and
          EPILOGUE_BEG notes to dwarf2_out_process_note.
	* gcc/dwarf2out.c (dwarf2out_state_label): New.
	(lookup_cfa): Don't consider entries between remember/restore
	state pairs.
	(reg_restore): New.
	(dwarf2out_remember_state): New.
	(dwarf2out_restore_state): New.
	(dwarf2out_frame_debug_expr): Cases to handle epilogue code.
	Essentially mirror images of what was already there.
	(dwarf2out_process_note): New.
	(dwarf2out_frame_debug): Initialize last_block and
	need_restore_state.
	(dw_cfi_oprnd1_desc): Handle
	DW_CFA_{remember_state,restore_state,restore}.
	(dwarf2out_being_prologue): Initialize fde->remember_restore_pairs.
	(convert_cfa_to_loc_list): Skip code bracketed between
	remember/restore state pairs.
	* gcc/dwarf2out.h: Export dwarf2out_process_note.
	* gcc/function.c (record_epilogue_insn,forget_epilogue_insn): New.
	(thread_prologue_and_epilogue_insns): Emit EPILOGUE_BEG note for
	sibcall epilogue sequences.
	(reposition_prologue_and_epilogue_notes): Shuffle EPILOGUE_BEG
	notes to appropriate places based on epilogue-ness of insns.
	* gcc/config/i386/i386.md (leave,leave_rex64): Tweak into
	something the DWARF2 unwind information generator understands.
	* gcc/config/i386/i386.c (pro_epilogue_adjust_stack): Mark
	insns as RTX_FRAME_RELATED_P as appropriate.
	(ix86_restore_moves_use_sp): New.
	(ix86_expand_prologue): Mark insns as RTX_FRAME_RELATED_P as
	appropriate.
	(ix86_mark_parallel_rtx_as_frame_related): New.
	(ix86_epilogue_restores_use_mov): New.
	(ix86_expand_epilogue): Mark insns as RTX_FRAME_RELATED_P as
	appropriate.

-- 
Nathan | From Man's effeminate slackness it begins.  --Paradise Lost

The last good thing written in C was Franz Schubert's Symphony Number 9.
                                               --Erwin Dieterich

Attachment: dwarf2-unwind.patch
Description: Text document


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