Subversion Repositories Kolibri OS

Rev

Rev 5222 | Blame | Compare with Previous | Last modification | View Log | RSS feed

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