/src/binutils-gdb/gas/frags.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* frags.c - manage frags - |
2 | | Copyright (C) 1987-2023 Free Software Foundation, Inc. |
3 | | |
4 | | This file is part of GAS, the GNU Assembler. |
5 | | |
6 | | GAS is free software; you can redistribute it and/or modify |
7 | | it under the terms of the GNU General Public License as published by |
8 | | the Free Software Foundation; either version 3, or (at your option) |
9 | | any later version. |
10 | | |
11 | | GAS is distributed in the hope that it will be useful, |
12 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | GNU General Public License for more details. |
15 | | |
16 | | You should have received a copy of the GNU General Public License |
17 | | along with GAS; see the file COPYING. If not, write to the Free |
18 | | Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA |
19 | | 02110-1301, USA. */ |
20 | | |
21 | | #include "as.h" |
22 | | #include "subsegs.h" |
23 | | #include "obstack.h" |
24 | | |
25 | | extern fragS zero_address_frag; |
26 | | extern fragS predefined_address_frag; |
27 | | |
28 | | static int totalfrags; |
29 | | |
30 | | int |
31 | | get_frag_count (void) |
32 | 0 | { |
33 | 0 | return totalfrags; |
34 | 0 | } |
35 | | |
36 | | void |
37 | | clear_frag_count (void) |
38 | 0 | { |
39 | 0 | totalfrags = 0; |
40 | 0 | } |
41 | | |
42 | | /* Initialization for frag routines. */ |
43 | | |
44 | | void |
45 | | frag_init (void) |
46 | 1.15k | { |
47 | 1.15k | zero_address_frag.fr_type = rs_fill; |
48 | 1.15k | predefined_address_frag.fr_type = rs_fill; |
49 | 1.15k | } |
50 | | |
51 | | /* Check that we're not trying to assemble into a section that can't |
52 | | allocate frags (currently, this is only possible in the absolute |
53 | | section), or into an mri common. */ |
54 | | |
55 | | static void |
56 | | frag_alloc_check (const struct obstack *ob) |
57 | 10.0M | { |
58 | 10.0M | if (ob->chunk_size == 0) |
59 | 0 | { |
60 | 0 | as_bad (_("attempt to allocate data in absolute section")); |
61 | 0 | subseg_set (text_section, 0); |
62 | 0 | } |
63 | | |
64 | 10.0M | if (mri_common_symbol != NULL) |
65 | 0 | { |
66 | 0 | as_bad (_("attempt to allocate data in common section")); |
67 | 0 | mri_common_symbol = NULL; |
68 | 0 | } |
69 | 10.0M | } |
70 | | |
71 | | /* Allocate a frag on the specified obstack. |
72 | | Call this routine from everywhere else, so that all the weird alignment |
73 | | hackery can be done in just one place. */ |
74 | | |
75 | | fragS * |
76 | | frag_alloc (struct obstack *ob) |
77 | 227k | { |
78 | 227k | fragS *ptr; |
79 | 227k | int oalign; |
80 | | |
81 | 227k | (void) obstack_alloc (ob, 0); |
82 | 227k | oalign = obstack_alignment_mask (ob); |
83 | 227k | obstack_alignment_mask (ob) = 0; |
84 | 227k | ptr = (fragS *) obstack_alloc (ob, SIZEOF_STRUCT_FRAG); |
85 | 227k | obstack_alignment_mask (ob) = oalign; |
86 | 227k | memset (ptr, 0, SIZEOF_STRUCT_FRAG); |
87 | 227k | totalfrags++; |
88 | 227k | return ptr; |
89 | 227k | } |
90 | | |
91 | | /* Try to augment current frag by nchars chars. |
92 | | If there is no room, close off the current frag with a ".fill 0" |
93 | | and begin a new frag. Then loop until the new frag has at least |
94 | | nchars chars available. Does not set up any fields in frag_now. */ |
95 | | |
96 | | void |
97 | | frag_grow (size_t nchars) |
98 | 9.33M | { |
99 | 9.33M | if (obstack_room (&frchain_now->frch_obstack) < nchars) |
100 | 9.47k | { |
101 | 9.47k | size_t oldc; |
102 | 9.47k | size_t newc; |
103 | | |
104 | | /* Try to allocate a bit more than needed right now. But don't do |
105 | | this if we would waste too much memory. Especially necessary |
106 | | for extremely big (like 2GB initialized) frags. */ |
107 | 9.47k | if (nchars < 0x10000) |
108 | 9.38k | newc = 2 * nchars; |
109 | 81 | else |
110 | 81 | newc = nchars + 0x10000; |
111 | 9.47k | newc += SIZEOF_STRUCT_FRAG; |
112 | | |
113 | | /* Check for possible overflow. */ |
114 | 9.47k | if (newc < nchars) |
115 | 0 | as_fatal (ngettext ("can't extend frag %lu char", |
116 | 0 | "can't extend frag %lu chars", |
117 | 0 | (unsigned long) nchars), |
118 | 0 | (unsigned long) nchars); |
119 | | |
120 | | /* Force to allocate at least NEWC bytes, but not less than the |
121 | | default. */ |
122 | 9.47k | oldc = obstack_chunk_size (&frchain_now->frch_obstack); |
123 | 9.47k | if (newc > oldc) |
124 | 641 | obstack_chunk_size (&frchain_now->frch_obstack) = newc; |
125 | | |
126 | 60.4k | while (obstack_room (&frchain_now->frch_obstack) < nchars) |
127 | 50.9k | { |
128 | | /* Not enough room in this frag. Close it and start a new one. |
129 | | This must be done in a loop because the created frag may not |
130 | | be big enough if the current obstack chunk is used. */ |
131 | 50.9k | frag_wane (frag_now); |
132 | 50.9k | frag_new (0); |
133 | 50.9k | } |
134 | | |
135 | | /* Restore the old chunk size. */ |
136 | 9.47k | obstack_chunk_size (&frchain_now->frch_obstack) = oldc; |
137 | 9.47k | } |
138 | 9.33M | } |
139 | | |
140 | | /* Call this to close off a completed frag, and start up a new (empty) |
141 | | frag, in the same subsegment as the old frag. |
142 | | [frchain_now remains the same but frag_now is updated.] |
143 | | Because this calculates the correct value of fr_fix by |
144 | | looking at the obstack 'frags', it needs to know how many |
145 | | characters at the end of the old frag belong to the maximal |
146 | | variable part; The rest must belong to fr_fix. |
147 | | It doesn't actually set up the old frag's fr_var. You may have |
148 | | set fr_var == 1, but allocated 10 chars to the end of the frag; |
149 | | In this case you pass old_frags_var_max_size == 10. |
150 | | In fact, you may use fr_var for something totally unrelated to the |
151 | | size of the variable part of the frag; None of the generic frag |
152 | | handling code makes use of fr_var. |
153 | | |
154 | | Make a new frag, initialising some components. Link new frag at end |
155 | | of frchain_now. */ |
156 | | |
157 | | void |
158 | | frag_new (size_t old_frags_var_max_size |
159 | | /* Number of chars (already allocated on obstack frags) in |
160 | | variable_length part of frag. */) |
161 | 213k | { |
162 | 213k | fragS *former_last_fragP; |
163 | 213k | frchainS *frchP; |
164 | | |
165 | 213k | gas_assert (frchain_now->frch_last == frag_now); |
166 | | |
167 | | /* Fix up old frag's fr_fix. */ |
168 | 0 | frag_now->fr_fix = frag_now_fix_octets (); |
169 | 213k | gas_assert (frag_now->fr_fix >= old_frags_var_max_size |
170 | 213k | || now_seg == absolute_section); |
171 | 0 | frag_now->fr_fix -= old_frags_var_max_size; |
172 | | /* Make sure its type is valid. */ |
173 | 213k | gas_assert (frag_now->fr_type != 0); |
174 | | |
175 | | /* This will align the obstack so the next struct we allocate on it |
176 | | will begin at a correct boundary. */ |
177 | 213k | obstack_finish (&frchain_now->frch_obstack); |
178 | 213k | frchP = frchain_now; |
179 | 213k | know (frchP); |
180 | 0 | former_last_fragP = frchP->frch_last; |
181 | 213k | gas_assert (former_last_fragP != 0); |
182 | 213k | gas_assert (former_last_fragP == frag_now); |
183 | 0 | frag_now = frag_alloc (&frchP->frch_obstack); |
184 | | |
185 | 213k | frag_now->fr_file = as_where (&frag_now->fr_line); |
186 | | |
187 | | /* Generally, frag_now->points to an address rounded up to next |
188 | | alignment. However, characters will add to obstack frags |
189 | | IMMEDIATELY after the struct frag, even if they are not starting |
190 | | at an alignment address. */ |
191 | 213k | former_last_fragP->fr_next = frag_now; |
192 | 213k | frchP->frch_last = frag_now; |
193 | | |
194 | 213k | #ifndef NO_LISTING |
195 | 213k | { |
196 | 213k | extern struct list_info_struct *listing_tail; |
197 | 213k | frag_now->line = listing_tail; |
198 | 213k | } |
199 | 213k | #endif |
200 | | |
201 | 213k | gas_assert (frchain_now->frch_last == frag_now); |
202 | | |
203 | 0 | frag_now->fr_next = NULL; |
204 | 213k | } |
205 | | |
206 | | /* Start a new frag unless we have n more chars of room in the current frag. |
207 | | Close off the old frag with a .fill 0. |
208 | | |
209 | | Return the address of the 1st char to write into. Advance |
210 | | frag_now_growth past the new chars. */ |
211 | | |
212 | | char * |
213 | | frag_more (size_t nchars) |
214 | 9.05M | { |
215 | 9.05M | char *retval; |
216 | | |
217 | 9.05M | frag_alloc_check (&frchain_now->frch_obstack); |
218 | 9.05M | frag_grow (nchars); |
219 | 9.05M | retval = obstack_next_free (&frchain_now->frch_obstack); |
220 | 9.05M | obstack_blank_fast (&frchain_now->frch_obstack, nchars); |
221 | 9.05M | return retval; |
222 | 9.05M | } |
223 | | |
224 | | /* Close the current frag, setting its fields for a relaxable frag. Start a |
225 | | new frag. */ |
226 | | |
227 | | static void |
228 | | frag_var_init (relax_stateT type, size_t max_chars, size_t var, |
229 | | relax_substateT subtype, symbolS *symbol, offsetT offset, |
230 | | char *opcode) |
231 | 162k | { |
232 | 162k | frag_now->fr_var = var; |
233 | 162k | frag_now->fr_type = type; |
234 | 162k | frag_now->fr_subtype = subtype; |
235 | 162k | frag_now->fr_symbol = symbol; |
236 | 162k | frag_now->fr_offset = offset; |
237 | 162k | frag_now->fr_opcode = opcode; |
238 | | #ifdef USING_CGEN |
239 | | frag_now->fr_cgen.insn = 0; |
240 | | frag_now->fr_cgen.opindex = 0; |
241 | | frag_now->fr_cgen.opinfo = 0; |
242 | | #endif |
243 | 162k | #ifdef TC_FRAG_INIT |
244 | 162k | TC_FRAG_INIT (frag_now, max_chars); |
245 | 162k | #endif |
246 | 162k | frag_now->fr_file = as_where (&frag_now->fr_line); |
247 | | |
248 | 162k | frag_new (max_chars); |
249 | 162k | } |
250 | | |
251 | | /* Start a new frag unless we have max_chars more chars of room in the |
252 | | current frag. Close off the old frag with a .fill 0. |
253 | | |
254 | | Set up a machine_dependent relaxable frag, then start a new frag. |
255 | | Return the address of the 1st char of the var part of the old frag |
256 | | to write into. */ |
257 | | |
258 | | char * |
259 | | frag_var (relax_stateT type, size_t max_chars, size_t var, |
260 | | relax_substateT subtype, symbolS *symbol, offsetT offset, |
261 | | char *opcode) |
262 | 162k | { |
263 | 162k | char *retval; |
264 | | |
265 | 162k | frag_grow (max_chars); |
266 | 162k | retval = obstack_next_free (&frchain_now->frch_obstack); |
267 | 162k | obstack_blank_fast (&frchain_now->frch_obstack, max_chars); |
268 | 162k | frag_var_init (type, max_chars, var, subtype, symbol, offset, opcode); |
269 | 162k | return retval; |
270 | 162k | } |
271 | | |
272 | | /* OVE: This variant of frag_var assumes that space for the tail has been |
273 | | allocated by caller. |
274 | | No call to frag_grow is done. */ |
275 | | |
276 | | char * |
277 | | frag_variant (relax_stateT type, size_t max_chars, size_t var, |
278 | | relax_substateT subtype, symbolS *symbol, offsetT offset, |
279 | | char *opcode) |
280 | 0 | { |
281 | 0 | char *retval; |
282 | |
|
283 | 0 | retval = obstack_next_free (&frchain_now->frch_obstack); |
284 | 0 | frag_var_init (type, max_chars, var, subtype, symbol, offset, opcode); |
285 | |
|
286 | 0 | return retval; |
287 | 0 | } |
288 | | |
289 | | /* Reduce the variable end of a frag to a harmless state. */ |
290 | | |
291 | | void |
292 | | frag_wane (fragS *fragP) |
293 | 51.2k | { |
294 | 51.2k | fragP->fr_type = rs_fill; |
295 | 51.2k | fragP->fr_offset = 0; |
296 | 51.2k | fragP->fr_var = 0; |
297 | 51.2k | } |
298 | | |
299 | | /* Return the number of bytes by which the current frag can be grown. */ |
300 | | |
301 | | size_t |
302 | | frag_room (void) |
303 | 0 | { |
304 | 0 | return obstack_room (&frchain_now->frch_obstack); |
305 | 0 | } |
306 | | |
307 | | /* Make an alignment frag. The size of this frag will be adjusted to |
308 | | force the next frag to have the appropriate alignment. ALIGNMENT |
309 | | is the power of two to which to align. FILL_CHARACTER is the |
310 | | character to use to fill in any bytes which are skipped. MAX is |
311 | | the maximum number of characters to skip when doing the alignment, |
312 | | or 0 if there is no maximum. */ |
313 | | |
314 | | void |
315 | | frag_align (int alignment, int fill_character, int max) |
316 | 45.5k | { |
317 | 45.5k | if (now_seg == absolute_section) |
318 | 8.17k | { |
319 | 8.17k | addressT new_off; |
320 | 8.17k | addressT mask; |
321 | | |
322 | 8.17k | mask = (~(addressT) 0) << alignment; |
323 | 8.17k | new_off = (abs_section_offset + ~mask) & mask; |
324 | 8.17k | if (max == 0 || new_off - abs_section_offset <= (addressT) max) |
325 | 8.16k | abs_section_offset = new_off; |
326 | 8.17k | } |
327 | 37.4k | else |
328 | 37.4k | { |
329 | 37.4k | char *p; |
330 | | |
331 | 37.4k | p = frag_var (rs_align, 1, 1, (relax_substateT) max, |
332 | 37.4k | (symbolS *) 0, (offsetT) alignment, (char *) 0); |
333 | 37.4k | *p = fill_character; |
334 | 37.4k | } |
335 | 45.5k | } |
336 | | |
337 | | /* Make an alignment frag like frag_align, but fill with a repeating |
338 | | pattern rather than a single byte. ALIGNMENT is the power of two |
339 | | to which to align. FILL_PATTERN is the fill pattern to repeat in |
340 | | the bytes which are skipped. N_FILL is the number of bytes in |
341 | | FILL_PATTERN. MAX is the maximum number of characters to skip when |
342 | | doing the alignment, or 0 if there is no maximum. */ |
343 | | |
344 | | void |
345 | | frag_align_pattern (int alignment, const char *fill_pattern, |
346 | | size_t n_fill, int max) |
347 | 37 | { |
348 | 37 | char *p; |
349 | | |
350 | 37 | p = frag_var (rs_align, n_fill, n_fill, (relax_substateT) max, |
351 | 37 | (symbolS *) 0, (offsetT) alignment, (char *) 0); |
352 | 37 | memcpy (p, fill_pattern, n_fill); |
353 | 37 | } |
354 | | |
355 | | /* The NOP_OPCODE is for the alignment fill value. Fill it with a nop |
356 | | instruction so that the disassembler does not choke on it. */ |
357 | | #ifndef NOP_OPCODE |
358 | | #define NOP_OPCODE 0x00 |
359 | | #endif |
360 | | |
361 | | /* Use this to restrict the amount of memory allocated for representing |
362 | | the alignment code. Needs to be large enough to hold any fixed sized |
363 | | prologue plus the replicating portion. */ |
364 | | #ifndef MAX_MEM_FOR_RS_ALIGN_CODE |
365 | | /* Assume that if HANDLE_ALIGN is not defined then no special action |
366 | | is required to code fill, which means that we get just repeat the |
367 | | one NOP_OPCODE byte. */ |
368 | | # ifndef HANDLE_ALIGN |
369 | | # define MAX_MEM_FOR_RS_ALIGN_CODE 1 |
370 | | # else |
371 | | # define MAX_MEM_FOR_RS_ALIGN_CODE (((size_t) 1 << alignment) - 1) |
372 | | # endif |
373 | | #endif |
374 | | |
375 | | void |
376 | | frag_align_code (int alignment, int max) |
377 | 10.0k | { |
378 | 10.0k | char *p; |
379 | | |
380 | 10.0k | p = frag_var (rs_align_code, MAX_MEM_FOR_RS_ALIGN_CODE, 1, |
381 | 10.0k | (relax_substateT) max, (symbolS *) 0, |
382 | 10.0k | (offsetT) alignment, (char *) 0); |
383 | 10.0k | *p = NOP_OPCODE; |
384 | 10.0k | } |
385 | | |
386 | | addressT |
387 | | frag_now_fix_octets (void) |
388 | 26.9M | { |
389 | 26.9M | if (now_seg == absolute_section) |
390 | 1.97M | return abs_section_offset; |
391 | | |
392 | 24.9M | return ((char *) obstack_next_free (&frchain_now->frch_obstack) |
393 | 24.9M | - frag_now->fr_literal); |
394 | 26.9M | } |
395 | | |
396 | | addressT |
397 | | frag_now_fix (void) |
398 | 26.7M | { |
399 | | /* Symbols whose section has SEC_ELF_OCTETS set, |
400 | | resolve to octets instead of target bytes. */ |
401 | 26.7M | if (now_seg->flags & SEC_OCTETS) |
402 | 184k | return frag_now_fix_octets (); |
403 | 26.5M | else |
404 | 26.5M | return frag_now_fix_octets () / OCTETS_PER_BYTE; |
405 | 26.7M | } |
406 | | |
407 | | void |
408 | | frag_append_1_char (int datum) |
409 | 1.03M | { |
410 | 1.03M | frag_alloc_check (&frchain_now->frch_obstack); |
411 | 1.03M | if (obstack_room (&frchain_now->frch_obstack) <= 1) |
412 | 226 | { |
413 | 226 | frag_wane (frag_now); |
414 | 226 | frag_new (0); |
415 | 226 | } |
416 | 1.03M | obstack_1grow (&frchain_now->frch_obstack, datum); |
417 | 1.03M | } |
418 | | |
419 | | /* Return TRUE if FRAG1 and FRAG2 have a fixed relationship between |
420 | | their start addresses. Set OFFSET to the difference in address |
421 | | not already accounted for in the frag FR_ADDRESS. */ |
422 | | |
423 | | bool |
424 | | frag_offset_fixed_p (const fragS *frag1, const fragS *frag2, offsetT *offset) |
425 | 4.57k | { |
426 | 4.57k | const fragS *frag; |
427 | 4.57k | offsetT off; |
428 | | |
429 | | /* Start with offset initialised to difference between the two frags. |
430 | | Prior to assigning frag addresses this will be zero. */ |
431 | 4.57k | off = frag1->fr_address - frag2->fr_address; |
432 | 4.57k | if (frag1 == frag2) |
433 | 2.61k | { |
434 | 2.61k | *offset = off; |
435 | 2.61k | return true; |
436 | 2.61k | } |
437 | | |
438 | | /* Maybe frag2 is after frag1. */ |
439 | 1.95k | frag = frag1; |
440 | 5.76k | while (frag->fr_type == rs_fill) |
441 | 5.11k | { |
442 | 5.11k | off += frag->fr_fix + frag->fr_offset * frag->fr_var; |
443 | 5.11k | frag = frag->fr_next; |
444 | 5.11k | if (frag == NULL) |
445 | 591 | break; |
446 | 4.52k | if (frag == frag2) |
447 | 720 | { |
448 | 720 | *offset = off; |
449 | 720 | return true; |
450 | 720 | } |
451 | 4.52k | } |
452 | | |
453 | | /* Maybe frag1 is after frag2. */ |
454 | 1.23k | off = frag1->fr_address - frag2->fr_address; |
455 | 1.23k | frag = frag2; |
456 | 1.23k | while (frag->fr_type == rs_fill) |
457 | 316 | { |
458 | 316 | off -= frag->fr_fix + frag->fr_offset * frag->fr_var; |
459 | 316 | frag = frag->fr_next; |
460 | 316 | if (frag == NULL) |
461 | 316 | break; |
462 | 0 | if (frag == frag1) |
463 | 0 | { |
464 | 0 | *offset = off; |
465 | 0 | return true; |
466 | 0 | } |
467 | 0 | } |
468 | | |
469 | 1.23k | return false; |
470 | 1.23k | } |
471 | | |
472 | | /* Return TRUE if FRAG2 follows FRAG1 with a fixed relationship |
473 | | between the two assuming alignment frags do nothing. Set OFFSET to |
474 | | the difference in address not already accounted for in the frag |
475 | | FR_ADDRESS. */ |
476 | | |
477 | | bool |
478 | | frag_offset_ignore_align_p (const fragS *frag1, const fragS *frag2, |
479 | | offsetT *offset) |
480 | 620k | { |
481 | 620k | const fragS *frag; |
482 | 620k | offsetT off; |
483 | | |
484 | | /* Start with offset initialised to difference between the two frags. |
485 | | Prior to assigning frag addresses this will be zero. */ |
486 | 620k | off = frag1->fr_address - frag2->fr_address; |
487 | 620k | if (frag1 == frag2) |
488 | 509k | { |
489 | 509k | *offset = off; |
490 | 509k | return true; |
491 | 509k | } |
492 | | |
493 | 111k | frag = frag1; |
494 | 125k | while (frag->fr_type == rs_fill |
495 | 125k | || frag->fr_type == rs_align |
496 | 125k | || frag->fr_type == rs_align_code |
497 | 125k | || frag->fr_type == rs_align_test) |
498 | 125k | { |
499 | 125k | if (frag->fr_type == rs_fill) |
500 | 125k | off += frag->fr_fix + frag->fr_offset * frag->fr_var; |
501 | 125k | frag = frag->fr_next; |
502 | 125k | if (frag == NULL) |
503 | 0 | break; |
504 | 125k | if (frag == frag2) |
505 | 111k | { |
506 | 111k | *offset = off; |
507 | 111k | return true; |
508 | 111k | } |
509 | 125k | } |
510 | | |
511 | 0 | return false; |
512 | 111k | } |
513 | | |
514 | | /* Return TRUE if we can determine whether FRAG2 OFF2 appears after |
515 | | (strict >, not >=) FRAG1 OFF1, assuming it is not before. Set |
516 | | *OFFSET so that resolve_expression will resolve an O_gt operation |
517 | | between them to false (0) if they are guaranteed to be at the same |
518 | | location, or to true (-1) if they are guaranteed to be at different |
519 | | locations. Return FALSE conservatively, e.g. if neither result can |
520 | | be guaranteed (yet). |
521 | | |
522 | | They are known to be in the same segment, and not the same frag |
523 | | (this is a fallback for frag_offset_fixed_p, that always takes care |
524 | | of this case), and it is expected (from the uses this is designed |
525 | | to simplify, namely location view increments) that frag2 is |
526 | | reachable from frag1 following the fr_next links, rather than the |
527 | | other way round. */ |
528 | | |
529 | | bool |
530 | | frag_gtoffset_p (valueT off2, const fragS *frag2, |
531 | | valueT off1, const fragS *frag1, offsetT *offset) |
532 | 0 | { |
533 | | /* Insanity check. */ |
534 | 0 | if (frag2 == frag1 || off1 > frag1->fr_fix) |
535 | 0 | return false; |
536 | | |
537 | | /* If the first symbol offset is at the end of the first frag and |
538 | | the second symbol offset at the beginning of the second frag then |
539 | | it is possible they are at the same address. Go looking for a |
540 | | non-zero fr_fix in any frag between these frags. If found then |
541 | | we can say the O_gt result will be true. If no such frag is |
542 | | found we assume that frag1 or any of the following frags might |
543 | | have a variable tail and thus the answer is unknown. This isn't |
544 | | strictly true; some frags don't have a variable tail, but it |
545 | | doesn't seem worth optimizing for those cases. */ |
546 | 0 | const fragS *frag = frag1; |
547 | 0 | offsetT delta = off2 - off1; |
548 | 0 | for (;;) |
549 | 0 | { |
550 | 0 | delta += frag->fr_fix; |
551 | 0 | frag = frag->fr_next; |
552 | 0 | if (frag == frag2) |
553 | 0 | { |
554 | 0 | if (delta == 0) |
555 | 0 | return false; |
556 | 0 | break; |
557 | 0 | } |
558 | | /* If we run off the end of the frag chain then we have a case |
559 | | where frag2 is not after frag1, ie. an O_gt expression not |
560 | | created for .loc view. */ |
561 | 0 | if (frag == NULL) |
562 | 0 | return false; |
563 | 0 | } |
564 | | |
565 | 0 | *offset = (off2 - off1 - delta) * OCTETS_PER_BYTE; |
566 | 0 | return true; |
567 | 0 | } |