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