Skip to content
  • Alan Modra's avatar
    [GOLD] PowerPC notoc eh_frame · 220f9906
    Alan Modra authored
    When generating notoc call and branch stubs without the benefit of
    pc-relative insns, the stubs need to use LR to access the run time PC.
    All LR changes must be described in .eh_frame if we're to support
    unwinding through asynchronous exceptions.  That's what this patch
    does.
    
    The patch has gone through way too many iterations.  At first I
    attempted to add multiple FDEs, one for each stub.  That ran into
    difficulties with do_plt_fde_location which is only capable of setting
    the address of a single FDE per Output_data section, and with removing
    any FDEs added on a previous do_relax pass.  Removing FDEs (git commit
    be897fb7) went overboard in matching the FDE contents.  That means
    either stashing the contents created for add_eh_frame_for_plt to use
    when calling remove_eh_frame_for_plt, or recreating contents on the
    fly (*) just to remove FDEs.  In fact, FDE content matching is quite
    unnecesary.  FDEs added by a previous do_relax pass are those with
    u_.from_linker.post_map set.  So they can easily be recognised just by
    looking at that flag.  This patch keeps that part of the multiple FDE
    changes.
    
    In the end I went for just one FDE per stub group to describe the call
    stubs.  That's reasonably efficient for the common case of only
    needing to describe the __tls_get_addr_opt call stub.  We don't expect
    to be making many calls using notoc stubs without pc-relative insns.
    
    *) Which has it's own set of problems.  The contents must be recreated
    using the old stub layout, but .eh_frame size can affect stub
    requirements so you need to temporarily keep the old .eh_frame size
    when creating new stubs, then reset .eh_frame size before adding new
    FDEs.
    
    	* ehframe.cc (Fde::operator==): Delete.
    	(Cie::remove_fde): Delete.
    	(Eh_frame::remove_ehframe_for_plt): Delete fde_data and fde_length
    	parameters.  Remove all post-map plt FDEs.
    	* ehframe.h (Fde:post_map): Make const, add variant to compare plt.
    	(Fde::operator==): Delete.
    	(Cie::remove_fde): Implement here.
    	(Cie::last_fde): New accessor.
    	(Eh_frame::remove_ehframe_for_plt): Update prototype.
    	* layout.cc (Layout::remove_eh_frame_for_plt): Delete fde_data and
    	fde_length parameters.
    	* layout.h (Layout::remove_eh_frame_for_plt): Update prototype.
    	* powerpc.cc (Stub_table::tls_get_addr_opt_bctrl_): Delete.
    	(Stub_table::plt_fde_len_, plt_fde_, init_plt_fde): Delete.
    	(Stub_table::add_plt_call_entry): Don't set tls_get_addr_opt_bctrl_.
    	(eh_advance): New function.
    	(stub_sort): New function.
    	(Stub_table::add_eh_frame): Emit eh_frame for notoc plt calls and
    	branches as well as __tls_get_addr_opt plt call stub.
    	(Stub_table::remove_eh_frame): Update to suit.
    220f9906
To find the state of this project's repository at the time of any of these versions, check out the tags.