]> Git Repo - binutils.git/blob - gas/write.c
record some of my gas work
[binutils.git] / gas / write.c
1 /* write.c - emit .o file
2
3    Copyright (C) 1986, 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
4
5    This file is part of GAS, the GNU Assembler.
6
7    GAS is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2, or (at your option)
10    any later version.
11
12    GAS is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GAS; see the file COPYING.  If not, write to
19    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 /* This thing should be set up to do byteordering correctly.  But... */
22
23 #include "as.h"
24 #include "subsegs.h"
25 #include "obstack.h"
26 #include "output-file.h"
27
28 /* The NOP_OPCODE is for the alignment fill value.
29  * fill it a nop instruction so that the disassembler does not choke
30  * on it
31  */
32 #ifndef NOP_OPCODE
33 #define NOP_OPCODE 0x00
34 #endif
35
36 #ifndef MANY_SEGMENTS
37 struct frag *text_frag_root;
38 struct frag *data_frag_root;
39 struct frag *bss_frag_root;
40
41 struct frag *text_last_frag;    /* Last frag in segment. */
42 struct frag *data_last_frag;    /* Last frag in segment. */
43 static struct frag *bss_last_frag;      /* Last frag in segment. */
44 #endif
45
46 static object_headers headers;
47
48 long string_byte_count;
49
50 static char *the_object_file;
51
52 char *next_object_file_charP;   /* Tracks object file bytes. */
53
54 #ifndef OBJ_VMS
55 int magic_number_for_object_file = DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE;
56 #endif
57
58 static int is_dnrange PARAMS ((struct frag * f1, struct frag * f2));
59 static long fixup_segment PARAMS ((fixS * fixP, segT this_segment_type));
60 static relax_addressT relax_align PARAMS ((relax_addressT addr, long align));
61 void relax_segment PARAMS ((struct frag * seg_frag_root, segT seg_type));
62
63 /*
64  *                      fix_new()
65  *
66  * Create a fixS in obstack 'notes'.
67  */
68 fixS *
69 fix_new (frag, where, size, add_symbol, sub_symbol, offset, pcrel, r_type)
70      fragS *frag;               /* Which frag? */
71      int where;                 /* Where in that frag? */
72      short int size;            /* 1, 2, or 4 usually. */
73      symbolS *add_symbol;       /* X_add_symbol. */
74      symbolS *sub_symbol;       /* X_subtract_symbol. */
75      long offset;               /* X_add_number. */
76      int pcrel;                 /* TRUE if PC-relative relocation. */
77      int r_type;                /* Relocation type */
78 {
79   fixS *fixP;
80
81   fixP = (fixS *) obstack_alloc (&notes, sizeof (fixS));
82
83   fixP->fx_frag = frag;
84   fixP->fx_where = where;
85   fixP->fx_size = size;
86   fixP->fx_addsy = add_symbol;
87   fixP->fx_subsy = sub_symbol;
88   fixP->fx_offset = offset;
89   fixP->fx_pcrel = pcrel;
90 #if defined(TC_SPARC) || defined(TC_A29K) || defined( NEED_FX_R_TYPE)
91   fixP->fx_r_type = r_type;
92 #endif
93   /* JF these 'cuz of the NS32K stuff */
94   fixP->fx_im_disp = 0;
95   fixP->fx_pcrel_adjust = 0;
96   fixP->fx_bsr = 0;
97   fixP->fx_bit_fixP = 0;
98
99   /* usually, we want relocs sorted numerically, but while
100            comparing to older versions of gas that have relocs
101            reverse sorted, it is convenient to have this compile
102            time option.  xoxorich. */
103
104 #ifdef REVERSE_SORT_RELOCS
105
106   fixP->fx_next = *seg_fix_rootP;
107   *seg_fix_rootP = fixP;
108
109 #else /* REVERSE_SORT_RELOCS */
110
111   fixP->fx_next = NULL;
112
113   if (*seg_fix_tailP)
114     (*seg_fix_tailP)->fx_next = fixP;
115   else
116     *seg_fix_rootP = fixP;
117   *seg_fix_tailP = fixP;
118
119 #endif /* REVERSE_SORT_RELOCS */
120
121   fixP->fx_callj = 0;
122   return (fixP);
123 }                               /* fix_new() */
124
125 #ifndef BFD
126
127 void 
128 remove_subsegs (head, seg, root, last)
129      frchainS *head;
130      int seg;
131      fragS **root;
132      fragS **last;
133 {
134   fragS dummy;
135   fragS *prev_frag = &dummy;
136   *root = head->frch_root;
137   while (head && head->frch_seg == seg)
138     {
139       prev_frag->fr_next = head->frch_root;
140
141       prev_frag = head->frch_last;
142       head = head->frch_next;
143     }
144   *last = prev_frag;
145   prev_frag->fr_next = 0;
146 }
147
148 void 
149 write_object_file ()
150 {
151   register struct frchain *frchainP;    /* Track along all frchains. */
152   register fragS *fragP;        /* Track along all frags. */
153   register struct frchain *next_frchainP;
154   register fragS **prev_fragPP;
155
156   long object_file_size;
157
158 #ifdef  OBJ_VMS
159   /*
160    *    Under VMS we try to be compatible with VAX-11 "C".  Thus, we
161    *    call a routine to check for the definition of the procedure
162    *    "_main", and if so -- fix it up so that it can be program
163    *    entry point.
164    */
165   VMS_Check_For_Main ();
166 #endif /* VMS */
167   /*
168    * After every sub-segment, we fake an ".align ...". This conforms to
169    * BSD4.2 brane-damage. We then fake ".fill 0" because that is the
170    * kind of frag that requires least thought. ".align" frags like to
171    * have a following frag since that makes calculating their intended
172    * length trivial.
173    */
174 #ifndef SUB_SEGMENT_ALIGN
175 #define SUB_SEGMENT_ALIGN (2)
176 #endif
177   for (frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next)
178     {
179 #ifdef  OBJ_VMS
180       /*
181        *        Under VAX/VMS, the linker (and PSECT specifications)
182        *        take care of correctly aligning the segments.
183        *        Doing the alignment here (on initialized data) can
184        *        mess up the calculation of global data PSECT sizes.
185        */
186 #undef  SUB_SEGMENT_ALIGN
187 #define SUB_SEGMENT_ALIGN ((frchainP->frch_seg != SEG_DATA) ? 2 : 0)
188 #endif /* VMS */
189       subseg_new (frchainP->frch_seg, frchainP->frch_subseg);
190       frag_align (SUB_SEGMENT_ALIGN, NOP_OPCODE);
191       /* frag_align will have left a new frag. */
192       /* Use this last frag for an empty ".fill". */
193       /*
194        * For this segment ...
195        * Create a last frag. Do not leave a "being filled in frag".
196        */
197       frag_wane (frag_now);
198       frag_now->fr_fix = 0;
199       know (frag_now->fr_next == NULL);
200       /* know( frags . obstack_c_base == frags . obstack_c_next_free ); */
201       /* Above shows we haven't left a half-completed object on obstack. */
202     }                           /* walk the frag chain */
203
204   /*
205    * From now on, we don't care about sub-segments.
206    * Build one frag chain for each segment. Linked thru fr_next.
207    * We know that there is at least 1 text frchain & at least 1 data
208    * frchain.
209    */
210
211   remove_subsegs (frchain_root, SEG_TEXT, &text_frag_root, &text_last_frag);
212   remove_subsegs (data0_frchainP, SEG_DATA, &data_frag_root, &data_last_frag);
213   remove_subsegs (bss0_frchainP, SEG_BSS, &bss_frag_root, &bss_last_frag);
214
215   /*
216    * We have two segments. If user gave -R flag, then we must put the
217    * data frags into the text segment. Do this before relaxing so
218    * we know to take advantage of -R and make shorter addresses.
219    */
220 #ifndef OBJ_AOUT
221   if (flagseen['R'])
222     {
223       fixS *tmp;
224
225       text_last_frag->fr_next = data_frag_root;
226       text_last_frag = data_last_frag;
227       data_last_frag = NULL;
228       data_frag_root = NULL;
229       if (text_fix_root)
230         {
231           for (tmp = text_fix_root; tmp->fx_next; tmp = tmp->fx_next);;
232           tmp->fx_next = data_fix_root;
233           text_fix_tail = data_fix_tail;
234         }
235       else
236         text_fix_root = data_fix_root;
237       data_fix_root = NULL;
238     }
239 #endif
240   relax_segment (text_frag_root, SEG_TEXT);
241   relax_segment (data_frag_root, SEG_DATA);
242   relax_segment (bss_frag_root, SEG_BSS);
243   /*
244    * Now the addresses of frags are correct within the segment.
245    */
246
247   know (text_last_frag->fr_type == rs_fill && text_last_frag->fr_offset == 0);
248   H_SET_TEXT_SIZE (&headers, text_last_frag->fr_address);
249   text_last_frag->fr_address = H_GET_TEXT_SIZE (&headers);
250
251   /*
252    * Join the 2 segments into 1 huge segment.
253    * To do this, re-compute every rn_address in the SEG_DATA frags.
254    * Then join the data frags after the text frags.
255    *
256    * Determine a_data [length of data segment].
257    */
258   if (data_frag_root)
259     {
260       register relax_addressT slide;
261
262       know ((text_last_frag->fr_type == rs_fill) && (text_last_frag->fr_offset == 0));
263
264       H_SET_DATA_SIZE (&headers, data_last_frag->fr_address);
265       data_last_frag->fr_address = H_GET_DATA_SIZE (&headers);
266       slide = H_GET_TEXT_SIZE (&headers);       /* & in file of the data segment. */
267 #ifdef OBJ_BOUT
268 #define RoundUp(N,S) (((N)+(S)-1)&-(S))
269       /* For b.out: If the data section has a strict alignment
270          requirement, its load address in the .o file will be
271          rounded up from the size of the text section.  These
272          two values are *not* the same!  Similarly for the bss
273          section....  */
274       slide = RoundUp (slide, 1 << section_alignment[SEG_DATA]);
275 #endif
276
277       for (fragP = data_frag_root; fragP; fragP = fragP->fr_next)
278         {
279           fragP->fr_address += slide;
280         }                       /* for each data frag */
281
282       know (text_last_frag != 0);
283       text_last_frag->fr_next = data_frag_root;
284     }
285   else
286     {
287       H_SET_DATA_SIZE (&headers, 0);
288     }
289
290 #ifdef OBJ_BOUT
291   /* See above comments on b.out data section address.  */
292   {
293     long bss_vma;
294     if (data_last_frag == 0)
295       bss_vma = H_GET_TEXT_SIZE (&headers);
296     else
297       bss_vma = data_last_frag->fr_address;
298     bss_vma = RoundUp (bss_vma, 1 << section_alignment[SEG_BSS]);
299     bss_address_frag.fr_address = bss_vma;
300   }
301 #else
302   bss_address_frag.fr_address = (H_GET_TEXT_SIZE (&headers) +
303                                  H_GET_DATA_SIZE (&headers));
304
305
306   /* Slide all the frags */
307   if (bss_frag_root)
308     {
309       relax_addressT slide = bss_address_frag.fr_address;
310
311       for (fragP = bss_frag_root; fragP; fragP = fragP->fr_next)
312         {
313           fragP->fr_address += slide;
314         }                       /* for each bss frag */
315     }
316
317 #endif
318
319   if (bss_last_frag)
320     H_SET_BSS_SIZE (&headers,
321                     bss_last_frag->fr_address - bss_frag_root->fr_address);
322   else
323     H_SET_BSS_SIZE (&headers, 0);
324
325   /*
326    *
327    * Crawl the symbol chain.
328    *
329    * For each symbol whose value depends on a frag, take the address of
330    * that frag and subsume it into the value of the symbol.
331    * After this, there is just one way to lookup a symbol value.
332    * Values are left in their final state for object file emission.
333    * We adjust the values of 'L' local symbols, even if we do
334    * not intend to emit them to the object file, because their values
335    * are needed for fix-ups.
336    *
337    * Unless we saw a -L flag, remove all symbols that begin with 'L'
338    * from the symbol chain.  (They are still pointed to by the fixes.)
339    *
340    * Count the remaining symbols.
341    * Assign a symbol number to each symbol.
342    * Count the number of string-table chars we will emit.
343    * Put this info into the headers as appropriate.
344    *
345    */
346   know (zero_address_frag.fr_address == 0);
347   string_byte_count = sizeof (string_byte_count);
348
349   obj_crawl_symbol_chain (&headers);
350
351   if (string_byte_count == sizeof (string_byte_count))
352     {
353       string_byte_count = 0;
354     }                           /* if no strings, then no count. */
355
356   H_SET_STRING_SIZE (&headers, string_byte_count);
357
358   /*
359    * Addresses of frags now reflect addresses we use in the object file.
360    * Symbol values are correct.
361    * Scan the frags, converting any ".org"s and ".align"s to ".fill"s.
362    * Also converting any machine-dependent frags using md_convert_frag();
363    */
364   subseg_change (SEG_TEXT, 0);
365
366   for (fragP = text_frag_root; fragP; fragP = fragP->fr_next)
367     {
368       switch (fragP->fr_type)
369         {
370         case rs_align:
371         case rs_org:
372 #ifdef HANDLE_ALIGN
373           HANDLE_ALIGN (fragP);
374 #endif
375           fragP->fr_type = rs_fill;
376           know (fragP->fr_var == 1);
377           know (fragP->fr_next != NULL);
378
379           fragP->fr_offset = (fragP->fr_next->fr_address
380                               - fragP->fr_address
381                               - fragP->fr_fix);
382           break;
383
384         case rs_fill:
385           break;
386
387         case rs_machine_dependent:
388           md_convert_frag (&headers, fragP);
389
390           know ((fragP->fr_next == NULL) || ((fragP->fr_next->fr_address - fragP->fr_address) == fragP->fr_fix));
391
392           /*
393            * After md_convert_frag, we make the frag into a ".space 0".
394            * Md_convert_frag() should set up any fixSs and constants
395            * required.
396            */
397           frag_wane (fragP);
398           break;
399
400 #ifndef WORKING_DOT_WORD
401         case rs_broken_word:
402           {
403             struct broken_word *lie;
404             extern md_short_jump_size;
405             extern md_long_jump_size;
406
407             if (fragP->fr_subtype)
408               {
409                 fragP->fr_fix += md_short_jump_size;
410                 for (lie = (struct broken_word *) (fragP->fr_symbol); lie && lie->dispfrag == fragP; lie = lie->next_broken_word)
411                   if (lie->added == 1)
412                     fragP->fr_fix += md_long_jump_size;
413               }
414             frag_wane (fragP);
415           }
416           break;
417 #endif
418
419         default:
420           BAD_CASE (fragP->fr_type);
421           break;
422         }                       /* switch (fr_type) */
423
424       if (!((fragP->fr_next == NULL)
425 #ifdef OBJ_BOUT
426             || (fragP->fr_next == data_frag_root)
427 #endif
428             || ((fragP->fr_next->fr_address - fragP->fr_address)
429                 == (fragP->fr_fix + (fragP->fr_offset * fragP->fr_var)))))
430         {
431           fprintf (stderr, "assertion failed: file `%s', line %d\n",
432                    __FILE__, __LINE__ - 4);
433           exit (1);
434         }
435     }                           /* for each frag. */
436
437 #ifndef WORKING_DOT_WORD
438   {
439     struct broken_word *lie;
440     struct broken_word **prevP;
441
442     prevP = &broken_words;
443     for (lie = broken_words; lie; lie = lie->next_broken_word)
444       if (!lie->added)
445         {
446 #ifdef TC_NS32K
447           fix_new_ns32k (lie->frag,
448                          lie->word_goes_here - lie->frag->fr_literal,
449                          2,
450                          lie->add,
451                          lie->sub,
452                          lie->addnum,
453                          0, 0, 2, 0, 0);
454 #else
455 # if defined(TC_SPARC) || defined(TC_A29K) || defined(NEED_FX_R_TYPE)
456           fix_new (lie->frag, lie->word_goes_here - lie->frag->fr_literal,
457                    2, lie->add,
458                    lie->sub, lie->addnum,
459                    0, NO_RELOC);
460 # else
461           fix_new (lie->frag, lie->word_goes_here - lie->frag->fr_literal,
462                    2, lie->add,
463                    lie->sub, lie->addnum,
464                    0, 0);
465
466 # endif                         /* tc_sparc|tc_a29k|need_fx_r_type */
467 #endif /* TC_NS32K */
468           /* md_number_to_chars(lie->word_goes_here,
469                                S_GET_VALUE(lie->add)
470                                + lie->addnum
471                                - S_GET_VALUE(lie->sub),
472                                2); */
473           *prevP = lie->next_broken_word;
474         }
475       else
476         prevP = &(lie->next_broken_word);
477
478     for (lie = broken_words; lie;)
479       {
480         struct broken_word *untruth;
481         char *table_ptr;
482         long table_addr;
483         long from_addr, to_addr;
484         int n, m;
485
486         extern md_short_jump_size;
487         extern md_long_jump_size;
488
489         fragP = lie->dispfrag;
490
491         /* Find out how many broken_words go here */
492         n = 0;
493         for (untruth = lie; untruth && untruth->dispfrag == fragP; untruth = untruth->next_broken_word)
494           if (untruth->added == 1)
495             n++;
496
497         table_ptr = lie->dispfrag->fr_opcode;
498         table_addr = lie->dispfrag->fr_address + (table_ptr - lie->dispfrag->fr_literal);
499         /* Create the jump around the long jumps */
500         /* This is a short jump from table_ptr+0 to table_ptr+n*long_jump_size */
501         from_addr = table_addr;
502         to_addr = table_addr + md_short_jump_size + n * md_long_jump_size;
503         md_create_short_jump (table_ptr, from_addr, to_addr, lie->dispfrag, lie->add);
504         table_ptr += md_short_jump_size;
505         table_addr += md_short_jump_size;
506
507         for (m = 0; lie && lie->dispfrag == fragP; m++, lie = lie->next_broken_word)
508           {
509             if (lie->added == 2)
510               continue;
511             /* Patch the jump table */
512             /* This is the offset from ??? to table_ptr+0 */
513             to_addr = table_addr
514               - S_GET_VALUE (lie->sub);
515             md_number_to_chars (lie->word_goes_here, to_addr, 2);
516             for (untruth = lie->next_broken_word; untruth && untruth->dispfrag == fragP; untruth = untruth->next_broken_word)
517               {
518                 if (untruth->use_jump == lie)
519                   md_number_to_chars (untruth->word_goes_here, to_addr, 2);
520               }
521
522             /* Install the long jump */
523             /* this is a long jump from table_ptr+0 to the final target */
524             from_addr = table_addr;
525             to_addr = S_GET_VALUE (lie->add) + lie->addnum;
526             md_create_long_jump (table_ptr, from_addr, to_addr, lie->dispfrag, lie->add);
527             table_ptr += md_long_jump_size;
528             table_addr += md_long_jump_size;
529           }
530       }
531   }
532 #endif /* not WORKING_DOT_WORD */
533
534 #ifndef OBJ_VMS
535   {                             /* not vms */
536     /*
537      * Scan every FixS performing fixups. We had to wait until now to do
538      * this because md_convert_frag() may have made some fixSs.
539      */
540     int trsize, drsize;
541
542     subseg_change (SEG_TEXT, 0);
543     trsize = md_reloc_size * fixup_segment (text_fix_root,
544                                             SEG_TEXT);
545     subseg_change (SEG_DATA, 0);
546     drsize = md_reloc_size * fixup_segment (data_fix_root,
547                                             SEG_DATA);
548     H_SET_RELOCATION_SIZE (&headers, trsize, drsize);
549
550     /* FIXME move this stuff into the pre-write-hook */
551     H_SET_MAGIC_NUMBER (&headers, magic_number_for_object_file);
552     H_SET_ENTRY_POINT (&headers, 0);
553
554     obj_pre_write_hook (&headers);      /* extra coff stuff */
555     if ((had_warnings () && flagseen['Z'])
556         || had_errors () > 0)
557       {
558         if (flagseen['Z'])
559           {
560             as_warn ("%d error%s, %d warning%s, generating bad object file.\n",
561                      had_errors (), had_errors () == 1 ? "" : "s",
562                      had_warnings (), had_warnings () == 1 ? "" : "s");
563           }
564         else
565           {
566             as_fatal ("%d error%s, %d warning%s, no object file generated.\n",
567                       had_errors (), had_errors () == 1 ? "" : "s",
568                       had_warnings (), had_warnings () == 1 ? "" : "s");
569           }                     /* on want output */
570       }                         /* on error condition */
571
572     object_file_size = H_GET_FILE_SIZE (&headers);
573     next_object_file_charP = the_object_file = xmalloc (object_file_size);
574
575     output_file_create (out_file_name);
576
577     obj_header_append (&next_object_file_charP, &headers);
578
579     know ((next_object_file_charP - the_object_file) == H_GET_HEADER_SIZE (&headers));
580
581     /*
582                  * Emit code.
583                  */
584     for (fragP = text_frag_root; fragP; fragP = fragP->fr_next)
585       {
586         register long count;
587         register char *fill_literal;
588         register long fill_size;
589
590         know (fragP->fr_type == rs_fill);
591         append (&next_object_file_charP, fragP->fr_literal, (unsigned long) fragP->fr_fix);
592         fill_literal = fragP->fr_literal + fragP->fr_fix;
593         fill_size = fragP->fr_var;
594         know (fragP->fr_offset >= 0);
595
596         for (count = fragP->fr_offset; count; count--)
597           {
598             append (&next_object_file_charP, fill_literal, (unsigned long) fill_size);
599           }                     /* for each  */
600
601       }                         /* for each code frag. */
602
603     know ((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE (&headers) + H_GET_TEXT_SIZE (&headers) + H_GET_DATA_SIZE (&headers)));
604
605     /*
606                  * Emit relocations.
607                  */
608     obj_emit_relocations (&next_object_file_charP, text_fix_root, (relax_addressT) 0);
609     know ((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE (&headers) + H_GET_TEXT_SIZE (&headers) + H_GET_DATA_SIZE (&headers) + H_GET_TEXT_RELOCATION_SIZE (&headers)));
610 #ifdef TC_I960
611     /* Make addresses in data relocation directives relative to beginning of
612                  * first data fragment, not end of last text fragment:  alignment of the
613                  * start of the data segment may place a gap between the segments.
614                  */
615     obj_emit_relocations (&next_object_file_charP, data_fix_root, data0_frchainP->frch_root->fr_address);
616 #else /* TC_I960 */
617     obj_emit_relocations (&next_object_file_charP, data_fix_root, text_last_frag->fr_address);
618 #endif /* TC_I960 */
619
620     know ((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE (&headers) + H_GET_TEXT_SIZE (&headers) + H_GET_DATA_SIZE (&headers) + H_GET_TEXT_RELOCATION_SIZE (&headers) + H_GET_DATA_RELOCATION_SIZE (&headers)));
621
622     /*
623                  * Emit line number entries.
624                  */
625     OBJ_EMIT_LINENO (&next_object_file_charP, lineno_rootP, the_object_file);
626     know ((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE (&headers) + H_GET_TEXT_SIZE (&headers) + H_GET_DATA_SIZE (&headers) + H_GET_TEXT_RELOCATION_SIZE (&headers) + H_GET_DATA_RELOCATION_SIZE (&headers) + H_GET_LINENO_SIZE (&headers)));
627
628     /*
629      * Emit symbols.
630      */
631     obj_emit_symbols (&next_object_file_charP, symbol_rootP);
632     know ((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE (&headers) + H_GET_TEXT_SIZE (&headers) + H_GET_DATA_SIZE (&headers) + H_GET_TEXT_RELOCATION_SIZE (&headers) + H_GET_DATA_RELOCATION_SIZE (&headers) + H_GET_LINENO_SIZE (&headers) + H_GET_SYMBOL_TABLE_SIZE (&headers)));
633
634     /*
635      * Emit strings.
636      */
637
638     if (string_byte_count > 0)
639       {
640         obj_emit_strings (&next_object_file_charP);
641       }                         /* only if we have a string table */
642
643     /*    know((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE(&headers) + H_GET_TEXT_SIZE(&headers) + H_GET_DATA_SIZE(&headers) + H_GET_TEXT_RELOCATION_SIZE(&headers) + H_GET_DATA_RELOCATION_SIZE(&headers) + H_GET_LINENO_SIZE(&headers) + H_GET_SYMBOL_TABLE_SIZE(&headers) + H_GET_STRING_SIZE(&headers)));
644                  */
645     /*    know(next_object_file_charP == the_object_file + object_file_size);*/
646
647 #ifdef BFD_HEADERS
648     bfd_seek (stdoutput, 0, 0);
649     bfd_write (the_object_file, 1, object_file_size, stdoutput);
650 #else
651
652     /* Write the data to the file */
653     output_file_append (the_object_file, object_file_size, out_file_name);
654 #endif
655
656     output_file_close (out_file_name);
657   }                             /* non vms output */
658 #else /* VMS */
659   /*
660    *    Now do the VMS-dependent part of writing the object file
661    */
662   VMS_write_object_file (H_GET_TEXT_SIZE (&headers),
663                          H_GET_DATA_SIZE (&headers),
664                          H_GET_BSS_SIZE (&headers),
665                          text_frag_root, data_frag_root);
666 #endif /* VMS */
667 }                               /* write_object_file() */
668
669 #else
670 #endif
671
672 /*
673  *                      relax_segment()
674  *
675  * Now we have a segment, not a crowd of sub-segments, we can make fr_address
676  * values.
677  *
678  * Relax the frags.
679  *
680  * After this, all frags in this segment have addresses that are correct
681  * within the segment. Since segments live in different file addresses,
682  * these frag addresses may not be the same as final object-file addresses.
683  */
684
685
686
687 void 
688 relax_segment (segment_frag_root, segment)
689      struct frag *segment_frag_root;
690      segT segment;              /* SEG_DATA or SEG_TEXT */
691 {
692   register struct frag *fragP;
693   register relax_addressT address;
694 #ifndef MANY_SEGMENTS
695   know (segment == SEG_DATA || segment == SEG_TEXT || segment == SEG_BSS);
696 #endif
697   /* In case md_estimate_size_before_relax() wants to make fixSs. */
698   subseg_change (segment, 0);
699
700   /* For each frag in segment: count and store  (a 1st guess of)
701      fr_address.  */
702   address = 0;
703   for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next)
704     {
705       fragP->fr_address = address;
706       address += fragP->fr_fix;
707
708       switch (fragP->fr_type)
709         {
710         case rs_fill:
711           address += fragP->fr_offset * fragP->fr_var;
712           break;
713
714         case rs_align:
715           address += relax_align (address, fragP->fr_offset);
716           break;
717
718         case rs_org:
719           /* Assume .org is nugatory. It will grow with 1st relax.  */
720           break;
721
722         case rs_machine_dependent:
723           address += md_estimate_size_before_relax (fragP, segment);
724           break;
725
726 #ifndef WORKING_DOT_WORD
727           /* Broken words don't concern us yet */
728         case rs_broken_word:
729           break;
730 #endif
731
732         default:
733           BAD_CASE (fragP->fr_type);
734           break;
735         }                       /* switch(fr_type) */
736     }                           /* for each frag in the segment */
737
738   /* Do relax().  */
739   {
740     long stretch;       /* May be any size, 0 or negative. */
741     /* Cumulative number of addresses we have */
742     /* relaxed this pass. */
743     /* We may have relaxed more than one address. */
744     long stretched;     /* Have we stretched on this pass? */
745     /* This is 'cuz stretch may be zero, when, in fact some piece of code
746        grew, and another shrank.  If a branch instruction doesn't fit anymore,
747        we could be scrod.  */
748
749     do
750       {
751         stretch = stretched = 0;
752         for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next)
753           {
754             long growth = 0;
755             unsigned long was_address;
756             long offset;
757             symbolS *symbolP;
758             long target;
759             long after;
760             long aim;
761
762             was_address = fragP->fr_address;
763             address = fragP->fr_address += stretch;
764             symbolP = fragP->fr_symbol;
765             offset = fragP->fr_offset;
766
767             switch (fragP->fr_type)
768               {
769               case rs_fill:     /* .fill never relaxes. */
770                 growth = 0;
771                 break;
772
773 #ifndef WORKING_DOT_WORD
774                 /* JF:  This is RMS's idea.  I do *NOT* want to be blamed
775                    for it I do not want to write it.  I do not want to have
776                    anything to do with it.  This is not the proper way to
777                    implement this misfeature.  */
778               case rs_broken_word:
779                 {
780                   struct broken_word *lie;
781                   struct broken_word *untruth;
782                   extern int md_short_jump_size;
783                   extern int md_long_jump_size;
784
785                   /* Yes this is ugly (storing the broken_word pointer
786                      in the symbol slot).  Still, this whole chunk of
787                      code is ugly, and I don't feel like doing anything
788                      about it.  Think of it as stubbornness in action.  */
789                   growth = 0;
790                   for (lie = (struct broken_word *) (fragP->fr_symbol);
791                        lie && lie->dispfrag == fragP;
792                        lie = lie->next_broken_word)
793                     {
794
795                       if (lie->added)
796                         continue;
797
798                       offset = (lie->add->sy_frag->fr_address
799                                 + S_GET_VALUE (lie->add)
800                                 + lie->addnum
801                                 - (lie->sub->sy_frag->fr_address
802                                    + S_GET_VALUE (lie->sub)));
803                       if (offset <= -32768 || offset >= 32767)
804                         {
805                           if (flagseen['K'])
806                             as_warn (".word %s-%s+%ld didn't fit",
807                                      S_GET_NAME (lie->add),
808                                      S_GET_NAME (lie->sub),
809                                      lie->addnum);
810                           lie->added = 1;
811                           if (fragP->fr_subtype == 0)
812                             {
813                               fragP->fr_subtype++;
814                               growth += md_short_jump_size;
815                             }
816                           for (untruth = lie->next_broken_word;
817                                untruth && untruth->dispfrag == lie->dispfrag;
818                                untruth = untruth->next_broken_word)
819                             if ((untruth->add->sy_frag == lie->add->sy_frag)
820                                 && S_GET_VALUE (untruth->add) == S_GET_VALUE (lie->add))
821                               {
822                                 untruth->added = 2;
823                                 untruth->use_jump = lie;
824                               }
825                           growth += md_long_jump_size;
826                         }
827                     }
828
829                   break;
830                 }               /* case rs_broken_word */
831 #endif
832               case rs_align:
833                 growth = (relax_align ((relax_addressT) (address + fragP->fr_fix), offset)
834                           - relax_align ((relax_addressT) (was_address + fragP->fr_fix), offset));
835                 break;
836
837               case rs_org:
838                 target = offset;
839
840                 if (symbolP)
841                   {
842 #ifdef MANY_SEGMENTS
843 #else
844                     know ((S_GET_SEGMENT (symbolP) == SEG_ABSOLUTE) || (S_GET_SEGMENT (symbolP) == SEG_DATA) || (S_GET_SEGMENT (symbolP) == SEG_TEXT) || S_GET_SEGMENT (symbolP) == SEG_BSS);
845                     know (symbolP->sy_frag);
846                     know (!(S_GET_SEGMENT (symbolP) == SEG_ABSOLUTE) || (symbolP->sy_frag == &zero_address_frag));
847 #endif
848                     target += S_GET_VALUE (symbolP)
849                       + symbolP->sy_frag->fr_address;
850                   }             /* if we have a symbol */
851
852                 know (fragP->fr_next);
853                 after = fragP->fr_next->fr_address;
854                 growth = ((target - after) > 0) ? (target - after) : 0;
855                 /* Growth may be -ve, but variable part of frag cannot have
856                    fewer than 0 chars.  That is, we can't .org backwards. */
857
858                 growth -= stretch;      /* This is an absolute growth factor */
859                 break;
860
861               case rs_machine_dependent:
862                 {
863                   const relax_typeS *this_type;
864                   const relax_typeS *start_type;
865                   relax_substateT next_state;
866                   relax_substateT this_state;
867
868                   this_state = fragP->fr_subtype;
869                   start_type = this_type = md_relax_table + this_state;
870                   target = offset;
871
872                   if (symbolP)
873                     {
874 #ifndef MANY_SEGMENTS
875                       know ((S_GET_SEGMENT (symbolP) == SEG_ABSOLUTE) || (S_GET_SEGMENT (symbolP) == SEG_DATA) || (S_GET_SEGMENT (symbolP) == SEG_BSS) || (S_GET_SEGMENT (symbolP) == SEG_TEXT));
876 #endif
877                       know (symbolP->sy_frag);
878                       know (!(S_GET_SEGMENT (symbolP) == SEG_ABSOLUTE) || symbolP->sy_frag == &zero_address_frag);
879                       target +=
880                         S_GET_VALUE (symbolP)
881                         + symbolP->sy_frag->fr_address;
882
883                       /* If frag has yet to be reached on this pass,
884                          assume it will move by STRETCH just as we did.
885                          If this is not so, it will be because some frag
886                          between grows, and that will force another pass.  */
887
888                       /* JF was just address */
889                       /* JF also added is_dnrange hack */
890                       /* There's gotta be a better/faster/etc way
891                          to do this. . . */
892                       /* [email protected]:  I changed this from > to >=
893                          because I ran into a zero-length frag (fr_fix=0)
894                          which was created when the obstack needed a new
895                          chunk JUST AFTER the opcode of a branch.  Since
896                          fr_fix is zero, fr_address of this frag is the same
897                          as fr_address of the next frag.  This
898                          zero-length frag was variable and jumped to .+2
899                          (in the next frag), but since the > comparison
900                          below failed (the two were =, not >), "stretch"
901                          was not added to the target.  Stretch was 178, so
902                          the offset appeared to be .-176 instead, which did
903                          not fit into a byte branch, so the assembler
904                          relaxed the branch to a word.  This didn't compare
905                          with what happened when the same source file was
906                          assembled on other machines, which is how I found it.
907                          You might want to think about what other places have
908                          trouble with zero length frags... */
909
910                       if (symbolP->sy_frag->fr_address >= was_address
911                           && is_dnrange (fragP, symbolP->sy_frag))
912                         {
913                           target += stretch;
914                         }
915                     }           /* if there's a symbol attached */
916
917                   aim = target - address - fragP->fr_fix;
918                   /* The displacement is affected by the instruction size
919                      for the 32k architecture. I think we ought to be able
920                      to add fragP->fr_pcrel_adjust in all cases (it should be
921                      zero if not used), but just in case it breaks something
922                      else we'll put this inside #ifdef NS32K ... #endif  */
923 #ifdef TC_NS32K
924                   aim += fragP->fr_pcrel_adjust;
925 #endif /* TC_NS32K */
926
927                   if (aim < 0)
928                     {
929                       /* Look backwards. */
930                       for (next_state = this_type->rlx_more; next_state;)
931                         if (aim >= this_type->rlx_backward)
932                           next_state = 0;
933                         else
934                           {
935                             /* Grow to next state. */
936                             this_state = next_state;
937                             this_type = md_relax_table + this_state;
938                             next_state = this_type->rlx_more;
939                           }
940                     }
941                   else
942                     {
943 #ifdef M68K_AIM_KLUDGE
944                       M68K_AIM_KLUDGE (aim, this_state, this_type);
945 #endif
946                       /* Look forwards. */
947                       for (next_state = this_type->rlx_more; next_state;)
948                         if (aim <= this_type->rlx_forward)
949                           next_state = 0;
950                         else
951                           {
952                             /* Grow to next state. */
953                             this_state = next_state;
954                             this_type = md_relax_table + this_state;
955                             next_state = this_type->rlx_more;
956                           }
957                     }
958
959                   growth = this_type->rlx_length - start_type->rlx_length;
960                   if (growth != 0)
961                     fragP->fr_subtype = this_state;
962                 }
963                 break;
964
965               default:
966                 BAD_CASE (fragP->fr_type);
967                 break;
968               }
969             if (growth)
970               {
971                 stretch += growth;
972                 stretched++;
973               }
974           }                     /* For each frag in the segment. */
975       }
976     while (stretched);          /* Until nothing further to relax. */
977   }                             /* do_relax */
978
979   /*
980    * We now have valid fr_address'es for each frag.
981    */
982
983   /*
984    * All fr_address's are correct, relative to their own segment.
985    * We have made all the fixS we will ever make.
986    */
987 }                               /* relax_segment() */
988
989 /*
990  * Relax_align. Advance location counter to next address that has 'alignment'
991  * lowest order bits all 0s.
992  */
993
994 /* How many addresses does the .align take? */
995 static relax_addressT
996 relax_align (address, alignment)
997      register relax_addressT address;   /* Address now. */
998      register long alignment;   /* Alignment (binary). */
999 {
1000   relax_addressT mask;
1001   relax_addressT new_address;
1002
1003   mask = ~((~0) << alignment);
1004   new_address = (address + mask) & (~mask);
1005   if (linkrelax)
1006     /* We must provide lots of padding, so the linker can discard it
1007        when needed.  The linker will not add extra space, ever.  */
1008     new_address += (1 << alignment);
1009   return (new_address - address);
1010 }                               /* relax_align() */
1011
1012 /* fixup_segment()
1013
1014    Go through all the fixS's in a segment and see which ones can be
1015    handled now.  (These consist of fixS where we have since discovered
1016    the value of a symbol, or the address of the frag involved.)
1017    For each one, call md_apply_fix to put the fix into the frag data.
1018
1019    Result is a count of how many relocation structs will be needed to
1020    handle the remaining fixS's that we couldn't completely handle here.
1021    These will be output later by emit_relocations().  */
1022
1023 static long
1024 fixup_segment (fixP, this_segment_type)
1025      register fixS *fixP;
1026      segT this_segment_type;    /* N_TYPE bits for segment. */
1027 {
1028   register long seg_reloc_count;
1029   register symbolS *add_symbolP;
1030   register symbolS *sub_symbolP;
1031   register long add_number;
1032   register int size;
1033   register char *place;
1034   register long where;
1035   register char pcrel;
1036   register fragS *fragP;
1037   register segT add_symbol_segment = SEG_ABSOLUTE;
1038
1039   /* FIXME: remove this line *//*       fixS *orig = fixP; */
1040   seg_reloc_count = 0;
1041 #ifdef TC_I960
1042   /* If the linker is doing the relaxing, we must not do any fixups */
1043   if (linkrelax)
1044     {
1045       for (; fixP; fixP = fixP->fx_next)
1046         {
1047           seg_reloc_count++;
1048         }
1049     }
1050   else
1051 #endif
1052     for (; fixP; fixP = fixP->fx_next)
1053       {
1054         fragP = fixP->fx_frag;
1055         know (fragP);
1056         where = fixP->fx_where;
1057         place = fragP->fr_literal + where;
1058         size = fixP->fx_size;
1059         add_symbolP = fixP->fx_addsy;
1060 #ifdef TC_I960
1061         if (fixP->fx_callj && TC_S_IS_CALLNAME (add_symbolP))
1062           {
1063             /* Relocation should be done via the
1064                            associated 'bal' entry point
1065                            symbol. */
1066
1067             if (!TC_S_IS_BALNAME (tc_get_bal_of_call (add_symbolP)))
1068               {
1069                 as_bad ("No 'bal' entry point for leafproc %s",
1070                         S_GET_NAME (add_symbolP));
1071                 continue;
1072               }
1073             fixP->fx_addsy = add_symbolP = tc_get_bal_of_call (add_symbolP);
1074           }                     /* callj relocation */
1075 #endif
1076         sub_symbolP = fixP->fx_subsy;
1077         add_number = fixP->fx_offset;
1078         pcrel = fixP->fx_pcrel;
1079
1080         if (add_symbolP)
1081           {
1082             add_symbol_segment = S_GET_SEGMENT (add_symbolP);
1083           }                     /* if there is an addend */
1084
1085         if (sub_symbolP)
1086           {
1087             if (!add_symbolP)
1088               {
1089                 /* Its just -sym */
1090                 if (S_GET_SEGMENT (sub_symbolP) != SEG_ABSOLUTE)
1091                   {
1092                     as_bad ("Negative of non-absolute symbol %s", S_GET_NAME (sub_symbolP));
1093                   }             /* not absolute */
1094
1095                 add_number -= S_GET_VALUE (sub_symbolP);
1096
1097                 /* if sub_symbol is in the same segment that add_symbol
1098                                    and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE */
1099               }
1100             else if ((S_GET_SEGMENT (sub_symbolP) == add_symbol_segment)
1101                      && (SEG_NORMAL (add_symbol_segment)
1102                          || (add_symbol_segment == SEG_ABSOLUTE)))
1103               {
1104                 /* Difference of 2 symbols from same segment. */
1105                 /* Can't make difference of 2 undefineds: 'value' means */
1106                 /* something different for N_UNDF. */
1107 #ifdef TC_I960
1108                 /* Makes no sense to use the difference of 2 arbitrary symbols
1109                                  * as the target of a call instruction.
1110                                  */
1111                 if (fixP->fx_callj)
1112                   {
1113                     as_bad ("callj to difference of 2 symbols");
1114                   }
1115 #endif /* TC_I960 */
1116                 add_number += S_GET_VALUE (add_symbolP) -
1117                   S_GET_VALUE (sub_symbolP);
1118
1119                 add_symbolP = NULL;
1120                 fixP->fx_addsy = NULL;
1121               }
1122             else
1123               {
1124                 /* Different segments in subtraction. */
1125                 know (!(S_IS_EXTERNAL (sub_symbolP) && (S_GET_SEGMENT (sub_symbolP) == SEG_ABSOLUTE)));
1126
1127                 if ((S_GET_SEGMENT (sub_symbolP) == SEG_ABSOLUTE))
1128                   {
1129                     add_number -= S_GET_VALUE (sub_symbolP);
1130                   }
1131                 else
1132                   {
1133                     as_bad ("Can't emit reloc {- %s-seg symbol \"%s\"} @ file address %d.",
1134                             segment_name (S_GET_SEGMENT (sub_symbolP)),
1135                        S_GET_NAME (sub_symbolP), fragP->fr_address + where);
1136                   }             /* if absolute */
1137               }
1138           }                     /* if sub_symbolP */
1139
1140         if (add_symbolP)
1141           {
1142             if (add_symbol_segment == this_segment_type && pcrel)
1143               {
1144                 /*
1145                                  * This fixup was made when the symbol's segment was
1146                                  * SEG_UNKNOWN, but it is now in the local segment.
1147                                  * So we know how to do the address without relocation.
1148                                  */
1149 #ifdef TC_I960
1150                 /* reloc_callj() may replace a 'call' with a 'calls' or a 'bal',
1151                                  * in which cases it modifies *fixP as appropriate.  In the case
1152                                  * of a 'calls', no further work is required, and *fixP has been
1153                                  * set up to make the rest of the code below a no-op.
1154                                  */
1155                 reloc_callj (fixP);
1156 #endif /* TC_I960 */
1157
1158                 add_number += S_GET_VALUE (add_symbolP);
1159                 add_number -= md_pcrel_from (fixP);
1160                 pcrel = 0;      /* Lie. Don't want further pcrel processing. */
1161                 fixP->fx_addsy = NULL;  /* No relocations please. */
1162               }
1163             else
1164               {
1165                 switch (add_symbol_segment)
1166                   {
1167                   case SEG_ABSOLUTE:
1168 #ifdef TC_I960
1169                     reloc_callj (fixP); /* See comment about reloc_callj() above*/
1170 #endif /* TC_I960 */
1171                     add_number += S_GET_VALUE (add_symbolP);
1172                     fixP->fx_addsy = NULL;
1173                     add_symbolP = NULL;
1174                     break;
1175                   default:
1176                     seg_reloc_count++;
1177                     add_number += S_GET_VALUE (add_symbolP);
1178                     break;
1179
1180                   case SEG_UNKNOWN:
1181 #ifdef TC_I960
1182                     if ((int) fixP->fx_bit_fixP == 13)
1183                       {
1184                         /* This is a COBR instruction.  They have only a
1185                                                  * 13-bit displacement and are only to be used
1186                                                  * for local branches: flag as error, don't generate
1187                                                  * relocation.
1188                                                  */
1189                         as_bad ("can't use COBR format with external label");
1190                         fixP->fx_addsy = NULL;  /* No relocations please. */
1191                         continue;
1192                       }         /* COBR */
1193 #endif /* TC_I960 */
1194
1195 #ifdef OBJ_COFF
1196 #ifdef TE_I386AIX
1197                     if (S_IS_COMMON (add_symbolP))
1198                       add_number += S_GET_VALUE (add_symbolP);
1199 #endif /* TE_I386AIX */
1200 #endif /* OBJ_COFF */
1201                     ++seg_reloc_count;
1202
1203                     break;
1204
1205
1206                   }             /* switch on symbol seg */
1207               }                 /* if not in local seg */
1208           }                     /* if there was a + symbol */
1209
1210         if (pcrel)
1211           {
1212             add_number -= md_pcrel_from (fixP);
1213             if (add_symbolP == 0)
1214               {
1215                 fixP->fx_addsy = &abs_symbol;
1216                 ++seg_reloc_count;
1217               }                 /* if there's an add_symbol */
1218           }                     /* if pcrel */
1219
1220         if (!fixP->fx_bit_fixP)
1221           {
1222             if ((size == 1 &&
1223                  (add_number & ~0xFF) && ((add_number & ~0xFF) != (-1 & ~0xFF))) ||
1224                 (size == 2 &&
1225                  (add_number & ~0xFFFF) && ((add_number & ~0xFFFF) != (-1 & ~0xFFFF))))
1226               {
1227                 as_bad ("Value of %d too large for field of %d bytes at 0x%x",
1228                         add_number, size, fragP->fr_address + where);
1229               }                 /* generic error checking */
1230 #ifdef WARN_SIGNED_OVERFLOW_WORD
1231             /* Warn if a .word value is too large when
1232                            treated as a signed number.  We already
1233                            know it is not too negative.  This is to
1234                            catch over-large switches generated by gcc
1235                            on the 68k.  */
1236             if (!flagseen['J']
1237                 && size == 2
1238                 && add_number > 0x7fff)
1239               as_bad ("Signed .word overflow; switch may be too large; %d at 0x%x",
1240                       add_number, fragP->fr_address + where);
1241 #endif
1242           }                     /* not a bit fix */
1243
1244         md_apply_fix (fixP, add_number);
1245       }                         /* For each fixS in this segment. */
1246
1247 #ifdef OBJ_COFF
1248 #ifdef TC_I960
1249   {
1250     fixS *topP = fixP;
1251
1252     /* two relocs per callj under coff. */
1253     for (fixP = topP; fixP; fixP = fixP->fx_next)
1254       {
1255         if (fixP->fx_callj && fixP->fx_addsy != 0)
1256           {
1257             ++seg_reloc_count;
1258           }                     /* if callj and not already fixed. */
1259       }                         /* for each fix */
1260   }
1261 #endif /* TC_I960 */
1262
1263 #endif /* OBJ_COFF */
1264   return (seg_reloc_count);
1265 }                               /* fixup_segment() */
1266
1267
1268 static int 
1269 is_dnrange (f1, f2)
1270      struct frag *f1;
1271      struct frag *f2;
1272 {
1273   while (f1)
1274     {
1275       if (f1->fr_next == f2)
1276         return 1;
1277       f1 = f1->fr_next;
1278     }
1279   return 0;
1280 }                               /* is_dnrange() */
1281
1282 /* Append a string onto another string, bumping the pointer along.  */
1283 void
1284 append (charPP, fromP, length)
1285      char **charPP;
1286      char *fromP;
1287      unsigned long length;
1288 {
1289   if (length)
1290     {                           /* Don't trust memcpy() of 0 chars. */
1291       memcpy (*charPP, fromP, (int) length);
1292       *charPP += length;
1293     }
1294 }
1295
1296 int section_alignment[SEG_MAXIMUM_ORDINAL];
1297
1298 /*
1299  * This routine records the largest alignment seen for each segment.
1300  * If the beginning of the segment is aligned on the worst-case
1301  * boundary, all of the other alignments within it will work.  At
1302  * least one object format really uses this info.
1303  */
1304 void 
1305 record_alignment (seg, align)
1306      segT seg;                  /* Segment to which alignment pertains */
1307      int align;                 /* Alignment, as a power of 2
1308                  *      (e.g., 1 => 2-byte boundary, 2 => 4-byte boundary, etc.)
1309                  */
1310 {
1311
1312   if (align > section_alignment[(int) seg])
1313     {
1314       section_alignment[(int) seg] = align;
1315     }                           /* if highest yet */
1316
1317   return;
1318 }                               /* record_alignment() */
1319
1320 /* end of write.c */
This page took 0.098609 seconds and 4 git commands to generate.