/src/binutils-gdb/gas/frags.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* frags.c - manage frags - |
2 | | Copyright (C) 1987-2025 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 unsigned int totalfrags; |
29 | | |
30 | | unsigned 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 | 28 | { |
47 | 28 | zero_address_frag.fr_type = rs_fill; |
48 | 28 | predefined_address_frag.fr_type = rs_fill; |
49 | 28 | } |
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 | 23.6k | { |
58 | 23.6k | 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 | 23.6k | if (mri_common_symbol != NULL) |
65 | 2 | { |
66 | 2 | as_bad (_("attempt to allocate data in common section")); |
67 | 2 | mri_common_symbol = NULL; |
68 | 2 | } |
69 | 23.6k | } |
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, size_t extra) |
77 | 3.73k | { |
78 | 3.73k | fragS *ptr; |
79 | 3.73k | int oalign; |
80 | | |
81 | 3.73k | (void) obstack_alloc (ob, 0); |
82 | 3.73k | oalign = obstack_alignment_mask (ob); |
83 | 3.73k | obstack_alignment_mask (ob) = 0; |
84 | 3.73k | ptr = (fragS *) obstack_alloc (ob, extra + SIZEOF_STRUCT_FRAG); |
85 | 3.73k | obstack_alignment_mask (ob) = oalign; |
86 | 3.73k | memset (ptr, 0, SIZEOF_STRUCT_FRAG); |
87 | 3.73k | totalfrags++; |
88 | 3.73k | return ptr; |
89 | 3.73k | } |
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 | 29.8k | { |
99 | 29.8k | if (obstack_room (&frchain_now->frch_obstack) < nchars) |
100 | 19 | { |
101 | 19 | size_t oldc; |
102 | 19 | 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 | 19 | if (nchars < 0x10000) |
108 | 19 | newc = 2 * nchars; |
109 | 0 | else |
110 | 0 | newc = nchars + 0x10000; |
111 | 19 | newc += SIZEOF_STRUCT_FRAG; |
112 | | |
113 | | /* Check for possible overflow. */ |
114 | 19 | 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 | 19 | oldc = obstack_chunk_size (&frchain_now->frch_obstack); |
123 | 19 | if (newc > oldc) |
124 | 0 | obstack_chunk_size (&frchain_now->frch_obstack) = newc; |
125 | | |
126 | 38 | while (obstack_room (&frchain_now->frch_obstack) < nchars) |
127 | 19 | { |
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 | 19 | frag_wane (frag_now); |
132 | 19 | frag_new (0); |
133 | 19 | } |
134 | | |
135 | | /* Restore the old chunk size. */ |
136 | 19 | obstack_chunk_size (&frchain_now->frch_obstack) = oldc; |
137 | 19 | } |
138 | 29.8k | } |
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 | 3.32k | { |
162 | 3.32k | fragS *former_last_fragP; |
163 | 3.32k | frchainS *frchP; |
164 | | |
165 | 3.32k | gas_assert (frchain_now->frch_last == frag_now); |
166 | | |
167 | | /* Fix up old frag's fr_fix. */ |
168 | 3.32k | frag_now->fr_fix = frag_now_fix_octets (); |
169 | 3.32k | gas_assert (frag_now->fr_fix >= old_frags_var_max_size |
170 | 3.32k | || now_seg == absolute_section); |
171 | 3.32k | frag_now->fr_fix -= old_frags_var_max_size; |
172 | | /* Make sure its type is valid. */ |
173 | 3.32k | 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 | 3.32k | obstack_finish (&frchain_now->frch_obstack); |
178 | 3.32k | frchP = frchain_now; |
179 | 3.32k | know (frchP); |
180 | 3.32k | former_last_fragP = frchP->frch_last; |
181 | 3.32k | gas_assert (former_last_fragP != 0); |
182 | 3.32k | gas_assert (former_last_fragP == frag_now); |
183 | 3.32k | frag_now = frag_alloc (&frchP->frch_obstack, 0); |
184 | | |
185 | 3.32k | 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 | 3.32k | former_last_fragP->fr_next = frag_now; |
192 | 3.32k | frchP->frch_last = frag_now; |
193 | | |
194 | 3.32k | #ifndef NO_LISTING |
195 | 3.32k | frag_now->line = listing_tail; |
196 | 3.32k | #endif |
197 | | |
198 | 3.32k | gas_assert (frchain_now->frch_last == frag_now); |
199 | | |
200 | 3.32k | frag_now->fr_next = NULL; |
201 | 3.32k | } |
202 | | |
203 | | /* Start a new frag unless we have n more chars of room in the current frag. |
204 | | Close off the old frag with a .fill 0. |
205 | | |
206 | | Return the address of the 1st char to write into. Advance |
207 | | frag_now_growth past the new chars. */ |
208 | | |
209 | | char * |
210 | | frag_more (size_t nchars) |
211 | 21.2k | { |
212 | 21.2k | char *retval; |
213 | | |
214 | 21.2k | frag_alloc_check (&frchain_now->frch_obstack); |
215 | 21.2k | frag_grow (nchars); |
216 | 21.2k | retval = obstack_next_free (&frchain_now->frch_obstack); |
217 | 21.2k | obstack_blank_fast (&frchain_now->frch_obstack, nchars); |
218 | 21.2k | return retval; |
219 | 21.2k | } |
220 | | |
221 | | /* Close the current frag, setting its fields for a relaxable frag. Start a |
222 | | new frag. */ |
223 | | |
224 | | static void |
225 | | frag_var_init (relax_stateT type, size_t max_chars, size_t var, |
226 | | relax_substateT subtype, symbolS *symbol, offsetT offset, |
227 | | char *opcode) |
228 | 3.30k | { |
229 | 3.30k | frag_now->fr_var = var; |
230 | 3.30k | frag_now->fr_type = type; |
231 | 3.30k | frag_now->fr_subtype = subtype; |
232 | 3.30k | frag_now->fr_symbol = symbol; |
233 | 3.30k | frag_now->fr_offset = offset; |
234 | 3.30k | frag_now->fr_opcode = opcode; |
235 | | #ifdef USING_CGEN |
236 | | frag_now->fr_cgen.insn = 0; |
237 | | frag_now->fr_cgen.opindex = 0; |
238 | | frag_now->fr_cgen.opinfo = 0; |
239 | | #endif |
240 | 3.30k | #ifdef TC_FRAG_INIT |
241 | 3.30k | TC_FRAG_INIT (frag_now, max_chars); |
242 | 3.30k | #endif |
243 | 3.30k | frag_now->fr_file = as_where (&frag_now->fr_line); |
244 | | |
245 | 3.30k | frag_new (max_chars); |
246 | 3.30k | } |
247 | | |
248 | | /* Start a new frag unless we have max_chars more chars of room in the |
249 | | current frag. Close off the old frag with a .fill 0. |
250 | | |
251 | | Set up a machine_dependent relaxable frag, then start a new frag. |
252 | | Return the address of the 1st char of the var part of the old frag |
253 | | to write into. */ |
254 | | |
255 | | char * |
256 | | frag_var (relax_stateT type, size_t max_chars, size_t var, |
257 | | relax_substateT subtype, symbolS *symbol, offsetT offset, |
258 | | char *opcode) |
259 | 3.30k | { |
260 | 3.30k | char *retval; |
261 | | |
262 | 3.30k | frag_grow (max_chars); |
263 | 3.30k | retval = obstack_next_free (&frchain_now->frch_obstack); |
264 | 3.30k | obstack_blank_fast (&frchain_now->frch_obstack, max_chars); |
265 | 3.30k | frag_var_init (type, max_chars, var, subtype, symbol, offset, opcode); |
266 | 3.30k | return retval; |
267 | 3.30k | } |
268 | | |
269 | | /* OVE: This variant of frag_var assumes that space for the tail has been |
270 | | allocated by caller. |
271 | | No call to frag_grow is done. */ |
272 | | |
273 | | char * |
274 | | frag_variant (relax_stateT type, size_t max_chars, size_t var, |
275 | | relax_substateT subtype, symbolS *symbol, offsetT offset, |
276 | | char *opcode) |
277 | 0 | { |
278 | 0 | char *retval; |
279 | |
|
280 | 0 | retval = obstack_next_free (&frchain_now->frch_obstack); |
281 | 0 | frag_var_init (type, max_chars, var, subtype, symbol, offset, opcode); |
282 | |
|
283 | 0 | return retval; |
284 | 0 | } |
285 | | |
286 | | /* Reduce the variable end of a frag to a harmless state. */ |
287 | | |
288 | | void |
289 | | frag_wane (fragS *fragP) |
290 | 21 | { |
291 | 21 | fragP->fr_type = rs_fill; |
292 | 21 | fragP->fr_offset = 0; |
293 | 21 | fragP->fr_var = 0; |
294 | 21 | } |
295 | | |
296 | | /* Return the number of bytes by which the current frag can be grown. */ |
297 | | |
298 | | size_t |
299 | | frag_room (void) |
300 | 0 | { |
301 | 0 | return obstack_room (&frchain_now->frch_obstack); |
302 | 0 | } |
303 | | |
304 | | /* Make an alignment frag. The size of this frag will be adjusted to |
305 | | force the next frag to have the appropriate alignment. ALIGNMENT |
306 | | is the power of two to which to align. FILL_CHARACTER is the |
307 | | character to use to fill in any bytes which are skipped. MAX is |
308 | | the maximum number of characters to skip when doing the alignment, |
309 | | or 0 if there is no maximum. */ |
310 | | |
311 | | void |
312 | | frag_align (int alignment, int fill_character, int max) |
313 | 188 | { |
314 | 188 | if (now_seg == absolute_section) |
315 | 137 | { |
316 | 137 | addressT new_off; |
317 | 137 | addressT mask; |
318 | | |
319 | 137 | mask = (~(addressT) 0) << alignment; |
320 | 137 | new_off = (abs_section_offset + ~mask) & mask; |
321 | 137 | if (max == 0 || new_off - abs_section_offset <= (addressT) max) |
322 | 137 | abs_section_offset = new_off; |
323 | 137 | } |
324 | 51 | else |
325 | 51 | { |
326 | 51 | char *p; |
327 | | |
328 | 51 | p = frag_var (rs_align, 1, 1, (relax_substateT) max, |
329 | 51 | (symbolS *) 0, (offsetT) alignment, (char *) 0); |
330 | 51 | *p = fill_character; |
331 | 51 | } |
332 | 188 | } |
333 | | |
334 | | /* Make an alignment frag like frag_align, but fill with a repeating |
335 | | pattern rather than a single byte. ALIGNMENT is the power of two |
336 | | to which to align. FILL_PATTERN is the fill pattern to repeat in |
337 | | the bytes which are skipped. N_FILL is the number of bytes in |
338 | | FILL_PATTERN. MAX is the maximum number of characters to skip when |
339 | | doing the alignment, or 0 if there is no maximum. */ |
340 | | |
341 | | void |
342 | | frag_align_pattern (int alignment, const char *fill_pattern, |
343 | | size_t n_fill, int max) |
344 | 0 | { |
345 | 0 | char *p; |
346 | |
|
347 | 0 | p = frag_var (rs_align, n_fill, n_fill, (relax_substateT) max, |
348 | 0 | (symbolS *) 0, (offsetT) alignment, (char *) 0); |
349 | 0 | memcpy (p, fill_pattern, n_fill); |
350 | 0 | } |
351 | | |
352 | | /* The NOP_OPCODE is for the alignment fill value. Fill it with a nop |
353 | | instruction so that the disassembler does not choke on it. */ |
354 | | #ifndef NOP_OPCODE |
355 | | #define NOP_OPCODE 0x00 |
356 | | #endif |
357 | | |
358 | | /* Use this to specify the amount of memory allocated for representing |
359 | | the alignment code. Needs to be large enough to hold any fixed size |
360 | | prologue plus the replicating portion. */ |
361 | | #ifndef MAX_MEM_FOR_RS_ALIGN_CODE |
362 | | # define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) 1 |
363 | | #endif |
364 | | |
365 | | void |
366 | | frag_align_code (int alignment, int max) |
367 | 192 | { |
368 | 192 | char *p; |
369 | | |
370 | 192 | p = frag_var (rs_align_code, MAX_MEM_FOR_RS_ALIGN_CODE (alignment, max), 1, |
371 | 192 | (relax_substateT) max, (symbolS *) 0, |
372 | 192 | (offsetT) alignment, (char *) 0); |
373 | 192 | *p = NOP_OPCODE; |
374 | 192 | } |
375 | | |
376 | | addressT |
377 | | frag_now_fix_octets (void) |
378 | 7.10M | { |
379 | 7.10M | if (now_seg == absolute_section) |
380 | 1.92M | return abs_section_offset; |
381 | | |
382 | 5.18M | return ((char *) obstack_next_free (&frchain_now->frch_obstack) |
383 | 5.18M | - frag_now->fr_literal); |
384 | 7.10M | } |
385 | | |
386 | | addressT |
387 | | frag_now_fix (void) |
388 | 7.09M | { |
389 | | /* Symbols whose section has SEC_ELF_OCTETS set, |
390 | | resolve to octets instead of target bytes. */ |
391 | 7.09M | if (now_seg->flags & SEC_OCTETS) |
392 | 302k | return frag_now_fix_octets (); |
393 | 6.79M | else |
394 | 6.79M | return frag_now_fix_octets () / OCTETS_PER_BYTE; |
395 | 7.09M | } |
396 | | |
397 | | void |
398 | | frag_append_1_char (int datum) |
399 | 2.36k | { |
400 | 2.36k | frag_alloc_check (&frchain_now->frch_obstack); |
401 | 2.36k | if (obstack_room (&frchain_now->frch_obstack) <= 1) |
402 | 2 | { |
403 | 2 | frag_wane (frag_now); |
404 | 2 | frag_new (0); |
405 | 2 | } |
406 | 2.36k | obstack_1grow (&frchain_now->frch_obstack, datum); |
407 | 2.36k | } |
408 | | |
409 | | /* Return TRUE if FRAG1 and FRAG2 have a fixed relationship between |
410 | | their start addresses. Set OFFSET to the difference in address |
411 | | not already accounted for in the frag FR_ADDRESS. */ |
412 | | |
413 | | bool |
414 | | frag_offset_fixed_p (const fragS *frag1, const fragS *frag2, offsetT *offset) |
415 | 81 | { |
416 | 81 | const fragS *frag; |
417 | 81 | offsetT off; |
418 | | |
419 | | /* Start with offset initialised to difference between the two frags. |
420 | | Prior to assigning frag addresses this will be zero. */ |
421 | 81 | off = frag1->fr_address - frag2->fr_address; |
422 | 81 | if (frag1 == frag2) |
423 | 81 | { |
424 | 81 | *offset = off; |
425 | 81 | return true; |
426 | 81 | } |
427 | | |
428 | | /* Maybe frag2 is after frag1. */ |
429 | 0 | frag = frag1; |
430 | 0 | while (frag->fr_type == rs_fill) |
431 | 0 | { |
432 | 0 | off += frag->fr_fix + frag->fr_offset * frag->fr_var; |
433 | 0 | frag = frag->fr_next; |
434 | 0 | if (frag == NULL) |
435 | 0 | break; |
436 | 0 | if (frag == frag2) |
437 | 0 | { |
438 | 0 | *offset = off; |
439 | 0 | return true; |
440 | 0 | } |
441 | 0 | } |
442 | | |
443 | | /* Maybe frag1 is after frag2. */ |
444 | 0 | off = frag1->fr_address - frag2->fr_address; |
445 | 0 | frag = frag2; |
446 | 0 | while (frag->fr_type == rs_fill) |
447 | 0 | { |
448 | 0 | off -= frag->fr_fix + frag->fr_offset * frag->fr_var; |
449 | 0 | frag = frag->fr_next; |
450 | 0 | if (frag == NULL) |
451 | 0 | break; |
452 | 0 | if (frag == frag1) |
453 | 0 | { |
454 | 0 | *offset = off; |
455 | 0 | return true; |
456 | 0 | } |
457 | 0 | } |
458 | | |
459 | 0 | return false; |
460 | 0 | } |
461 | | |
462 | | /* Return TRUE if FRAG2 follows FRAG1 with a fixed relationship |
463 | | between the two assuming alignment frags do nothing. Set OFFSET to |
464 | | the difference in address not already accounted for in the frag |
465 | | FR_ADDRESS. */ |
466 | | |
467 | | bool |
468 | | frag_offset_ignore_align_p (const fragS *frag1, const fragS *frag2, |
469 | | offsetT *offset) |
470 | 0 | { |
471 | 0 | const fragS *frag; |
472 | 0 | offsetT off; |
473 | | |
474 | | /* Start with offset initialised to difference between the two frags. |
475 | | Prior to assigning frag addresses this will be zero. */ |
476 | 0 | off = frag1->fr_address - frag2->fr_address; |
477 | 0 | if (frag1 == frag2) |
478 | 0 | { |
479 | 0 | *offset = off; |
480 | 0 | return true; |
481 | 0 | } |
482 | | |
483 | 0 | frag = frag1; |
484 | 0 | while (frag->fr_type == rs_fill |
485 | 0 | || frag->fr_type == rs_align |
486 | 0 | || frag->fr_type == rs_align_code |
487 | 0 | || frag->fr_type == rs_align_test) |
488 | 0 | { |
489 | 0 | if (frag->fr_type == rs_fill) |
490 | 0 | off += frag->fr_fix + frag->fr_offset * frag->fr_var; |
491 | 0 | frag = frag->fr_next; |
492 | 0 | if (frag == NULL) |
493 | 0 | break; |
494 | 0 | if (frag == frag2) |
495 | 0 | { |
496 | 0 | *offset = off; |
497 | 0 | return true; |
498 | 0 | } |
499 | 0 | } |
500 | | |
501 | 0 | return false; |
502 | 0 | } |
503 | | |
504 | | /* Return TRUE if we can determine whether FRAG2 OFF2 appears after |
505 | | (strict >, not >=) FRAG1 OFF1, assuming it is not before. Set |
506 | | *OFFSET so that resolve_expression will resolve an O_gt operation |
507 | | between them to false (0) if they are guaranteed to be at the same |
508 | | location, or to true (-1) if they are guaranteed to be at different |
509 | | locations. Return FALSE conservatively, e.g. if neither result can |
510 | | be guaranteed (yet). |
511 | | |
512 | | They are known to be in the same segment, and not the same frag |
513 | | (this is a fallback for frag_offset_fixed_p, that always takes care |
514 | | of this case), and it is expected (from the uses this is designed |
515 | | to simplify, namely location view increments) that frag2 is |
516 | | reachable from frag1 following the fr_next links, rather than the |
517 | | other way round. */ |
518 | | |
519 | | bool |
520 | | frag_gtoffset_p (valueT off2, const fragS *frag2, |
521 | | valueT off1, const fragS *frag1, offsetT *offset) |
522 | 0 | { |
523 | | /* Insanity check. */ |
524 | 0 | if (frag2 == frag1 || off1 > frag1->fr_fix) |
525 | 0 | return false; |
526 | | |
527 | | /* If the first symbol offset is at the end of the first frag and |
528 | | the second symbol offset at the beginning of the second frag then |
529 | | it is possible they are at the same address. Go looking for a |
530 | | non-zero fr_fix in any frag between these frags. If found then |
531 | | we can say the O_gt result will be true. If no such frag is |
532 | | found we assume that frag1 or any of the following frags might |
533 | | have a variable tail and thus the answer is unknown. This isn't |
534 | | strictly true; some frags don't have a variable tail, but it |
535 | | doesn't seem worth optimizing for those cases. */ |
536 | 0 | const fragS *frag = frag1; |
537 | 0 | offsetT delta = off2 - off1; |
538 | 0 | for (;;) |
539 | 0 | { |
540 | 0 | delta += frag->fr_fix; |
541 | 0 | frag = frag->fr_next; |
542 | 0 | if (frag == frag2) |
543 | 0 | { |
544 | 0 | if (delta == 0) |
545 | 0 | return false; |
546 | 0 | break; |
547 | 0 | } |
548 | | /* If we run off the end of the frag chain then we have a case |
549 | | where frag2 is not after frag1, ie. an O_gt expression not |
550 | | created for .loc view. */ |
551 | 0 | if (frag == NULL) |
552 | 0 | return false; |
553 | 0 | } |
554 | | |
555 | 0 | *offset = (off2 - off1 - delta) * OCTETS_PER_BYTE; |
556 | 0 | return true; |
557 | 0 | } |