1 /* obj-format for ieee-695 records.
2 Copyright (C) 1991, 1992 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
24 steve chamberlain steve@cygnus.com
28 this will hopefully become the port through which bfd and gas talk,
29 for the moment, only ieee is known to work well.
35 #include "output-file.h"
40 /* How many addresses does the .align take? */
41 static relax_addressT
relax_align(address
, alignment
)
42 register relax_addressT address
; /* Address now. */
43 register long alignment
; /* Alignment (binary). */
46 relax_addressT new_address
;
48 mask
= ~ ( (~0) << alignment
);
49 new_address
= (address
+ mask
) & (~ mask
);
50 return (new_address
- address
);
53 /* calculate the size of the frag chain and create a bfd section
54 to contain all of it */
55 static void DEFUN(size_section
,(abfd
, idx
),
60 unsigned int size
= 0;
61 fragS
*frag
= segment_info
[idx
].frag_root
;
63 if (frag
->fr_address
!= size
) {
64 printf("Out of step\n");
65 size
= frag
->fr_address
;
68 switch (frag
->fr_type
) {
71 size
+= frag
->fr_offset
* frag
->fr_var
;
74 size
+= relax_align(size
, frag
->fr_offset
);
79 char *name
= segment_info
[idx
].name
;
80 if (name
== (char *)NULL
) {
83 segment_info
[idx
].user_stuff
= (char *)(sec
= bfd_make_section(abfd
, name
));
84 /* Make it output through itself */
85 sec
->output_section
= sec
;
86 sec
->flags
|= SEC_HAS_CONTENTS
;
87 bfd_set_section_size(abfd
, sec
, size
);
91 /* run through a frag chain and write out the data to go with it */
92 static void DEFUN(fill_section
,(abfd
, idx
),
96 asection
*sec
= segment_info
[idx
].user_stuff
;
98 fragS
*frag
= segment_info
[idx
].frag_root
;
99 unsigned int offset
= 0;
101 unsigned int fill_size
;
103 switch (frag
->fr_type
) {
109 bfd_set_section_contents(abfd
,
115 offset
+= frag
->fr_fix
;
116 fill_size
= frag
->fr_var
;
119 unsigned int off
= frag
->fr_fix
;
120 for (count
= frag
->fr_offset
; count
; count
--)
122 bfd_set_section_contents(abfd
, sec
,
125 frag
->fr_address
+ off
,
134 frag
= frag
->fr_next
;
139 /* Count the relocations in a chain */
141 static unsigned int DEFUN(count_entries_in_chain
,(idx
),
144 unsigned int nrelocs
;
147 /* Count the relocations */
148 fixup_ptr
= segment_info
[idx
].fix_root
;
150 while (fixup_ptr
!= (fixS
*)NULL
)
152 fixup_ptr
= fixup_ptr
->fx_next
;
158 /* output all the relocations for a section */
159 void DEFUN(do_relocs_for
,(idx
),
162 unsigned int nrelocs
;
163 arelent
**reloc_ptr_vector
;
164 arelent
*reloc_vector
;
166 asection
*section
= (asection
*)(segment_info
[idx
].user_stuff
);
170 nrelocs
= count_entries_in_chain(idx
);
172 reloc_ptr_vector
= (arelent
**)malloc((nrelocs
+1) * sizeof(arelent
*));
173 reloc_vector
= (arelent
*)malloc(nrelocs
* sizeof(arelent
));
174 ptrs
= (asymbol
**)malloc(nrelocs
* sizeof(asymbol
*));
175 from
= segment_info
[idx
].fix_root
;
176 for (i
= 0; i
< nrelocs
; i
++)
178 arelent
*to
= reloc_vector
+ i
;
180 reloc_ptr_vector
[i
] = to
;
181 to
->howto
= (reloc_howto_type
*)(from
->fx_r_type
);
183 /* We can't represent complicated things in a reloc yet */
184 /* if (from->fx_addsy == 0 ||
185 from->fx_subsy != 0) abort();
187 s
= &( from
->fx_addsy
->sy_symbol
.sy
);
188 to
->address
= ((char *)( from
->fx_frag
->fr_address
+
190 - ((char *)(&(from
->fx_frag
->fr_literal
)));
191 to
->addend
= from
->fx_offset
;
192 /* If we know the symbol which we want to relocate to, turn this
193 reloaction into a section relative.
195 If this relocation is pcrelative, and we know the
196 destination, we still want to keep the relocation - since
197 the linker might relax some of the bytes, but it stops
198 being pc relative and turns into an absolute relocation.
202 if ((s
->flags
& BSF_UNDEFINED
)==0) {
203 to
->section
= s
->section
;
204 to
->addend
+= s
->value
;
206 if (to
->howto
->pcrel_offset
) {
207 /* This is a pcrel relocation, the addend should be adjusted */
208 to
->addend
-= to
->address
+1;
213 *ptrs
= &(from
->fx_addsy
->sy_symbol
.sy
);
214 to
->sym_ptr_ptr
= ptrs
;
216 if (to
->howto
->pcrel_offset
) {
217 /* This is a pcrel relocation, the addend should be adjusted */
218 to
->addend
-= to
->address
-1;
228 from
= from
->fx_next
;
231 /* attatch to the section */
232 section
->orelocation
= reloc_ptr_vector
;
233 section
->reloc_count
= nrelocs
;
234 section
->flags
|= SEC_LOAD
;
238 /* do the symbols.. */
239 static void DEFUN(do_symbols
, (abfd
),
242 extern symbolS
*symbol_rootP
;
244 asymbol
**symbol_ptr_vec
;
246 unsigned int count
= 0;
250 for (ptr
= symbol_rootP
;
251 ptr
!= (symbolS
*)NULL
;
254 if (SEG_NORMAL(ptr
->sy_symbol
.seg
))
256 ptr
->sy_symbol
.sy
.section
=
257 (asection
*)(segment_info
[ptr
->sy_symbol
.seg
].user_stuff
);
258 ptr
->sy_symbol
.sy
.value
+= ptr
->sy_frag
->fr_address
;
259 if (ptr
->sy_symbol
.sy
.flags
== 0) {
260 ptr
->sy_symbol
.sy
.flags
= BSF_LOCAL
;
264 switch (ptr
->sy_symbol
.seg
) {
266 ptr
->sy_symbol
.sy
.flags
|= BSF_ABSOLUTE
;
267 ptr
->sy_symbol
.sy
.section
= 0;
270 ptr
->sy_symbol
.sy
.flags
= BSF_UNDEFINED
;
271 ptr
->sy_symbol
.sy
.section
= 0;
279 symbol_ptr_vec
= (asymbol
**)malloc((count
+1) * sizeof(asymbol
*));
282 for (ptr
= symbol_rootP
;
283 ptr
!= (symbolS
*)NULL
;
286 symbol_ptr_vec
[index
] = &(ptr
->sy_symbol
.sy
);
289 symbol_ptr_vec
[index
] =0;
290 abfd
->outsymbols
= symbol_ptr_vec
;
291 abfd
->symcount
= count
;
294 /* The generic as->bfd converter. Other backends may have special case
297 void DEFUN_VOID(bfd_as_write_hook
)
301 for (i
= SEG_E0
; i
< SEG_UNKNOWN
; i
++) {
302 size_section(abfd
, i
);
306 for (i
= SEG_E0
; i
< SEG_UNKNOWN
; i
++)
307 fill_section(abfd
,i
);
311 for (i
= SEG_E0
; i
< SEG_UNKNOWN
; i
++)
321 return x
->sy_symbol
.sy
.value
;
328 x
->sy_symbol
.seg
= y
;
334 if (SEG_NORMAL(x
->sy_symbol
.seg
))
338 switch (x
->sy_symbol
.seg
)
347 S_IS_EXTERNAL(x
) { abort(); }
348 S_GET_DESC(x
) { abort() ; }
352 { return x
->sy_symbol
.seg
; }
357 x
->sy_symbol
.sy
.flags
|= BSF_GLOBAL
| BSF_EXPORT
;
363 x
->sy_symbol
.sy
.name
= y
; }
369 s
->sy_symbol
.sy
.value
= v
;
372 S_GET_OTHER(x
) { abort() ;}
373 S_IS_DEBUG(x
) { abort(); }
375 char *segment_name() { abort(); }
377 void obj_read_begin_hook() { }
379 static void obj_ieee_section(ignore
)
382 extern char *input_line_pointer
;
383 extern char is_end_of_line
[];
384 char *p
= input_line_pointer
;
387 /* Look up the name, if it doesn't exist, make it */
388 while (*p
&&* p
!= ' ' && *p
!= ',' && !is_end_of_line
[*p
]) {
391 for (i
= SEG_E0
; i
< SEG_UNKNOWN
; i
++) {
392 if (segment_info
[i
].hadone
){
393 if (strncmp(segment_info
[i
].name
, s
, p
-s
) ==0) {
400 if (i
== SEG_UNKNOWN
) {
401 as_bad("too many sections");
405 segment_info
[i
].hadone
= 1;
406 segment_info
[i
].name
= malloc(p
-s
+ 1);
407 memcpy(segment_info
[i
].name
, s
, p
-s
);
408 segment_info
[i
].name
[p
-s
] = 0;
411 while (!is_end_of_line
[*p
])
413 input_line_pointer
= p
;
425 * We read 0 or more ',' seperated, double-quoted strings.
427 * Caller should have checked need_pass_2 is FALSE because we don't check it.
432 const pseudo_typeS obj_pseudo_table
[] =
434 {"section", obj_ieee_section
, 0},
438 {"export", s_globl
, 0},
439 {"option", s_ignore
, 0},
440 {"end", s_ignore
, 0},
441 {"import", s_ignore
, 0},
442 {"sdata", stringer
, 0},
449 void obj_symbol_new_hook(symbolP
)
452 symbolP
->sy_symbol
.sy
.the_bfd
= abfd
;
460 extern void DEFUN_VOID(write_object_file
)
463 struct frchain
*frchain_ptr
;
464 struct frag
*frag_ptr
;
466 abfd
= bfd_openw(out_file_name
, "ieee");
469 as_perror ("FATAL: Can't create %s", out_file_name
);
472 bfd_set_format(abfd
, bfd_object
);
473 bfd_set_arch_mach(abfd
, bfd_arch_h8300
, 0);
477 for (frchain_ptr
= frchain_root
;
478 frchain_ptr
!= (struct frchain
*)NULL
;
479 frchain_ptr
= frchain_ptr
->frch_next
) {
480 /* Run through all the sub-segments and align them up. Also close any
481 open frags. We tack a .fill onto the end of the frag chain so
482 that any .align's size can be worked by looking at the next
485 subseg_new(frchain_ptr
->frch_seg
, frchain_ptr
->frch_subseg
);
486 #define SUB_SEGMENT_ALIGN 2
487 frag_align(SUB_SEGMENT_ALIGN
,0);
489 frag_now
->fr_fix
= 0;
490 know( frag_now
->fr_next
== NULL
);
493 /* Now build one big frag chain for each segment, linked through
495 for (i
= SEG_E0
; i
< SEG_UNKNOWN
; i
++)
498 fragS
** prev_frag_ptr_ptr
;
499 struct frchain
*next_frchain_ptr
;
501 /* struct frag **head_ptr = segment_info[i].frag_root;*/
503 segment_info
[i
].frag_root
= segment_info
[i
].frchainP
->frch_root
;
505 /* Im not sure what this is for */
506 for (frchain_ptr
= segment_info
[i
].frchainP
->frch_root
;
507 frchain_ptr
!= (struct frchain
*)NULL
;
508 frchain_ptr
= frchain_ptr
->frch_next
)
510 *head_ptr
= frchain_ptr
;
511 head_ptr
= &frchain_ptr
->next
;
518 for (i
= SEG_E0
; i
< SEG_UNKNOWN
; i
++) {
519 relax_segment(segment_info
[i
].frag_root
, i
);
522 /* Now the addresses of the frags are correct within the segment */
530 H_SET_TEXT_SIZE(a
,b
) { abort(); }
531 H_GET_TEXT_SIZE() { abort(); }
532 H_SET_BSS_SIZE() { abort(); }
533 H_SET_STRING_SIZE() { abort(); }
534 H_SET_RELOCATION_SIZE() { abort(); }
535 H_SET_MAGIC_NUMBER() { abort(); }
536 H_GET_FILE_SIZE() { abort(); }
537 H_GET_TEXT_RELOCATION_SIZE() { abort(); }
539 /* end of obj-ieee.c */