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