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