ehopt.c revision 77298
138889Sjdp/* ehopt.c--optimize gcc exception frame information.
277298Sobrien   Copyright (C) 1998, 2000 Free Software Foundation, Inc.
338889Sjdp   Written by Ian Lance Taylor <ian@cygnus.com>.
438889Sjdp
538889SjdpThis file is part of GAS, the GNU Assembler.
638889Sjdp
738889SjdpGAS is free software; you can redistribute it and/or modify
838889Sjdpit under the terms of the GNU General Public License as published by
938889Sjdpthe Free Software Foundation; either version 2, or (at your option)
1038889Sjdpany later version.
1138889Sjdp
1238889SjdpGAS is distributed in the hope that it will be useful,
1338889Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of
1438889SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1538889SjdpGNU General Public License for more details.
1638889Sjdp
1738889SjdpYou should have received a copy of the GNU General Public License
1838889Sjdpalong with GAS; see the file COPYING.  If not, write to the Free
1938889SjdpSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
2077298Sobrien02111-1307, USA.  */
2138889Sjdp
2238889Sjdp#include "as.h"
2338889Sjdp#include "subsegs.h"
2438889Sjdp
2538889Sjdp/* We include this ELF file, even though we may not be assembling for
2638889Sjdp   ELF, since the exception frame information is always in a format
2738889Sjdp   derived from DWARF.  */
2838889Sjdp
2938889Sjdp#include "elf/dwarf2.h"
3038889Sjdp
3138889Sjdp/* Try to optimize gcc 2.8 exception frame information.
3238889Sjdp
3338889Sjdp   Exception frame information is emitted for every function in the
3477298Sobrien   .eh_frame or .debug_frame sections.  Simple information for a function
3577298Sobrien   with no exceptions looks like this:
3638889Sjdp
3738889Sjdp__FRAME_BEGIN__:
3838889Sjdp	.4byte	.LLCIE1	/ Length of Common Information Entry
3938889Sjdp.LSCIE1:
4077298Sobrien#if .eh_frame
4138889Sjdp	.4byte	0x0	/ CIE Identifier Tag
4277298Sobrien#elif .debug_frame
4377298Sobrien	.4byte	0xffffffff / CIE Identifier Tag
4477298Sobrien#endif
4538889Sjdp	.byte	0x1	/ CIE Version
4638889Sjdp	.byte	0x0	/ CIE Augmentation (none)
4738889Sjdp	.byte	0x1	/ ULEB128 0x1 (CIE Code Alignment Factor)
4838889Sjdp	.byte	0x7c	/ SLEB128 -4 (CIE Data Alignment Factor)
4938889Sjdp	.byte	0x8	/ CIE RA Column
5038889Sjdp	.byte	0xc	/ DW_CFA_def_cfa
5138889Sjdp	.byte	0x4	/ ULEB128 0x4
5238889Sjdp	.byte	0x4	/ ULEB128 0x4
5338889Sjdp	.byte	0x88	/ DW_CFA_offset, column 0x8
5438889Sjdp	.byte	0x1	/ ULEB128 0x1
5538889Sjdp	.align 4
5638889Sjdp.LECIE1:
5738889Sjdp	.set	.LLCIE1,.LECIE1-.LSCIE1	/ CIE Length Symbol
5838889Sjdp	.4byte	.LLFDE1	/ FDE Length
5938889Sjdp.LSFDE1:
6038889Sjdp	.4byte	.LSFDE1-__FRAME_BEGIN__	/ FDE CIE offset
6138889Sjdp	.4byte	.LFB1	/ FDE initial location
6238889Sjdp	.4byte	.LFE1-.LFB1	/ FDE address range
6338889Sjdp	.byte	0x4	/ DW_CFA_advance_loc4
6438889Sjdp	.4byte	.LCFI0-.LFB1
6538889Sjdp	.byte	0xe	/ DW_CFA_def_cfa_offset
6638889Sjdp	.byte	0x8	/ ULEB128 0x8
6738889Sjdp	.byte	0x85	/ DW_CFA_offset, column 0x5
6838889Sjdp	.byte	0x2	/ ULEB128 0x2
6938889Sjdp	.byte	0x4	/ DW_CFA_advance_loc4
7038889Sjdp	.4byte	.LCFI1-.LCFI0
7138889Sjdp	.byte	0xd	/ DW_CFA_def_cfa_register
7238889Sjdp	.byte	0x5	/ ULEB128 0x5
7338889Sjdp	.byte	0x4	/ DW_CFA_advance_loc4
7438889Sjdp	.4byte	.LCFI2-.LCFI1
7538889Sjdp	.byte	0x2e	/ DW_CFA_GNU_args_size
7638889Sjdp	.byte	0x4	/ ULEB128 0x4
7738889Sjdp	.byte	0x4	/ DW_CFA_advance_loc4
7838889Sjdp	.4byte	.LCFI3-.LCFI2
7938889Sjdp	.byte	0x2e	/ DW_CFA_GNU_args_size
8038889Sjdp	.byte	0x0	/ ULEB128 0x0
8138889Sjdp	.align 4
8238889Sjdp.LEFDE1:
8338889Sjdp	.set	.LLFDE1,.LEFDE1-.LSFDE1	/ FDE Length Symbol
8438889Sjdp
8538889Sjdp   The immediate issue we can address in the assembler is the
8638889Sjdp   DW_CFA_advance_loc4 followed by a four byte value.  The value is
8738889Sjdp   the difference of two addresses in the function.  Since gcc does
8838889Sjdp   not know this value, it always uses four bytes.  We will know the
8938889Sjdp   value at the end of assembly, so we can do better.  */
9038889Sjdp
9177298Sobrienstatic int eh_frame_code_alignment PARAMS ((int));
9238889Sjdp
9338889Sjdp/* Get the code alignment factor from the CIE.  */
9438889Sjdp
9538889Sjdpstatic int
9677298Sobrieneh_frame_code_alignment (in_seg)
9777298Sobrien     int in_seg;
9838889Sjdp{
9977298Sobrien  /* ??? Assume .eh_frame and .debug_frame have the same alignment.  */
10038889Sjdp  static int code_alignment;
10177298Sobrien
10238889Sjdp  fragS *f;
10338889Sjdp  fixS *fix;
10438889Sjdp  int offset;
10577298Sobrien  char CIE_id;
10638889Sjdp  char augmentation[10];
10738889Sjdp  int iaug;
10838889Sjdp
10938889Sjdp  if (code_alignment != 0)
11038889Sjdp    return code_alignment;
11138889Sjdp
11277298Sobrien  /* Can't find the alignment if we've changed sections.  */
11377298Sobrien  if (! in_seg)
11477298Sobrien    return -1;
11538889Sjdp
11677298Sobrien  /* We should find the CIE at the start of the section.  */
11777298Sobrien
11838889Sjdp#if defined (BFD_ASSEMBLER) || defined (MANY_SEGMENTS)
11938889Sjdp  f = seg_info (now_seg)->frchainP->frch_root;
12038889Sjdp#else
12138889Sjdp  f = frchain_now->frch_root;
12238889Sjdp#endif
12338889Sjdp#ifdef BFD_ASSEMBLER
12438889Sjdp  fix = seg_info (now_seg)->frchainP->fix_root;
12538889Sjdp#else
12638889Sjdp  fix = *seg_fix_rootP;
12738889Sjdp#endif
12838889Sjdp
12938889Sjdp  /* Look through the frags of the section to find the code alignment.  */
13038889Sjdp
13177298Sobrien  /* First make sure that the CIE Identifier Tag is 0/-1.  */
13238889Sjdp
13377298Sobrien  if (strcmp (segment_name (now_seg), ".debug_frame") == 0)
13477298Sobrien    CIE_id = (char)0xff;
13577298Sobrien  else
13677298Sobrien    CIE_id = 0;
13777298Sobrien
13838889Sjdp  offset = 4;
13938889Sjdp  while (f != NULL && offset >= f->fr_fix)
14038889Sjdp    {
14138889Sjdp      offset -= f->fr_fix;
14238889Sjdp      f = f->fr_next;
14338889Sjdp    }
14438889Sjdp  if (f == NULL
14538889Sjdp      || f->fr_fix - offset < 4
14677298Sobrien      || f->fr_literal[offset] != CIE_id
14777298Sobrien      || f->fr_literal[offset + 1] != CIE_id
14877298Sobrien      || f->fr_literal[offset + 2] != CIE_id
14977298Sobrien      || f->fr_literal[offset + 3] != CIE_id)
15038889Sjdp    {
15138889Sjdp      code_alignment = -1;
15238889Sjdp      return -1;
15338889Sjdp    }
15438889Sjdp
15538889Sjdp  /* Next make sure the CIE version number is 1.  */
15638889Sjdp
15738889Sjdp  offset += 4;
15838889Sjdp  while (f != NULL && offset >= f->fr_fix)
15938889Sjdp    {
16038889Sjdp      offset -= f->fr_fix;
16138889Sjdp      f = f->fr_next;
16238889Sjdp    }
16338889Sjdp  if (f == NULL
16438889Sjdp      || f->fr_fix - offset < 1
16538889Sjdp      || f->fr_literal[offset] != 1)
16638889Sjdp    {
16738889Sjdp      code_alignment = -1;
16838889Sjdp      return -1;
16938889Sjdp    }
17038889Sjdp
17138889Sjdp  /* Skip the augmentation (a null terminated string).  */
17238889Sjdp
17338889Sjdp  iaug = 0;
17438889Sjdp  ++offset;
17538889Sjdp  while (1)
17638889Sjdp    {
17738889Sjdp      while (f != NULL && offset >= f->fr_fix)
17838889Sjdp	{
17938889Sjdp	  offset -= f->fr_fix;
18038889Sjdp	  f = f->fr_next;
18138889Sjdp	}
18238889Sjdp      if (f == NULL)
18338889Sjdp	{
18438889Sjdp	  code_alignment = -1;
18538889Sjdp	  return -1;
18638889Sjdp	}
18738889Sjdp      while (offset < f->fr_fix && f->fr_literal[offset] != '\0')
18838889Sjdp	{
18938889Sjdp	  if ((size_t) iaug < (sizeof augmentation) - 1)
19038889Sjdp	    {
19138889Sjdp	      augmentation[iaug] = f->fr_literal[offset];
19238889Sjdp	      ++iaug;
19338889Sjdp	    }
19438889Sjdp	  ++offset;
19538889Sjdp	}
19638889Sjdp      if (offset < f->fr_fix)
19738889Sjdp	break;
19838889Sjdp    }
19938889Sjdp  ++offset;
20038889Sjdp  while (f != NULL && offset >= f->fr_fix)
20138889Sjdp    {
20238889Sjdp      offset -= f->fr_fix;
20338889Sjdp      f = f->fr_next;
20438889Sjdp    }
20538889Sjdp  if (f == NULL)
20638889Sjdp    {
20738889Sjdp      code_alignment = -1;
20838889Sjdp      return -1;
20938889Sjdp    }
21038889Sjdp
21138889Sjdp  augmentation[iaug] = '\0';
21238889Sjdp  if (augmentation[0] == '\0')
21338889Sjdp    {
21438889Sjdp      /* No augmentation.  */
21538889Sjdp    }
21638889Sjdp  else if (strcmp (augmentation, "eh") == 0)
21738889Sjdp    {
21838889Sjdp      /* We have to skip a pointer.  Unfortunately, we don't know how
21938889Sjdp	 large it is.  We find out by looking for a matching fixup.  */
22038889Sjdp      while (fix != NULL
22138889Sjdp	     && (fix->fx_frag != f || fix->fx_where != offset))
22238889Sjdp	fix = fix->fx_next;
22338889Sjdp      if (fix == NULL)
22438889Sjdp	offset += 4;
22538889Sjdp      else
22638889Sjdp	offset += fix->fx_size;
22738889Sjdp      while (f != NULL && offset >= f->fr_fix)
22838889Sjdp	{
22938889Sjdp	  offset -= f->fr_fix;
23038889Sjdp	  f = f->fr_next;
23138889Sjdp	}
23238889Sjdp      if (f == NULL)
23338889Sjdp	{
23438889Sjdp	  code_alignment = -1;
23538889Sjdp	  return -1;
23638889Sjdp	}
23738889Sjdp    }
23838889Sjdp  else
23938889Sjdp    {
24038889Sjdp      code_alignment = -1;
24138889Sjdp      return -1;
24238889Sjdp    }
24338889Sjdp
24438889Sjdp  /* We're now at the code alignment factor, which is a ULEB128.  If
24538889Sjdp     it isn't a single byte, forget it.  */
24638889Sjdp
24738889Sjdp  code_alignment = f->fr_literal[offset] & 0xff;
24838889Sjdp  if ((code_alignment & 0x80) != 0 || code_alignment == 0)
24938889Sjdp    {
25038889Sjdp      code_alignment = -1;
25138889Sjdp      return -1;
25238889Sjdp    }
25338889Sjdp
25438889Sjdp  return code_alignment;
25538889Sjdp}
25638889Sjdp
25738889Sjdp/* This function is called from emit_expr.  It looks for cases which
25838889Sjdp   we can optimize.
25938889Sjdp
26038889Sjdp   Rather than try to parse all this information as we read it, we
26138889Sjdp   look for a single byte DW_CFA_advance_loc4 followed by a 4 byte
26238889Sjdp   difference.  We turn that into a rs_cfa_advance frag, and handle
26338889Sjdp   those frags at the end of the assembly.  If the gcc output changes
26438889Sjdp   somewhat, this optimization may stop working.
26538889Sjdp
26638889Sjdp   This function returns non-zero if it handled the expression and
26738889Sjdp   emit_expr should not do anything, or zero otherwise.  It can also
26838889Sjdp   change *EXP and *PNBYTES.  */
26938889Sjdp
27038889Sjdpint
27138889Sjdpcheck_eh_frame (exp, pnbytes)
27238889Sjdp     expressionS *exp;
27338889Sjdp     unsigned int *pnbytes;
27438889Sjdp{
27577298Sobrien  struct frame_data
27677298Sobrien  {
27777298Sobrien    symbolS *size_end_sym;
27877298Sobrien    fragS *loc4_frag;
27977298Sobrien    int saw_size;
28077298Sobrien    int saw_advance_loc4;
28177298Sobrien    int loc4_fix;
28277298Sobrien  };
28338889Sjdp
28477298Sobrien  static struct frame_data eh_frame_data;
28577298Sobrien  static struct frame_data debug_frame_data;
28677298Sobrien  struct frame_data *d;
28777298Sobrien
28877298Sobrien  /* Don't optimize.  */
28977298Sobrien  if (flag_traditional_format)
29077298Sobrien    return 0;
29177298Sobrien
29277298Sobrien  /* Select the proper section data.  */
29377298Sobrien  if (strcmp (segment_name (now_seg), ".eh_frame") == 0)
29477298Sobrien    d = &eh_frame_data;
29577298Sobrien  else if (strcmp (segment_name (now_seg), ".debug_frame") == 0)
29677298Sobrien    d = &debug_frame_data;
29777298Sobrien  else
29877298Sobrien    return 0;
29977298Sobrien
30077298Sobrien  if (d->saw_size && S_IS_DEFINED (d->size_end_sym))
30156944Sobrien    {
30256944Sobrien      /* We have come to the end of the CIE or FDE.  See below where
30356944Sobrien         we set saw_size.  We must check this first because we may now
30456944Sobrien         be looking at the next size.  */
30577298Sobrien      d->saw_size = 0;
30677298Sobrien      d->saw_advance_loc4 = 0;
30756944Sobrien    }
30856944Sobrien
30977298Sobrien  if (! d->saw_size
31077298Sobrien      && *pnbytes == 4)
31138889Sjdp    {
31256944Sobrien      /* This might be the size of the CIE or FDE.  We want to know
31356944Sobrien         the size so that we don't accidentally optimize across an FDE
31456944Sobrien         boundary.  We recognize the size in one of two forms: a
31556944Sobrien         symbol which will later be defined as a difference, or a
31656944Sobrien         subtraction of two symbols.  Either way, we can tell when we
31756944Sobrien         are at the end of the FDE because the symbol becomes defined
31856944Sobrien         (in the case of a subtraction, the end symbol, from which the
31956944Sobrien         start symbol is being subtracted).  Other ways of describing
32056944Sobrien         the size will not be optimized.  */
32156944Sobrien      if ((exp->X_op == O_symbol || exp->X_op == O_subtract)
32256944Sobrien	  && ! S_IS_DEFINED (exp->X_add_symbol))
32356944Sobrien	{
32477298Sobrien	  d->saw_size = 1;
32577298Sobrien	  d->size_end_sym = exp->X_add_symbol;
32656944Sobrien	}
32756944Sobrien    }
32877298Sobrien  else if (d->saw_size
32956944Sobrien	   && *pnbytes == 1
33038889Sjdp	   && exp->X_op == O_constant
33138889Sjdp	   && exp->X_add_number == DW_CFA_advance_loc4)
33238889Sjdp    {
33338889Sjdp      /* This might be a DW_CFA_advance_loc4.  Record the frag and the
33438889Sjdp         position within the frag, so that we can change it later.  */
33577298Sobrien      d->saw_advance_loc4 = 1;
33638889Sjdp      frag_grow (1);
33777298Sobrien      d->loc4_frag = frag_now;
33877298Sobrien      d->loc4_fix = frag_now_fix ();
33938889Sjdp    }
34077298Sobrien  else if (d->saw_advance_loc4
34138889Sjdp	   && *pnbytes == 4
34238889Sjdp	   && exp->X_op == O_constant)
34338889Sjdp    {
34438889Sjdp      int ca;
34538889Sjdp
34638889Sjdp      /* This is a case which we can optimize.  The two symbols being
34738889Sjdp         subtracted were in the same frag and the expression was
34838889Sjdp         reduced to a constant.  We can do the optimization entirely
34938889Sjdp         in this function.  */
35038889Sjdp
35177298Sobrien      d->saw_advance_loc4 = 0;
35238889Sjdp
35377298Sobrien      ca = eh_frame_code_alignment (1);
35438889Sjdp      if (ca < 0)
35538889Sjdp	{
35638889Sjdp	  /* Don't optimize.  */
35738889Sjdp	}
35838889Sjdp      else if (exp->X_add_number % ca == 0
35938889Sjdp	       && exp->X_add_number / ca < 0x40)
36038889Sjdp	{
36177298Sobrien	  d->loc4_frag->fr_literal[d->loc4_fix]
36238889Sjdp	    = DW_CFA_advance_loc | (exp->X_add_number / ca);
36338889Sjdp	  /* No more bytes needed.  */
36438889Sjdp	  return 1;
36538889Sjdp	}
36638889Sjdp      else if (exp->X_add_number < 0x100)
36738889Sjdp	{
36877298Sobrien	  d->loc4_frag->fr_literal[d->loc4_fix] = DW_CFA_advance_loc1;
36938889Sjdp	  *pnbytes = 1;
37038889Sjdp	}
37138889Sjdp      else if (exp->X_add_number < 0x10000)
37238889Sjdp	{
37377298Sobrien	  d->loc4_frag->fr_literal[d->loc4_fix] = DW_CFA_advance_loc2;
37438889Sjdp	  *pnbytes = 2;
37538889Sjdp	}
37638889Sjdp    }
37777298Sobrien  else if (d->saw_advance_loc4
37838889Sjdp	   && *pnbytes == 4
37938889Sjdp	   && exp->X_op == O_subtract)
38038889Sjdp    {
38138889Sjdp      /* This is a case we can optimize.  The expression was not
38238889Sjdp         reduced, so we can not finish the optimization until the end
38338889Sjdp         of the assembly.  We set up a variant frag which we handle
38438889Sjdp         later.  */
38538889Sjdp
38677298Sobrien      d->saw_advance_loc4 = 0;
38738889Sjdp
38838889Sjdp      frag_var (rs_cfa, 4, 0, 0, make_expr_symbol (exp),
38977298Sobrien		d->loc4_fix, (char *) d->loc4_frag);
39038889Sjdp
39138889Sjdp      return 1;
39238889Sjdp    }
39338889Sjdp  else
39477298Sobrien    d->saw_advance_loc4 = 0;
39538889Sjdp
39638889Sjdp  return 0;
39738889Sjdp}
39838889Sjdp
39938889Sjdp/* The function estimates the size of a rs_cfa variant frag based on
40038889Sjdp   the current values of the symbols.  It is called before the
40138889Sjdp   relaxation loop.  We set fr_subtype to the expected length.  */
40238889Sjdp
40338889Sjdpint
40438889Sjdpeh_frame_estimate_size_before_relax (frag)
40538889Sjdp     fragS *frag;
40638889Sjdp{
40738889Sjdp  int ca;
40838889Sjdp  offsetT diff;
40938889Sjdp  int ret;
41038889Sjdp
41177298Sobrien  ca = eh_frame_code_alignment (0);
41238889Sjdp  diff = resolve_symbol_value (frag->fr_symbol, 0);
41338889Sjdp
41438889Sjdp  if (ca < 0)
41538889Sjdp    ret = 4;
41638889Sjdp  else if (diff % ca == 0 && diff / ca < 0x40)
41738889Sjdp    ret = 0;
41838889Sjdp  else if (diff < 0x100)
41938889Sjdp    ret = 1;
42038889Sjdp  else if (diff < 0x10000)
42138889Sjdp    ret = 2;
42238889Sjdp  else
42338889Sjdp    ret = 4;
42438889Sjdp
42538889Sjdp  frag->fr_subtype = ret;
42638889Sjdp
42738889Sjdp  return ret;
42838889Sjdp}
42938889Sjdp
43038889Sjdp/* This function relaxes a rs_cfa variant frag based on the current
43138889Sjdp   values of the symbols.  fr_subtype is the current length of the
43238889Sjdp   frag.  This returns the change in frag length.  */
43338889Sjdp
43438889Sjdpint
43538889Sjdpeh_frame_relax_frag (frag)
43638889Sjdp     fragS *frag;
43738889Sjdp{
43838889Sjdp  int oldsize, newsize;
43938889Sjdp
44038889Sjdp  oldsize = frag->fr_subtype;
44138889Sjdp  newsize = eh_frame_estimate_size_before_relax (frag);
44238889Sjdp  return newsize - oldsize;
44338889Sjdp}
44438889Sjdp
44538889Sjdp/* This function converts a rs_cfa variant frag into a normal fill
44638889Sjdp   frag.  This is called after all relaxation has been done.
44738889Sjdp   fr_subtype will be the desired length of the frag.  */
44838889Sjdp
44938889Sjdpvoid
45038889Sjdpeh_frame_convert_frag (frag)
45138889Sjdp     fragS *frag;
45238889Sjdp{
45338889Sjdp  offsetT diff;
45438889Sjdp  fragS *loc4_frag;
45538889Sjdp  int loc4_fix;
45638889Sjdp
45738889Sjdp  loc4_frag = (fragS *) frag->fr_opcode;
45838889Sjdp  loc4_fix = (int) frag->fr_offset;
45938889Sjdp
46038889Sjdp  diff = resolve_symbol_value (frag->fr_symbol, 1);
46138889Sjdp
46238889Sjdp  if (frag->fr_subtype == 0)
46338889Sjdp    {
46438889Sjdp      int ca;
46538889Sjdp
46677298Sobrien      ca = eh_frame_code_alignment (0);
46738889Sjdp      assert (ca > 0 && diff % ca == 0 && diff / ca < 0x40);
46838889Sjdp      loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc | (diff / ca);
46938889Sjdp    }
47038889Sjdp  else if (frag->fr_subtype == 1)
47138889Sjdp    {
47238889Sjdp      assert (diff < 0x100);
47338889Sjdp      loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc1;
47438889Sjdp      frag->fr_literal[frag->fr_fix] = diff;
47538889Sjdp    }
47638889Sjdp  else if (frag->fr_subtype == 2)
47738889Sjdp    {
47838889Sjdp      assert (diff < 0x10000);
47938889Sjdp      loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc2;
48038889Sjdp      md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 2);
48138889Sjdp    }
48238889Sjdp  else
48338889Sjdp    md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 4);
48438889Sjdp
48538889Sjdp  frag->fr_fix += frag->fr_subtype;
48638889Sjdp  frag->fr_type = rs_fill;
48738889Sjdp  frag->fr_offset = 0;
48838889Sjdp}
489