All files over ~5 lines get copylefted. All copylefted files get
[deliverable/binutils-gdb.git] / gas / config / obj-ieee.c
1 /* obj-format for ieee-695 records.
2 Copyright (C) 1991, 1992 Free Software Foundation, Inc.
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21 /*
22 created by
23
24 steve chamberlain steve@cygnus.com
25 */
26
27 /*
28 this will hopefully become the port through which bfd and gas talk,
29 for the moment, only ieee is known to work well.
30 */
31
32 #include "bfd.h"
33 #include "as.h"
34 #include "subsegs.h"
35 #include "output-file.h"
36 #include "frags.h"
37
38 bfd *abfd;
39
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). */
44 {
45 relax_addressT mask;
46 relax_addressT new_address;
47
48 mask = ~ ( (~0) << alignment );
49 new_address = (address + mask) & (~ mask);
50 return (new_address - address);
51 } /* relax_align() */
52
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),
56 bfd *abfd AND
57 unsigned int idx)
58 {
59 asection *sec;
60 unsigned int size = 0;
61 fragS *frag = segment_info[idx].frag_root;
62 while (frag) {
63 if (frag->fr_address != size) {
64 printf("Out of step\n");
65 size = frag->fr_address;
66 }
67 size += frag->fr_fix;
68 switch (frag->fr_type) {
69 case rs_fill:
70 case rs_org:
71 size += frag->fr_offset * frag->fr_var;
72 break;
73 case rs_align:
74 size += relax_align(size, frag->fr_offset);
75 }
76 frag = frag->fr_next;
77 }
78 if (size) {
79 char *name = segment_info[idx].name;
80 if (name == (char *)NULL) {
81 name = ".data";
82 }
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);
88 }
89 }
90
91 /* run through a frag chain and write out the data to go with it */
92 static void DEFUN(fill_section,(abfd, idx),
93 bfd *abfd AND
94 unsigned int idx)
95 {
96 asection *sec = segment_info[idx].user_stuff;
97 if (sec) {
98 fragS *frag = segment_info[idx].frag_root;
99 unsigned int offset = 0;
100 while (frag) {
101 unsigned int fill_size;
102 unsigned int count;
103 switch (frag->fr_type) {
104 case rs_fill:
105 case rs_align:
106 case rs_org:
107 if(frag->fr_fix)
108 {
109 bfd_set_section_contents(abfd,
110 sec,
111 frag->fr_literal,
112 frag->fr_address,
113 frag->fr_fix);
114 }
115 offset += frag->fr_fix;
116 fill_size = frag->fr_var;
117 if (fill_size)
118 {
119 unsigned int off = frag->fr_fix;
120 for (count = frag->fr_offset; count; count--)
121 {
122 bfd_set_section_contents(abfd, sec,
123 frag->fr_literal +
124 frag->fr_fix,
125 frag->fr_address + off,
126 fill_size);
127 off += fill_size;
128 }
129 }
130 break;
131 default:
132 abort();
133 }
134 frag = frag->fr_next;
135 }
136 }
137 }
138
139 /* Count the relocations in a chain */
140
141 static unsigned int DEFUN(count_entries_in_chain,(idx),
142 unsigned int idx)
143 {
144 unsigned int nrelocs;
145 fixS *fixup_ptr;
146
147 /* Count the relocations */
148 fixup_ptr = segment_info[idx].fix_root;
149 nrelocs = 0;
150 while (fixup_ptr != (fixS *)NULL)
151 {
152 fixup_ptr = fixup_ptr->fx_next;
153 nrelocs ++ ;
154 }
155 return nrelocs;
156 }
157
158 /* output all the relocations for a section */
159 void DEFUN(do_relocs_for,(idx),
160 unsigned int idx)
161 {
162 unsigned int nrelocs;
163 arelent **reloc_ptr_vector;
164 arelent *reloc_vector;
165 asymbol **ptrs;
166 asection *section = (asection *)(segment_info[idx].user_stuff);
167 unsigned int i;
168 fixS *from;
169 if (section) {
170 nrelocs = count_entries_in_chain(idx);
171
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++)
177 {
178 arelent *to = reloc_vector + i;
179 asymbol *s ;
180 reloc_ptr_vector[i] = to;
181 to->howto = (reloc_howto_type *)(from->fx_r_type);
182
183 /* We can't represent complicated things in a reloc yet */
184 /* if (from->fx_addsy == 0 ||
185 from->fx_subsy != 0) abort();
186 */
187 s = &( from->fx_addsy->sy_symbol.sy);
188 to->address = ((char *)( from->fx_frag->fr_address +
189 from->fx_where))
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.
194
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.
199
200 */
201 if (s) {
202 if ((s->flags & BSF_UNDEFINED)==0) {
203 to->section = s->section;
204 to->addend += s->value ;
205 to->sym_ptr_ptr = 0;
206 if (to->howto->pcrel_offset) {
207 /* This is a pcrel relocation, the addend should be adjusted */
208 to->addend -= to->address +1;
209 }
210 }
211 else {
212 to->section = 0;
213 *ptrs = &(from->fx_addsy->sy_symbol.sy);
214 to->sym_ptr_ptr = ptrs;
215
216 if (to->howto->pcrel_offset) {
217 /* This is a pcrel relocation, the addend should be adjusted */
218 to->addend -= to->address -1;
219 }
220 }
221
222 }
223 else {
224 to->section = 0;
225 }
226
227 ptrs++;
228 from = from->fx_next;
229 }
230
231 /* attatch to the section */
232 section->orelocation = reloc_ptr_vector;
233 section->reloc_count = nrelocs;
234 section->flags |= SEC_LOAD;
235 }
236 }
237
238 /* do the symbols.. */
239 static void DEFUN(do_symbols, (abfd),
240 bfd *abfd)
241 {
242 extern symbolS *symbol_rootP;
243 symbolS *ptr;
244 asymbol **symbol_ptr_vec;
245 asymbol *symbol_vec;
246 unsigned int count = 0;
247 unsigned int index;
248
249
250 for (ptr = symbol_rootP;
251 ptr != (symbolS *)NULL;
252 ptr = ptr->sy_next)
253 {
254 if (SEG_NORMAL(ptr->sy_symbol.seg))
255 {
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 ;
261 }
262 }
263 else {
264 switch (ptr->sy_symbol.seg) {
265 case SEG_ABSOLUTE:
266 ptr->sy_symbol.sy.flags |= BSF_ABSOLUTE;
267 ptr->sy_symbol.sy.section = 0;
268 break;
269 case SEG_UNKNOWN:
270 ptr->sy_symbol.sy.flags = BSF_UNDEFINED ;
271 ptr->sy_symbol.sy.section = 0;
272 break;
273 default:
274 abort();
275 }
276 }
277 count++;
278 }
279 symbol_ptr_vec = (asymbol **)malloc((count+1) * sizeof(asymbol *));
280
281 index = 0;
282 for (ptr = symbol_rootP;
283 ptr != (symbolS *)NULL;
284 ptr = ptr->sy_next)
285 {
286 symbol_ptr_vec[index] = &(ptr->sy_symbol.sy);
287 index++;
288 }
289 symbol_ptr_vec[index] =0;
290 abfd->outsymbols = symbol_ptr_vec;
291 abfd->symcount = count;
292 }
293
294 /* The generic as->bfd converter. Other backends may have special case
295 code */
296
297 void DEFUN_VOID(bfd_as_write_hook)
298 {
299 int i;
300
301 for (i = SEG_E0; i < SEG_UNKNOWN; i++) {
302 size_section(abfd, i);
303 }
304
305
306 for (i = SEG_E0; i < SEG_UNKNOWN; i++)
307 fill_section(abfd,i);
308
309 do_symbols(abfd);
310
311 for (i = SEG_E0; i < SEG_UNKNOWN; i++)
312 do_relocs_for(i);
313
314 }
315
316
317
318 S_GET_VALUE(x)
319 symbolS *x;
320 {
321 return x->sy_symbol.sy.value;
322 }
323
324 S_SET_SEGMENT(x,y)
325 symbolS *x ;
326 int y;
327 {
328 x->sy_symbol.seg = y;
329 }
330
331 S_IS_DEFINED(x)
332 symbolS *x;
333 {
334 if (SEG_NORMAL(x->sy_symbol.seg))
335 {
336 return 1;
337 }
338 switch (x->sy_symbol.seg)
339 {
340 case SEG_UNKNOWN:
341 return 0;
342 default:
343 abort();
344 }
345 }
346
347 S_IS_EXTERNAL(x) { abort(); }
348 S_GET_DESC(x) { abort() ; }
349
350 S_GET_SEGMENT(x)
351 symbolS *x;
352 { return x->sy_symbol.seg; }
353
354 S_SET_EXTERNAL(x)
355 symbolS *x;
356 {
357 x->sy_symbol.sy.flags |= BSF_GLOBAL | BSF_EXPORT;
358 }
359
360 S_SET_NAME(x,y)
361 symbolS*x;
362 char *y; {
363 x->sy_symbol.sy.name = y; }
364
365 S_SET_VALUE(s,v)
366 symbolS *s;
367 long v;
368 {
369 s->sy_symbol.sy.value = v;
370 }
371
372 S_GET_OTHER(x) { abort() ;}
373 S_IS_DEBUG(x) { abort(); }
374
375 char *segment_name() { abort(); }
376
377 void obj_read_begin_hook() { }
378
379 static void obj_ieee_section(ignore)
380 int ignore;
381 {
382 extern char *input_line_pointer;
383 extern char is_end_of_line[];
384 char *p= input_line_pointer;
385 char *s = p;
386 int i;
387 /* Look up the name, if it doesn't exist, make it */
388 while (*p &&* p != ' ' && *p != ',' && !is_end_of_line[*p]) {
389 p++;
390 }
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) {
394 goto ok;
395
396 }
397 }
398 else break;
399 }
400 if (i == SEG_UNKNOWN) {
401 as_bad("too many sections");
402 return;
403 }
404
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;
409 ok:
410 subseg_new(i,0);
411 while (!is_end_of_line[*p])
412 p++;
413 input_line_pointer = p;
414
415 }
416
417
418 void cons();
419 void s_ignore();
420
421
422 /*
423 * stringer()
424 *
425 * We read 0 or more ',' seperated, double-quoted strings.
426 *
427 * Caller should have checked need_pass_2 is FALSE because we don't check it.
428 */
429
430 void stringer();
431 void s_globl();
432 const pseudo_typeS obj_pseudo_table[] =
433 {
434 {"section", obj_ieee_section, 0},
435 {"data.b", cons, 1},
436 {"data.w", cons, 2},
437 {"data.l", cons, 4},
438 {"export", s_globl, 0},
439 {"option", s_ignore, 0},
440 {"end", s_ignore, 0},
441 {"import", s_ignore, 0},
442 {"sdata", stringer, 0},
443 0,
444
445 };
446
447
448
449 void obj_symbol_new_hook(symbolP)
450 symbolS *symbolP;
451 {
452 symbolP->sy_symbol.sy.the_bfd = abfd;
453 }
454
455
456
457
458
459 #if 1
460 extern void DEFUN_VOID(write_object_file)
461 {
462 int i;
463 struct frchain *frchain_ptr;
464 struct frag *frag_ptr;
465
466 abfd = bfd_openw(out_file_name, "ieee");
467
468 if (abfd == 0) {
469 as_perror ("FATAL: Can't create %s", out_file_name);
470 exit(42);
471 }
472 bfd_set_format(abfd, bfd_object);
473 bfd_set_arch_mach(abfd, bfd_arch_h8300, 0);
474 subseg_new(1,0);
475 subseg_new(2,0);
476 subseg_new(3,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
483 frag */
484
485 subseg_new(frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
486 #define SUB_SEGMENT_ALIGN 2
487 frag_align(SUB_SEGMENT_ALIGN,0);
488 frag_wane(frag_now);
489 frag_now->fr_fix = 0;
490 know( frag_now->fr_next == NULL );
491 }
492
493 /* Now build one big frag chain for each segment, linked through
494 fr_next. */
495 for (i = SEG_E0; i < SEG_UNKNOWN; i++)
496 {
497
498 fragS ** prev_frag_ptr_ptr ;
499 struct frchain *next_frchain_ptr;
500
501 /* struct frag **head_ptr = segment_info[i].frag_root;*/
502
503 segment_info[i].frag_root = segment_info[i].frchainP->frch_root;
504 #if 0
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)
509 {
510 *head_ptr = frchain_ptr;
511 head_ptr = &frchain_ptr->next;
512 }
513
514
515 #endif
516 }
517
518 for (i = SEG_E0; i < SEG_UNKNOWN; i++) {
519 relax_segment(segment_info[i].frag_root, i);
520 }
521
522 /* Now the addresses of the frags are correct within the segment */
523
524 bfd_as_write_hook();
525 bfd_close(abfd);
526 }
527
528 #endif
529
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(); }
538
539 /* end of obj-ieee.c */
This page took 0.041158 seconds and 5 git commands to generate.