xref: /netbsd-src/external/gpl3/binutils/dist/gas/ehopt.c (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
1 /* ehopt.c--optimize gcc exception frame information.
2    Copyright (C) 1998-2024 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 
25 /* We include this ELF file, even though we may not be assembling for
26    ELF, since the exception frame information is always in a format
27    derived from DWARF.  */
28 
29 #include "dwarf2.h"
30 
31 /* Try to optimize gcc 2.8 exception frame information.
32 
33    Exception frame information is emitted for every function in the
34    .eh_frame or .debug_frame sections.  Simple information for a function
35    with no exceptions looks like this:
36 
37 __FRAME_BEGIN__:
38 	.4byte	.LLCIE1	/ Length of Common Information Entry
39 .LSCIE1:
40 #if .eh_frame
41 	.4byte	0x0	/ CIE Identifier Tag
42 #elif .debug_frame
43 	.4byte	0xffffffff / CIE Identifier Tag
44 #endif
45 	.byte	0x1	/ CIE Version
46 	.byte	0x0	/ CIE Augmentation (none)
47 	.byte	0x1	/ ULEB128 0x1 (CIE Code Alignment Factor)
48 	.byte	0x7c	/ SLEB128 -4 (CIE Data Alignment Factor)
49 	.byte	0x8	/ CIE RA Column
50 	.byte	0xc	/ DW_CFA_def_cfa
51 	.byte	0x4	/ ULEB128 0x4
52 	.byte	0x4	/ ULEB128 0x4
53 	.byte	0x88	/ DW_CFA_offset, column 0x8
54 	.byte	0x1	/ ULEB128 0x1
55 	.align 4
56 .LECIE1:
57 	.set	.LLCIE1,.LECIE1-.LSCIE1	/ CIE Length Symbol
58 	.4byte	.LLFDE1	/ FDE Length
59 .LSFDE1:
60 	.4byte	.LSFDE1-__FRAME_BEGIN__	/ FDE CIE offset
61 	.4byte	.LFB1	/ FDE initial location
62 	.4byte	.LFE1-.LFB1	/ FDE address range
63 	.byte	0x4	/ DW_CFA_advance_loc4
64 	.4byte	.LCFI0-.LFB1
65 	.byte	0xe	/ DW_CFA_def_cfa_offset
66 	.byte	0x8	/ ULEB128 0x8
67 	.byte	0x85	/ DW_CFA_offset, column 0x5
68 	.byte	0x2	/ ULEB128 0x2
69 	.byte	0x4	/ DW_CFA_advance_loc4
70 	.4byte	.LCFI1-.LCFI0
71 	.byte	0xd	/ DW_CFA_def_cfa_register
72 	.byte	0x5	/ ULEB128 0x5
73 	.byte	0x4	/ DW_CFA_advance_loc4
74 	.4byte	.LCFI2-.LCFI1
75 	.byte	0x2e	/ DW_CFA_GNU_args_size
76 	.byte	0x4	/ ULEB128 0x4
77 	.byte	0x4	/ DW_CFA_advance_loc4
78 	.4byte	.LCFI3-.LCFI2
79 	.byte	0x2e	/ DW_CFA_GNU_args_size
80 	.byte	0x0	/ ULEB128 0x0
81 	.align 4
82 .LEFDE1:
83 	.set	.LLFDE1,.LEFDE1-.LSFDE1	/ FDE Length Symbol
84 
85    The immediate issue we can address in the assembler is the
86    DW_CFA_advance_loc4 followed by a four byte value.  The value is
87    the difference of two addresses in the function.  Since gcc does
88    not know this value, it always uses four bytes.  We will know the
89    value at the end of assembly, so we can do better.  */
90 
91 struct cie_info
92 {
93   unsigned code_alignment;
94   int z_augmentation;
95 };
96 
97 /* Extract information from the CIE.  */
98 
99 static int
get_cie_info(struct cie_info * info)100 get_cie_info (struct cie_info *info)
101 {
102   fragS *f;
103   fixS *fix;
104   unsigned int offset;
105   char CIE_id;
106   char augmentation[10];
107   int iaug;
108   int code_alignment = 0;
109 
110   /* We should find the CIE at the start of the section.  */
111 
112   f = seg_info (now_seg)->frchainP->frch_root;
113   fix = seg_info (now_seg)->frchainP->fix_root;
114 
115   /* Look through the frags of the section to find the code alignment.  */
116 
117   /* First make sure that the CIE Identifier Tag is 0/-1.  */
118 
119   if (startswith (segment_name (now_seg), ".debug_frame"))
120     CIE_id = (char)0xff;
121   else
122     CIE_id = 0;
123 
124   offset = 4;
125   while (f != NULL && offset >= f->fr_fix)
126     {
127       offset -= f->fr_fix;
128       f = f->fr_next;
129     }
130   if (f == NULL
131       || f->fr_fix - offset < 4
132       || f->fr_literal[offset] != CIE_id
133       || f->fr_literal[offset + 1] != CIE_id
134       || f->fr_literal[offset + 2] != CIE_id
135       || f->fr_literal[offset + 3] != CIE_id)
136     return 0;
137 
138   /* Next make sure the CIE version number is 1.  */
139 
140   offset += 4;
141   while (f != NULL && offset >= f->fr_fix)
142     {
143       offset -= f->fr_fix;
144       f = f->fr_next;
145     }
146   if (f == NULL
147       || f->fr_fix - offset < 1
148       || f->fr_literal[offset] != 1)
149     return 0;
150 
151   /* Skip the augmentation (a null terminated string).  */
152 
153   iaug = 0;
154   ++offset;
155   while (1)
156     {
157       while (f != NULL && offset >= f->fr_fix)
158 	{
159 	  offset -= f->fr_fix;
160 	  f = f->fr_next;
161 	}
162       if (f == NULL)
163 	return 0;
164 
165       while (offset < f->fr_fix && f->fr_literal[offset] != '\0')
166 	{
167 	  if ((size_t) iaug < (sizeof augmentation) - 1)
168 	    {
169 	      augmentation[iaug] = f->fr_literal[offset];
170 	      ++iaug;
171 	    }
172 	  ++offset;
173 	}
174       if (offset < f->fr_fix)
175 	break;
176     }
177   ++offset;
178   while (f != NULL && offset >= f->fr_fix)
179     {
180       offset -= f->fr_fix;
181       f = f->fr_next;
182     }
183   if (f == NULL)
184     return 0;
185 
186   augmentation[iaug] = '\0';
187   if (augmentation[0] == '\0')
188     {
189       /* No augmentation.  */
190     }
191   else if (strcmp (augmentation, "eh") == 0)
192     {
193       /* We have to skip a pointer.  Unfortunately, we don't know how
194 	 large it is.  We find out by looking for a matching fixup.  */
195       while (fix != NULL
196 	     && (fix->fx_frag != f || fix->fx_where != offset))
197 	fix = fix->fx_next;
198       if (fix == NULL)
199 	offset += 4;
200       else
201 	offset += fix->fx_size;
202       while (f != NULL && offset >= f->fr_fix)
203 	{
204 	  offset -= f->fr_fix;
205 	  f = f->fr_next;
206 	}
207       if (f == NULL)
208 	return 0;
209     }
210   else if (augmentation[0] != 'z')
211     return 0;
212 
213   /* We're now at the code alignment factor, which is a ULEB128.  If
214      it isn't a single byte, forget it.  */
215 
216   code_alignment = f->fr_literal[offset] & 0xff;
217   if ((code_alignment & 0x80) != 0)
218     code_alignment = 0;
219 
220   info->code_alignment = code_alignment;
221   info->z_augmentation = (augmentation[0] == 'z');
222 
223   return 1;
224 }
225 
226 enum frame_state
227 {
228   state_idle,
229   state_saw_size,
230   state_saw_cie_offset,
231   state_saw_pc_begin,
232   state_seeing_aug_size,
233   state_skipping_aug,
234   state_wait_loc4,
235   state_saw_loc4,
236   state_error,
237 };
238 
239 struct frame_data
240 {
241   enum frame_state state;
242 
243   int cie_info_ok;
244   struct cie_info cie_info;
245 
246   symbolS *size_end_sym;
247   fragS *loc4_frag;
248   int loc4_fix;
249 
250   int aug_size;
251   int aug_shift;
252 };
253 
254 static struct eh_state
255 {
256   struct frame_data eh_data;
257   struct frame_data debug_data;
258 } frame;
259 
260 /* This function is called from emit_expr.  It looks for cases which
261    we can optimize.
262 
263    Rather than try to parse all this information as we read it, we
264    look for a single byte DW_CFA_advance_loc4 followed by a 4 byte
265    difference.  We turn that into a rs_cfa_advance frag, and handle
266    those frags at the end of the assembly.  If the gcc output changes
267    somewhat, this optimization may stop working.
268 
269    This function returns non-zero if it handled the expression and
270    emit_expr should not do anything, or zero otherwise.  It can also
271    change *EXP and *PNBYTES.  */
272 
273 int
check_eh_frame(expressionS * exp,unsigned int * pnbytes)274 check_eh_frame (expressionS *exp, unsigned int *pnbytes)
275 {
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 (startswith (segment_name (now_seg), ".eh_frame")
289       && segment_name (now_seg)[9] != '_')
290     d = &frame.eh_data;
291   else if (startswith (segment_name (now_seg), ".debug_frame"))
292     d = &frame.debug_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 + 4);
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 (symbol_symbolS (exp->X_add_symbol)
439 	      && symbol_constant_p (exp->X_op_symbol)
440 	      && S_GET_SEGMENT (exp->X_op_symbol) == absolute_section
441 	      && ((exp->X_op == O_divide
442 		   ? *symbol_X_add_number (exp->X_op_symbol)
443 		   : (offsetT) 1 << *symbol_X_add_number (exp->X_op_symbol))
444 		  == (offsetT) d->cie_info.code_alignment))
445 	    {
446 	      expressionS *symval;
447 
448 	      symval = symbol_get_value_expression (exp->X_add_symbol);
449 	      if (symval->X_op == O_subtract)
450 		{
451 		  /* This is a case we can optimize as well.  The
452 		     expression was not reduced, so we can not finish
453 		     the optimization until the end of the assembly.
454 		     We set up a variant frag which we handle later.  */
455 		  frag_var (rs_cfa, 4, 0, d->cie_info.code_alignment << 3,
456 			    make_expr_symbol (symval),
457 			    d->loc4_fix, (char *) d->loc4_frag);
458 		  return 1;
459 		}
460 	    }
461 	}
462       break;
463 
464     case state_error:
465       /* Just skipping everything.  */
466       break;
467     }
468 
469   return 0;
470 }
471 
472 /* The function estimates the size of a rs_cfa variant frag based on
473    the current values of the symbols.  It is called before the
474    relaxation loop.  We set fr_subtype{0:2} to the expected length.  */
475 
476 int
eh_frame_estimate_size_before_relax(fragS * frag)477 eh_frame_estimate_size_before_relax (fragS *frag)
478 {
479   offsetT diff;
480   int ca = frag->fr_subtype >> 3;
481   int ret;
482 
483   diff = resolve_symbol_value (frag->fr_symbol);
484 
485   gas_assert (ca > 0);
486   diff /= ca;
487   if (diff == 0)
488     ret = -1;
489   else if (diff < 0x40)
490     ret = 0;
491   else if (diff < 0x100)
492     ret = 1;
493   else if (diff < 0x10000)
494     ret = 2;
495   else
496     ret = 4;
497 
498   frag->fr_subtype = (frag->fr_subtype & ~7) | (ret & 7);
499 
500   return ret;
501 }
502 
503 /* This function relaxes a rs_cfa variant frag based on the current
504    values of the symbols.  fr_subtype{0:2} is the current length of
505    the frag.  This returns the change in frag length.  */
506 
507 int
eh_frame_relax_frag(fragS * frag)508 eh_frame_relax_frag (fragS *frag)
509 {
510   int oldsize, newsize;
511 
512   oldsize = frag->fr_subtype & 7;
513   if (oldsize == 7)
514     oldsize = -1;
515   newsize = eh_frame_estimate_size_before_relax (frag);
516   return newsize - oldsize;
517 }
518 
519 /* This function converts a rs_cfa variant frag into a normal fill
520    frag.  This is called after all relaxation has been done.
521    fr_subtype{0:2} will be the desired length of the frag.  */
522 
523 void
eh_frame_convert_frag(fragS * frag)524 eh_frame_convert_frag (fragS *frag)
525 {
526   offsetT diff;
527   fragS *loc4_frag;
528   int loc4_fix, ca;
529 
530   loc4_frag = (fragS *) frag->fr_opcode;
531   loc4_fix = (int) frag->fr_offset;
532 
533   diff = resolve_symbol_value (frag->fr_symbol);
534 
535   ca = frag->fr_subtype >> 3;
536   gas_assert (ca > 0);
537   diff /= ca;
538   switch (frag->fr_subtype & 7)
539     {
540     case 0:
541       gas_assert (diff < 0x40);
542       loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc | diff;
543       break;
544 
545     case 1:
546       gas_assert (diff < 0x100);
547       loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc1;
548       frag->fr_literal[frag->fr_fix] = diff;
549       break;
550 
551     case 2:
552       gas_assert (diff < 0x10000);
553       loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc2;
554       md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 2);
555       break;
556 
557     case 4:
558       md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 4);
559       break;
560 
561     case 7:
562       gas_assert (diff == 0);
563       frag->fr_fix -= 8;
564       break;
565 
566     default:
567       abort ();
568     }
569 
570   frag->fr_fix += frag->fr_subtype & 7;
571   frag->fr_type = rs_fill;
572   frag->fr_subtype = 0;
573   frag->fr_offset = 0;
574 }
575 
576 void
eh_begin(void)577 eh_begin (void)
578 {
579   memset (&frame, 0, sizeof (frame));
580 }
581