Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /* ehopt.c--optimize gcc exception frame information.
  2.    Copyright 1998, 2000, 2001, 2003, 2005, 2007, 2008, 2009
  3.    Free Software Foundation, Inc.
  4.    Written by Ian Lance Taylor <ian@cygnus.com>.
  5.  
  6.    This file is part of GAS, the GNU Assembler.
  7.  
  8.    GAS is free software; you can redistribute it and/or modify
  9.    it under the terms of the GNU General Public License as published by
  10.    the Free Software Foundation; either version 3, or (at your option)
  11.    any later version.
  12.  
  13.    GAS is distributed in the hope that it will be useful,
  14.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.    GNU General Public License for more details.
  17.  
  18.    You should have received a copy of the GNU General Public License
  19.    along with GAS; see the file COPYING.  If not, write to the Free
  20.    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
  21.    02110-1301, USA.  */
  22.  
  23. #include "as.h"
  24. #include "subsegs.h"
  25. #include "struc-symbol.h"
  26.  
  27. /* We include this ELF file, even though we may not be assembling for
  28.    ELF, since the exception frame information is always in a format
  29.    derived from DWARF.  */
  30.  
  31. #include "dwarf2.h"
  32.  
  33. /* Try to optimize gcc 2.8 exception frame information.
  34.  
  35.    Exception frame information is emitted for every function in the
  36.    .eh_frame or .debug_frame sections.  Simple information for a function
  37.    with no exceptions looks like this:
  38.  
  39. __FRAME_BEGIN__:
  40.         .4byte  .LLCIE1 / Length of Common Information Entry
  41. .LSCIE1:
  42. #if .eh_frame
  43.         .4byte  0x0     / CIE Identifier Tag
  44. #elif .debug_frame
  45.         .4byte  0xffffffff / CIE Identifier Tag
  46. #endif
  47.         .byte   0x1     / CIE Version
  48.         .byte   0x0     / CIE Augmentation (none)
  49.         .byte   0x1     / ULEB128 0x1 (CIE Code Alignment Factor)
  50.         .byte   0x7c    / SLEB128 -4 (CIE Data Alignment Factor)
  51.         .byte   0x8     / CIE RA Column
  52.         .byte   0xc     / DW_CFA_def_cfa
  53.         .byte   0x4     / ULEB128 0x4
  54.         .byte   0x4     / ULEB128 0x4
  55.         .byte   0x88    / DW_CFA_offset, column 0x8
  56.         .byte   0x1     / ULEB128 0x1
  57.         .align 4
  58. .LECIE1:
  59.         .set    .LLCIE1,.LECIE1-.LSCIE1 / CIE Length Symbol
  60.         .4byte  .LLFDE1 / FDE Length
  61. .LSFDE1:
  62.         .4byte  .LSFDE1-__FRAME_BEGIN__ / FDE CIE offset
  63.         .4byte  .LFB1   / FDE initial location
  64.         .4byte  .LFE1-.LFB1     / FDE address range
  65.         .byte   0x4     / DW_CFA_advance_loc4
  66.         .4byte  .LCFI0-.LFB1
  67.         .byte   0xe     / DW_CFA_def_cfa_offset
  68.         .byte   0x8     / ULEB128 0x8
  69.         .byte   0x85    / DW_CFA_offset, column 0x5
  70.         .byte   0x2     / ULEB128 0x2
  71.         .byte   0x4     / DW_CFA_advance_loc4
  72.         .4byte  .LCFI1-.LCFI0
  73.         .byte   0xd     / DW_CFA_def_cfa_register
  74.         .byte   0x5     / ULEB128 0x5
  75.         .byte   0x4     / DW_CFA_advance_loc4
  76.         .4byte  .LCFI2-.LCFI1
  77.         .byte   0x2e    / DW_CFA_GNU_args_size
  78.         .byte   0x4     / ULEB128 0x4
  79.         .byte   0x4     / DW_CFA_advance_loc4
  80.         .4byte  .LCFI3-.LCFI2
  81.         .byte   0x2e    / DW_CFA_GNU_args_size
  82.         .byte   0x0     / ULEB128 0x0
  83.         .align 4
  84. .LEFDE1:
  85.         .set    .LLFDE1,.LEFDE1-.LSFDE1 / FDE Length Symbol
  86.  
  87.    The immediate issue we can address in the assembler is the
  88.    DW_CFA_advance_loc4 followed by a four byte value.  The value is
  89.    the difference of two addresses in the function.  Since gcc does
  90.    not know this value, it always uses four bytes.  We will know the
  91.    value at the end of assembly, so we can do better.  */
  92.  
  93. struct cie_info
  94. {
  95.   unsigned code_alignment;
  96.   int z_augmentation;
  97. };
  98.  
  99. static int get_cie_info (struct cie_info *);
  100.  
  101. /* Extract information from the CIE.  */
  102.  
  103. static int
  104. get_cie_info (struct cie_info *info)
  105. {
  106.   fragS *f;
  107.   fixS *fix;
  108.   int offset;
  109.   char CIE_id;
  110.   char augmentation[10];
  111.   int iaug;
  112.   int code_alignment = 0;
  113.  
  114.   /* We should find the CIE at the start of the section.  */
  115.  
  116.   f = seg_info (now_seg)->frchainP->frch_root;
  117.   fix = seg_info (now_seg)->frchainP->fix_root;
  118.  
  119.   /* Look through the frags of the section to find the code alignment.  */
  120.  
  121.   /* First make sure that the CIE Identifier Tag is 0/-1.  */
  122.  
  123.   if (strncmp (segment_name (now_seg), ".debug_frame", 12) == 0)
  124.     CIE_id = (char)0xff;
  125.   else
  126.     CIE_id = 0;
  127.  
  128.   offset = 4;
  129.   while (f != NULL && offset >= f->fr_fix)
  130.     {
  131.       offset -= f->fr_fix;
  132.       f = f->fr_next;
  133.     }
  134.   if (f == NULL
  135.       || f->fr_fix - offset < 4
  136.       || f->fr_literal[offset] != CIE_id
  137.       || f->fr_literal[offset + 1] != CIE_id
  138.       || f->fr_literal[offset + 2] != CIE_id
  139.       || f->fr_literal[offset + 3] != CIE_id)
  140.     return 0;
  141.  
  142.   /* Next make sure the CIE version number is 1.  */
  143.  
  144.   offset += 4;
  145.   while (f != NULL && offset >= f->fr_fix)
  146.     {
  147.       offset -= f->fr_fix;
  148.       f = f->fr_next;
  149.     }
  150.   if (f == NULL
  151.       || f->fr_fix - offset < 1
  152.       || f->fr_literal[offset] != 1)
  153.     return 0;
  154.  
  155.   /* Skip the augmentation (a null terminated string).  */
  156.  
  157.   iaug = 0;
  158.   ++offset;
  159.   while (1)
  160.     {
  161.       while (f != NULL && offset >= f->fr_fix)
  162.         {
  163.           offset -= f->fr_fix;
  164.           f = f->fr_next;
  165.         }
  166.       if (f == NULL)
  167.         return 0;
  168.  
  169.       while (offset < f->fr_fix && f->fr_literal[offset] != '\0')
  170.         {
  171.           if ((size_t) iaug < (sizeof augmentation) - 1)
  172.             {
  173.               augmentation[iaug] = f->fr_literal[offset];
  174.               ++iaug;
  175.             }
  176.           ++offset;
  177.         }
  178.       if (offset < f->fr_fix)
  179.         break;
  180.     }
  181.   ++offset;
  182.   while (f != NULL && offset >= f->fr_fix)
  183.     {
  184.       offset -= f->fr_fix;
  185.       f = f->fr_next;
  186.     }
  187.   if (f == NULL)
  188.     return 0;
  189.  
  190.   augmentation[iaug] = '\0';
  191.   if (augmentation[0] == '\0')
  192.     {
  193.       /* No augmentation.  */
  194.     }
  195.   else if (strcmp (augmentation, "eh") == 0)
  196.     {
  197.       /* We have to skip a pointer.  Unfortunately, we don't know how
  198.          large it is.  We find out by looking for a matching fixup.  */
  199.       while (fix != NULL
  200.              && (fix->fx_frag != f || fix->fx_where != offset))
  201.         fix = fix->fx_next;
  202.       if (fix == NULL)
  203.         offset += 4;
  204.       else
  205.         offset += fix->fx_size;
  206.       while (f != NULL && offset >= f->fr_fix)
  207.         {
  208.           offset -= f->fr_fix;
  209.           f = f->fr_next;
  210.         }
  211.       if (f == NULL)
  212.         return 0;
  213.     }
  214.   else if (augmentation[0] != 'z')
  215.     return 0;
  216.  
  217.   /* We're now at the code alignment factor, which is a ULEB128.  If
  218.      it isn't a single byte, forget it.  */
  219.  
  220.   code_alignment = f->fr_literal[offset] & 0xff;
  221.   if ((code_alignment & 0x80) != 0)
  222.     code_alignment = 0;
  223.  
  224.   info->code_alignment = code_alignment;
  225.   info->z_augmentation = (augmentation[0] == 'z');
  226.  
  227.   return 1;
  228. }
  229.  
  230. enum frame_state
  231. {
  232.   state_idle,
  233.   state_saw_size,
  234.   state_saw_cie_offset,
  235.   state_saw_pc_begin,
  236.   state_seeing_aug_size,
  237.   state_skipping_aug,
  238.   state_wait_loc4,
  239.   state_saw_loc4,
  240.   state_error,
  241. };
  242.  
  243. /* This function is called from emit_expr.  It looks for cases which
  244.    we can optimize.
  245.  
  246.    Rather than try to parse all this information as we read it, we
  247.    look for a single byte DW_CFA_advance_loc4 followed by a 4 byte
  248.    difference.  We turn that into a rs_cfa_advance frag, and handle
  249.    those frags at the end of the assembly.  If the gcc output changes
  250.    somewhat, this optimization may stop working.
  251.  
  252.    This function returns non-zero if it handled the expression and
  253.    emit_expr should not do anything, or zero otherwise.  It can also
  254.    change *EXP and *PNBYTES.  */
  255.  
  256. int
  257. check_eh_frame (expressionS *exp, unsigned int *pnbytes)
  258. {
  259.   struct frame_data
  260.   {
  261.     enum frame_state state;
  262.  
  263.     int cie_info_ok;
  264.     struct cie_info cie_info;
  265.  
  266.     symbolS *size_end_sym;
  267.     fragS *loc4_frag;
  268.     int loc4_fix;
  269.  
  270.     int aug_size;
  271.     int aug_shift;
  272.   };
  273.  
  274.   static struct frame_data eh_frame_data;
  275.   static struct frame_data debug_frame_data;
  276.   struct frame_data *d;
  277.  
  278.   /* Don't optimize.  */
  279.   if (flag_traditional_format)
  280.     return 0;
  281.  
  282. #ifdef md_allow_eh_opt
  283.   if (! md_allow_eh_opt)
  284.     return 0;
  285. #endif
  286.  
  287.   /* Select the proper section data.  */
  288.   if (strncmp (segment_name (now_seg), ".eh_frame", 9) == 0
  289.       && segment_name (now_seg)[9] != '_')
  290.     d = &eh_frame_data;
  291.   else if (strncmp (segment_name (now_seg), ".debug_frame", 12) == 0)
  292.     d = &debug_frame_data;
  293.   else
  294.     return 0;
  295.  
  296.   if (d->state >= state_saw_size && S_IS_DEFINED (d->size_end_sym))
  297.     {
  298.       /* We have come to the end of the CIE or FDE.  See below where
  299.          we set saw_size.  We must check this first because we may now
  300.          be looking at the next size.  */
  301.       d->state = state_idle;
  302.     }
  303.  
  304.   switch (d->state)
  305.     {
  306.     case state_idle:
  307.       if (*pnbytes == 4)
  308.         {
  309.           /* This might be the size of the CIE or FDE.  We want to know
  310.              the size so that we don't accidentally optimize across an FDE
  311.              boundary.  We recognize the size in one of two forms: a
  312.              symbol which will later be defined as a difference, or a
  313.              subtraction of two symbols.  Either way, we can tell when we
  314.              are at the end of the FDE because the symbol becomes defined
  315.              (in the case of a subtraction, the end symbol, from which the
  316.              start symbol is being subtracted).  Other ways of describing
  317.              the size will not be optimized.  */
  318.           if ((exp->X_op == O_symbol || exp->X_op == O_subtract)
  319.               && ! S_IS_DEFINED (exp->X_add_symbol))
  320.             {
  321.               d->state = state_saw_size;
  322.               d->size_end_sym = exp->X_add_symbol;
  323.             }
  324.         }
  325.       break;
  326.  
  327.     case state_saw_size:
  328.     case state_saw_cie_offset:
  329.       /* Assume whatever form it appears in, it appears atomically.  */
  330.       d->state = (enum frame_state) (d->state + 1);
  331.       break;
  332.  
  333.     case state_saw_pc_begin:
  334.       /* Decide whether we should see an augmentation.  */
  335.       if (! d->cie_info_ok
  336.           && ! (d->cie_info_ok = get_cie_info (&d->cie_info)))
  337.         d->state = state_error;
  338.       else if (d->cie_info.z_augmentation)
  339.         {
  340.           d->state = state_seeing_aug_size;
  341.           d->aug_size = 0;
  342.           d->aug_shift = 0;
  343.         }
  344.       else
  345.         d->state = state_wait_loc4;
  346.       break;
  347.  
  348.     case state_seeing_aug_size:
  349.       /* Bytes == -1 means this comes from an leb128 directive.  */
  350.       if ((int)*pnbytes == -1 && exp->X_op == O_constant)
  351.         {
  352.           d->aug_size = exp->X_add_number;
  353.           d->state = state_skipping_aug;
  354.         }
  355.       else if (*pnbytes == 1 && exp->X_op == O_constant)
  356.         {
  357.           unsigned char byte = exp->X_add_number;
  358.           d->aug_size |= (byte & 0x7f) << d->aug_shift;
  359.           d->aug_shift += 7;
  360.           if ((byte & 0x80) == 0)
  361.             d->state = state_skipping_aug;
  362.         }
  363.       else
  364.         d->state = state_error;
  365.       if (d->state == state_skipping_aug && d->aug_size == 0)
  366.         d->state = state_wait_loc4;
  367.       break;
  368.  
  369.     case state_skipping_aug:
  370.       if ((int)*pnbytes < 0)
  371.         d->state = state_error;
  372.       else
  373.         {
  374.           int left = (d->aug_size -= *pnbytes);
  375.           if (left == 0)
  376.             d->state = state_wait_loc4;
  377.           else if (left < 0)
  378.             d->state = state_error;
  379.         }
  380.       break;
  381.  
  382.     case state_wait_loc4:
  383.       if (*pnbytes == 1
  384.           && exp->X_op == O_constant
  385.           && exp->X_add_number == DW_CFA_advance_loc4)
  386.         {
  387.           /* This might be a DW_CFA_advance_loc4.  Record the frag and the
  388.              position within the frag, so that we can change it later.  */
  389.           frag_grow (1);
  390.           d->state = state_saw_loc4;
  391.           d->loc4_frag = frag_now;
  392.           d->loc4_fix = frag_now_fix ();
  393.         }
  394.       break;
  395.  
  396.     case state_saw_loc4:
  397.       d->state = state_wait_loc4;
  398.       if (*pnbytes != 4)
  399.         break;
  400.       if (exp->X_op == O_constant)
  401.         {
  402.           /* This is a case which we can optimize.  The two symbols being
  403.              subtracted were in the same frag and the expression was
  404.              reduced to a constant.  We can do the optimization entirely
  405.              in this function.  */
  406.           if (exp->X_add_number < 0x40)
  407.             {
  408.               d->loc4_frag->fr_literal[d->loc4_fix]
  409.                 = DW_CFA_advance_loc | exp->X_add_number;
  410.               /* No more bytes needed.  */
  411.               return 1;
  412.             }
  413.           else if (exp->X_add_number < 0x100)
  414.             {
  415.               d->loc4_frag->fr_literal[d->loc4_fix] = DW_CFA_advance_loc1;
  416.               *pnbytes = 1;
  417.             }
  418.           else if (exp->X_add_number < 0x10000)
  419.             {
  420.               d->loc4_frag->fr_literal[d->loc4_fix] = DW_CFA_advance_loc2;
  421.               *pnbytes = 2;
  422.             }
  423.         }
  424.       else if (exp->X_op == O_subtract && d->cie_info.code_alignment == 1)
  425.         {
  426.           /* This is a case we can optimize.  The expression was not
  427.              reduced, so we can not finish the optimization until the end
  428.              of the assembly.  We set up a variant frag which we handle
  429.              later.  */
  430.           frag_var (rs_cfa, 4, 0, 1 << 3, make_expr_symbol (exp),
  431.                     d->loc4_fix, (char *) d->loc4_frag);
  432.           return 1;
  433.         }
  434.       else if ((exp->X_op == O_divide
  435.                 || exp->X_op == O_right_shift)
  436.                && d->cie_info.code_alignment > 1)
  437.         {
  438.           if (exp->X_add_symbol->bsym
  439.               && exp->X_op_symbol->bsym
  440.               && exp->X_add_symbol->sy_value.X_op == O_subtract
  441.               && exp->X_op_symbol->sy_value.X_op == O_constant
  442.               && ((exp->X_op == O_divide
  443.                    ? exp->X_op_symbol->sy_value.X_add_number
  444.                    : (offsetT) 1 << exp->X_op_symbol->sy_value.X_add_number)
  445.                   == (offsetT) d->cie_info.code_alignment))
  446.             {
  447.               /* This is a case we can optimize as well.  The expression was
  448.                  not reduced, so we can not finish the optimization until the
  449.                  end of the assembly.  We set up a variant frag which we
  450.                  handle later.  */
  451.               frag_var (rs_cfa, 4, 0, d->cie_info.code_alignment << 3,
  452.                         make_expr_symbol (&exp->X_add_symbol->sy_value),
  453.                         d->loc4_fix, (char *) d->loc4_frag);
  454.               return 1;
  455.             }
  456.         }
  457.       break;
  458.  
  459.     case state_error:
  460.       /* Just skipping everything.  */
  461.       break;
  462.     }
  463.  
  464.   return 0;
  465. }
  466.  
  467. /* The function estimates the size of a rs_cfa variant frag based on
  468.    the current values of the symbols.  It is called before the
  469.    relaxation loop.  We set fr_subtype{0:2} to the expected length.  */
  470.  
  471. int
  472. eh_frame_estimate_size_before_relax (fragS *frag)
  473. {
  474.   offsetT diff;
  475.   int ca = frag->fr_subtype >> 3;
  476.   int ret;
  477.  
  478.   diff = resolve_symbol_value (frag->fr_symbol);
  479.  
  480.   gas_assert (ca > 0);
  481.   diff /= ca;
  482.   if (diff < 0x40)
  483.     ret = 0;
  484.   else if (diff < 0x100)
  485.     ret = 1;
  486.   else if (diff < 0x10000)
  487.     ret = 2;
  488.   else
  489.     ret = 4;
  490.  
  491.   frag->fr_subtype = (frag->fr_subtype & ~7) | ret;
  492.  
  493.   return ret;
  494. }
  495.  
  496. /* This function relaxes a rs_cfa variant frag based on the current
  497.    values of the symbols.  fr_subtype{0:2} is the current length of
  498.    the frag.  This returns the change in frag length.  */
  499.  
  500. int
  501. eh_frame_relax_frag (fragS *frag)
  502. {
  503.   int oldsize, newsize;
  504.  
  505.   oldsize = frag->fr_subtype & 7;
  506.   newsize = eh_frame_estimate_size_before_relax (frag);
  507.   return newsize - oldsize;
  508. }
  509.  
  510. /* This function converts a rs_cfa variant frag into a normal fill
  511.    frag.  This is called after all relaxation has been done.
  512.    fr_subtype{0:2} will be the desired length of the frag.  */
  513.  
  514. void
  515. eh_frame_convert_frag (fragS *frag)
  516. {
  517.   offsetT diff;
  518.   fragS *loc4_frag;
  519.   int loc4_fix, ca;
  520.  
  521.   loc4_frag = (fragS *) frag->fr_opcode;
  522.   loc4_fix = (int) frag->fr_offset;
  523.  
  524.   diff = resolve_symbol_value (frag->fr_symbol);
  525.  
  526.   ca = frag->fr_subtype >> 3;
  527.   gas_assert (ca > 0);
  528.   diff /= ca;
  529.   switch (frag->fr_subtype & 7)
  530.     {
  531.     case 0:
  532.       gas_assert (diff < 0x40);
  533.       loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc | diff;
  534.       break;
  535.  
  536.     case 1:
  537.       gas_assert (diff < 0x100);
  538.       loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc1;
  539.       frag->fr_literal[frag->fr_fix] = diff;
  540.       break;
  541.  
  542.     case 2:
  543.       gas_assert (diff < 0x10000);
  544.       loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc2;
  545.       md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 2);
  546.       break;
  547.  
  548.     default:
  549.       md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 4);
  550.       break;
  551.     }
  552.  
  553.   frag->fr_fix += frag->fr_subtype & 7;
  554.   frag->fr_type = rs_fill;
  555.   frag->fr_subtype = 0;
  556.   frag->fr_offset = 0;
  557. }
  558.