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