Back to index

cell-binutils  2.17cvs20070401
ehopt.c
Go to the documentation of this file.
00001 /* ehopt.c--optimize gcc exception frame information.
00002    Copyright 1998, 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
00003    Written by Ian Lance Taylor <ian@cygnus.com>.
00004 
00005 This file is part of GAS, the GNU Assembler.
00006 
00007 GAS is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2, or (at your option)
00010 any later version.
00011 
00012 GAS is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with GAS; see the file COPYING.  If not, write to the Free
00019 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
00020 02110-1301, USA.  */
00021 
00022 #include "as.h"
00023 #include "subsegs.h"
00024 
00025 /* We include this ELF file, even though we may not be assembling for
00026    ELF, since the exception frame information is always in a format
00027    derived from DWARF.  */
00028 
00029 #include "elf/dwarf2.h"
00030 
00031 /* Try to optimize gcc 2.8 exception frame information.
00032 
00033    Exception frame information is emitted for every function in the
00034    .eh_frame or .debug_frame sections.  Simple information for a function
00035    with no exceptions looks like this:
00036 
00037 __FRAME_BEGIN__:
00038        .4byte .LLCIE1       / Length of Common Information Entry
00039 .LSCIE1:
00040 #if .eh_frame
00041        .4byte 0x0    / CIE Identifier Tag
00042 #elif .debug_frame
00043        .4byte 0xffffffff / CIE Identifier Tag
00044 #endif
00045        .byte  0x1    / CIE Version
00046        .byte  0x0    / CIE Augmentation (none)
00047        .byte  0x1    / ULEB128 0x1 (CIE Code Alignment Factor)
00048        .byte  0x7c   / SLEB128 -4 (CIE Data Alignment Factor)
00049        .byte  0x8    / CIE RA Column
00050        .byte  0xc    / DW_CFA_def_cfa
00051        .byte  0x4    / ULEB128 0x4
00052        .byte  0x4    / ULEB128 0x4
00053        .byte  0x88   / DW_CFA_offset, column 0x8
00054        .byte  0x1    / ULEB128 0x1
00055        .align 4
00056 .LECIE1:
00057        .set   .LLCIE1,.LECIE1-.LSCIE1     / CIE Length Symbol
00058        .4byte .LLFDE1       / FDE Length
00059 .LSFDE1:
00060        .4byte .LSFDE1-__FRAME_BEGIN__     / FDE CIE offset
00061        .4byte .LFB1  / FDE initial location
00062        .4byte .LFE1-.LFB1   / FDE address range
00063        .byte  0x4    / DW_CFA_advance_loc4
00064        .4byte .LCFI0-.LFB1
00065        .byte  0xe    / DW_CFA_def_cfa_offset
00066        .byte  0x8    / ULEB128 0x8
00067        .byte  0x85   / DW_CFA_offset, column 0x5
00068        .byte  0x2    / ULEB128 0x2
00069        .byte  0x4    / DW_CFA_advance_loc4
00070        .4byte .LCFI1-.LCFI0
00071        .byte  0xd    / DW_CFA_def_cfa_register
00072        .byte  0x5    / ULEB128 0x5
00073        .byte  0x4    / DW_CFA_advance_loc4
00074        .4byte .LCFI2-.LCFI1
00075        .byte  0x2e   / DW_CFA_GNU_args_size
00076        .byte  0x4    / ULEB128 0x4
00077        .byte  0x4    / DW_CFA_advance_loc4
00078        .4byte .LCFI3-.LCFI2
00079        .byte  0x2e   / DW_CFA_GNU_args_size
00080        .byte  0x0    / ULEB128 0x0
00081        .align 4
00082 .LEFDE1:
00083        .set   .LLFDE1,.LEFDE1-.LSFDE1     / FDE Length Symbol
00084 
00085    The immediate issue we can address in the assembler is the
00086    DW_CFA_advance_loc4 followed by a four byte value.  The value is
00087    the difference of two addresses in the function.  Since gcc does
00088    not know this value, it always uses four bytes.  We will know the
00089    value at the end of assembly, so we can do better.  */
00090 
00091 struct cie_info
00092 {
00093   unsigned code_alignment;
00094   int z_augmentation;
00095 };
00096 
00097 static int get_cie_info (struct cie_info *);
00098 
00099 /* Extract information from the CIE.  */
00100 
00101 static int
00102 get_cie_info (struct cie_info *info)
00103 {
00104   fragS *f;
00105   fixS *fix;
00106   int offset;
00107   char CIE_id;
00108   char augmentation[10];
00109   int iaug;
00110   int code_alignment = 0;
00111 
00112   /* We should find the CIE at the start of the section.  */
00113 
00114   f = seg_info (now_seg)->frchainP->frch_root;
00115   fix = seg_info (now_seg)->frchainP->fix_root;
00116 
00117   /* Look through the frags of the section to find the code alignment.  */
00118 
00119   /* First make sure that the CIE Identifier Tag is 0/-1.  */
00120 
00121   if (strcmp (segment_name (now_seg), ".debug_frame") == 0)
00122     CIE_id = (char)0xff;
00123   else
00124     CIE_id = 0;
00125 
00126   offset = 4;
00127   while (f != NULL && offset >= f->fr_fix)
00128     {
00129       offset -= f->fr_fix;
00130       f = f->fr_next;
00131     }
00132   if (f == NULL
00133       || f->fr_fix - offset < 4
00134       || f->fr_literal[offset] != CIE_id
00135       || f->fr_literal[offset + 1] != CIE_id
00136       || f->fr_literal[offset + 2] != CIE_id
00137       || f->fr_literal[offset + 3] != CIE_id)
00138     return 0;
00139 
00140   /* Next make sure the CIE version number is 1.  */
00141 
00142   offset += 4;
00143   while (f != NULL && offset >= f->fr_fix)
00144     {
00145       offset -= f->fr_fix;
00146       f = f->fr_next;
00147     }
00148   if (f == NULL
00149       || f->fr_fix - offset < 1
00150       || f->fr_literal[offset] != 1)
00151     return 0;
00152 
00153   /* Skip the augmentation (a null terminated string).  */
00154 
00155   iaug = 0;
00156   ++offset;
00157   while (1)
00158     {
00159       while (f != NULL && offset >= f->fr_fix)
00160        {
00161          offset -= f->fr_fix;
00162          f = f->fr_next;
00163        }
00164       if (f == NULL)
00165        return 0;
00166 
00167       while (offset < f->fr_fix && f->fr_literal[offset] != '\0')
00168        {
00169          if ((size_t) iaug < (sizeof augmentation) - 1)
00170            {
00171              augmentation[iaug] = f->fr_literal[offset];
00172              ++iaug;
00173            }
00174          ++offset;
00175        }
00176       if (offset < f->fr_fix)
00177        break;
00178     }
00179   ++offset;
00180   while (f != NULL && offset >= f->fr_fix)
00181     {
00182       offset -= f->fr_fix;
00183       f = f->fr_next;
00184     }
00185   if (f == NULL)
00186     return 0;
00187 
00188   augmentation[iaug] = '\0';
00189   if (augmentation[0] == '\0')
00190     {
00191       /* No augmentation.  */
00192     }
00193   else if (strcmp (augmentation, "eh") == 0)
00194     {
00195       /* We have to skip a pointer.  Unfortunately, we don't know how
00196         large it is.  We find out by looking for a matching fixup.  */
00197       while (fix != NULL
00198             && (fix->fx_frag != f || fix->fx_where != offset))
00199        fix = fix->fx_next;
00200       if (fix == NULL)
00201        offset += 4;
00202       else
00203        offset += fix->fx_size;
00204       while (f != NULL && offset >= f->fr_fix)
00205        {
00206          offset -= f->fr_fix;
00207          f = f->fr_next;
00208        }
00209       if (f == NULL)
00210        return 0;
00211     }
00212   else if (augmentation[0] != 'z')
00213     return 0;
00214 
00215   /* We're now at the code alignment factor, which is a ULEB128.  If
00216      it isn't a single byte, forget it.  */
00217 
00218   code_alignment = f->fr_literal[offset] & 0xff;
00219   if ((code_alignment & 0x80) != 0)
00220     code_alignment = 0;
00221 
00222   info->code_alignment = code_alignment;
00223   info->z_augmentation = (augmentation[0] == 'z');
00224 
00225   return 1;
00226 }
00227 
00228 /* This function is called from emit_expr.  It looks for cases which
00229    we can optimize.
00230 
00231    Rather than try to parse all this information as we read it, we
00232    look for a single byte DW_CFA_advance_loc4 followed by a 4 byte
00233    difference.  We turn that into a rs_cfa_advance frag, and handle
00234    those frags at the end of the assembly.  If the gcc output changes
00235    somewhat, this optimization may stop working.
00236 
00237    This function returns non-zero if it handled the expression and
00238    emit_expr should not do anything, or zero otherwise.  It can also
00239    change *EXP and *PNBYTES.  */
00240 
00241 int
00242 check_eh_frame (expressionS *exp, unsigned int *pnbytes)
00243 {
00244   struct frame_data
00245   {
00246     enum frame_state
00247     {
00248       state_idle,
00249       state_saw_size,
00250       state_saw_cie_offset,
00251       state_saw_pc_begin,
00252       state_seeing_aug_size,
00253       state_skipping_aug,
00254       state_wait_loc4,
00255       state_saw_loc4,
00256       state_error,
00257     } state;
00258 
00259     int cie_info_ok;
00260     struct cie_info cie_info;
00261 
00262     symbolS *size_end_sym;
00263     fragS *loc4_frag;
00264     int loc4_fix;
00265 
00266     int aug_size;
00267     int aug_shift;
00268   };
00269 
00270   static struct frame_data eh_frame_data;
00271   static struct frame_data debug_frame_data;
00272   struct frame_data *d;
00273 
00274   /* Don't optimize.  */
00275   if (flag_traditional_format)
00276     return 0;
00277 
00278   /* Select the proper section data.  */
00279   if (strcmp (segment_name (now_seg), ".eh_frame") == 0)
00280     d = &eh_frame_data;
00281   else if (strcmp (segment_name (now_seg), ".debug_frame") == 0)
00282     d = &debug_frame_data;
00283   else
00284     return 0;
00285 
00286   if (d->state >= state_saw_size && S_IS_DEFINED (d->size_end_sym))
00287     {
00288       /* We have come to the end of the CIE or FDE.  See below where
00289          we set saw_size.  We must check this first because we may now
00290          be looking at the next size.  */
00291       d->state = state_idle;
00292     }
00293 
00294   switch (d->state)
00295     {
00296     case state_idle:
00297       if (*pnbytes == 4)
00298        {
00299          /* This might be the size of the CIE or FDE.  We want to know
00300             the size so that we don't accidentally optimize across an FDE
00301             boundary.  We recognize the size in one of two forms: a
00302             symbol which will later be defined as a difference, or a
00303             subtraction of two symbols.  Either way, we can tell when we
00304             are at the end of the FDE because the symbol becomes defined
00305             (in the case of a subtraction, the end symbol, from which the
00306             start symbol is being subtracted).  Other ways of describing
00307             the size will not be optimized.  */
00308          if ((exp->X_op == O_symbol || exp->X_op == O_subtract)
00309              && ! S_IS_DEFINED (exp->X_add_symbol))
00310            {
00311              d->state = state_saw_size;
00312              d->size_end_sym = exp->X_add_symbol;
00313            }
00314        }
00315       break;
00316 
00317     case state_saw_size:
00318     case state_saw_cie_offset:
00319       /* Assume whatever form it appears in, it appears atomically.  */
00320       d->state += 1;
00321       break;
00322 
00323     case state_saw_pc_begin:
00324       /* Decide whether we should see an augmentation.  */
00325       if (! d->cie_info_ok
00326          && ! (d->cie_info_ok = get_cie_info (&d->cie_info)))
00327        d->state = state_error;
00328       else if (d->cie_info.z_augmentation)
00329        {
00330          d->state = state_seeing_aug_size;
00331          d->aug_size = 0;
00332          d->aug_shift = 0;
00333        }
00334       else
00335        d->state = state_wait_loc4;
00336       break;
00337 
00338     case state_seeing_aug_size:
00339       /* Bytes == -1 means this comes from an leb128 directive.  */
00340       if ((int)*pnbytes == -1 && exp->X_op == O_constant)
00341        {
00342          d->aug_size = exp->X_add_number;
00343          d->state = state_skipping_aug;
00344        }
00345       else if (*pnbytes == 1 && exp->X_op == O_constant)
00346        {
00347          unsigned char byte = exp->X_add_number;
00348          d->aug_size |= (byte & 0x7f) << d->aug_shift;
00349          d->aug_shift += 7;
00350          if ((byte & 0x80) == 0)
00351            d->state = state_skipping_aug;
00352        }
00353       else
00354        d->state = state_error;
00355       if (d->state == state_skipping_aug && d->aug_size == 0)
00356        d->state = state_wait_loc4;
00357       break;
00358 
00359     case state_skipping_aug:
00360       if ((int)*pnbytes < 0)
00361        d->state = state_error;
00362       else
00363        {
00364          int left = (d->aug_size -= *pnbytes);
00365          if (left == 0)
00366            d->state = state_wait_loc4;
00367          else if (left < 0)
00368            d->state = state_error;
00369        }
00370       break;
00371 
00372     case state_wait_loc4:
00373       if (*pnbytes == 1
00374          && exp->X_op == O_constant
00375          && exp->X_add_number == DW_CFA_advance_loc4)
00376        {
00377          /* This might be a DW_CFA_advance_loc4.  Record the frag and the
00378             position within the frag, so that we can change it later.  */
00379          frag_grow (1);
00380          d->state = state_saw_loc4;
00381          d->loc4_frag = frag_now;
00382          d->loc4_fix = frag_now_fix ();
00383        }
00384       break;
00385 
00386     case state_saw_loc4:
00387       d->state = state_wait_loc4;
00388       if (*pnbytes != 4)
00389        break;
00390       if (exp->X_op == O_constant)
00391        {
00392          /* This is a case which we can optimize.  The two symbols being
00393             subtracted were in the same frag and the expression was
00394             reduced to a constant.  We can do the optimization entirely
00395             in this function.  */
00396          if (d->cie_info.code_alignment > 0
00397              && exp->X_add_number % d->cie_info.code_alignment == 0
00398              && exp->X_add_number / d->cie_info.code_alignment < 0x40)
00399            {
00400              d->loc4_frag->fr_literal[d->loc4_fix]
00401               = DW_CFA_advance_loc
00402                 | (exp->X_add_number / d->cie_info.code_alignment);
00403              /* No more bytes needed.  */
00404              return 1;
00405            }
00406          else if (exp->X_add_number < 0x100)
00407            {
00408              d->loc4_frag->fr_literal[d->loc4_fix] = DW_CFA_advance_loc1;
00409              *pnbytes = 1;
00410            }
00411          else if (exp->X_add_number < 0x10000)
00412            {
00413              d->loc4_frag->fr_literal[d->loc4_fix] = DW_CFA_advance_loc2;
00414              *pnbytes = 2;
00415            }
00416        }
00417       else if (exp->X_op == O_subtract)
00418        {
00419          /* This is a case we can optimize.  The expression was not
00420             reduced, so we can not finish the optimization until the end
00421             of the assembly.  We set up a variant frag which we handle
00422             later.  */
00423          int fr_subtype;
00424 
00425          if (d->cie_info.code_alignment > 0)
00426            fr_subtype = d->cie_info.code_alignment << 3;
00427          else
00428            fr_subtype = 0;
00429 
00430          frag_var (rs_cfa, 4, 0, fr_subtype, make_expr_symbol (exp),
00431                   d->loc4_fix, (char *) d->loc4_frag);
00432          return 1;
00433        }
00434       break;
00435 
00436     case state_error:
00437       /* Just skipping everything.  */
00438       break;
00439     }
00440 
00441   return 0;
00442 }
00443 
00444 /* The function estimates the size of a rs_cfa variant frag based on
00445    the current values of the symbols.  It is called before the
00446    relaxation loop.  We set fr_subtype{0:2} to the expected length.  */
00447 
00448 int
00449 eh_frame_estimate_size_before_relax (fragS *frag)
00450 {
00451   offsetT diff;
00452   int ca = frag->fr_subtype >> 3;
00453   int ret;
00454 
00455   diff = resolve_symbol_value (frag->fr_symbol);
00456 
00457   if (ca > 0 && diff % ca == 0 && diff / ca < 0x40)
00458     ret = 0;
00459   else if (diff < 0x100)
00460     ret = 1;
00461   else if (diff < 0x10000)
00462     ret = 2;
00463   else
00464     ret = 4;
00465 
00466   frag->fr_subtype = (frag->fr_subtype & ~7) | ret;
00467 
00468   return ret;
00469 }
00470 
00471 /* This function relaxes a rs_cfa variant frag based on the current
00472    values of the symbols.  fr_subtype{0:2} is the current length of
00473    the frag.  This returns the change in frag length.  */
00474 
00475 int
00476 eh_frame_relax_frag (fragS *frag)
00477 {
00478   int oldsize, newsize;
00479 
00480   oldsize = frag->fr_subtype & 7;
00481   newsize = eh_frame_estimate_size_before_relax (frag);
00482   return newsize - oldsize;
00483 }
00484 
00485 /* This function converts a rs_cfa variant frag into a normal fill
00486    frag.  This is called after all relaxation has been done.
00487    fr_subtype{0:2} will be the desired length of the frag.  */
00488 
00489 void
00490 eh_frame_convert_frag (fragS *frag)
00491 {
00492   offsetT diff;
00493   fragS *loc4_frag;
00494   int loc4_fix;
00495 
00496   loc4_frag = (fragS *) frag->fr_opcode;
00497   loc4_fix = (int) frag->fr_offset;
00498 
00499   diff = resolve_symbol_value (frag->fr_symbol);
00500 
00501   switch (frag->fr_subtype & 7)
00502     {
00503     case 0:
00504       {
00505        int ca = frag->fr_subtype >> 3;
00506        assert (ca > 0 && diff % ca == 0 && diff / ca < 0x40);
00507        loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc | (diff / ca);
00508       }
00509       break;
00510 
00511     case 1:
00512       assert (diff < 0x100);
00513       loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc1;
00514       frag->fr_literal[frag->fr_fix] = diff;
00515       break;
00516 
00517     case 2:
00518       assert (diff < 0x10000);
00519       loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc2;
00520       md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 2);
00521       break;
00522 
00523     default:
00524       md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 4);
00525       break;
00526     }
00527 
00528   frag->fr_fix += frag->fr_subtype & 7;
00529   frag->fr_type = rs_fill;
00530   frag->fr_subtype = 0;
00531   frag->fr_offset = 0;
00532 }