]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - bfd/oasys.c
* config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
[thirdparty/binutils-gdb.git] / bfd / oasys.c
1 /* BFD back-end for oasys objects.
2 Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3 Written by Steve Chamberlain of Cygnus Support, <sac@cygnus.com>.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program 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 of the License, or
10 (at your option) any later version.
11
12 This program 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 this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21 #define UNDERSCORE_HACK 1
22 #include "bfd.h"
23 #include "sysdep.h"
24 #include <ctype.h>
25 #include "libbfd.h"
26 #include "oasys.h"
27 #include "liboasys.h"
28
29 /* XXX - FIXME. offsetof belongs in the system-specific files in
30 ../include/sys. */
31 /* Define offsetof for those systems which lack it */
32
33 #ifndef offsetof
34 #define offsetof(type, identifier) (size_t) &(((type *) 0)->identifier)
35 #endif
36
37 static boolean oasys_read_record PARAMS ((bfd *,
38 oasys_record_union_type *));
39 static boolean oasys_write_sections PARAMS ((bfd *));
40 static boolean oasys_write_record PARAMS ((bfd *,
41 oasys_record_enum_type,
42 oasys_record_union_type *,
43 size_t));
44 static boolean oasys_write_syms PARAMS ((bfd *));
45 static boolean oasys_write_header PARAMS ((bfd *));
46 static boolean oasys_write_end PARAMS ((bfd *));
47 static boolean oasys_write_data PARAMS ((bfd *));
48
49 /* Read in all the section data and relocation stuff too */
50 PROTO (static boolean, oasys_slurp_section_data, (bfd * CONST abfd));
51
52 static boolean
53 oasys_read_record (abfd, record)
54 bfd *abfd;
55 oasys_record_union_type *record;
56 {
57 if (bfd_read ((PTR) record, 1, sizeof (record->header), abfd)
58 != sizeof (record->header))
59 return false;
60
61 if ((size_t) record->header.length <= (size_t) sizeof (record->header))
62 return true;
63 if (bfd_read ((PTR) (((char *) record) + sizeof (record->header)),
64 1, record->header.length - sizeof (record->header),
65 abfd)
66 != record->header.length - sizeof (record->header))
67 return false;
68 return true;
69 }
70 static size_t
71 oasys_string_length (record)
72 oasys_record_union_type *record;
73 {
74 return record->header.length
75 - ((char *) record->symbol.name - (char *) record);
76 }
77
78 /*****************************************************************************/
79
80 /*
81
82 Slurp the symbol table by reading in all the records at the start file
83 till we get to the first section record.
84
85 We'll sort the symbolss into two lists, defined and undefined. The
86 undefined symbols will be placed into the table according to their
87 refno.
88
89 We do this by placing all undefined symbols at the front of the table
90 moving in, and the defined symbols at the end of the table moving back.
91
92 */
93
94 static boolean
95 oasys_slurp_symbol_table (abfd)
96 bfd *CONST abfd;
97 {
98 oasys_record_union_type record;
99 oasys_data_type *data = OASYS_DATA (abfd);
100 boolean loop = true;
101 asymbol *dest_defined;
102 asymbol *dest;
103 char *string_ptr;
104
105
106 if (data->symbols != (asymbol *) NULL)
107 {
108 return true;
109 }
110 /* Buy enough memory for all the symbols and all the names */
111 data->symbols =
112 (asymbol *) bfd_alloc (abfd, sizeof (asymbol) * abfd->symcount);
113 #ifdef UNDERSCORE_HACK
114 /* buy 1 more char for each symbol to keep the underscore in*/
115 data->strings = bfd_alloc (abfd, data->symbol_string_length +
116 abfd->symcount);
117 #else
118 data->strings = bfd_alloc (abfd, data->symbol_string_length);
119 #endif
120 if (!data->symbols || !data->strings)
121 return false;
122
123 dest_defined = data->symbols + abfd->symcount - 1;
124
125 string_ptr = data->strings;
126 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
127 return false;
128 while (loop)
129 {
130
131 if (! oasys_read_record (abfd, &record))
132 return false;
133 switch (record.header.type)
134 {
135 case oasys_record_is_header_enum:
136 break;
137 case oasys_record_is_local_enum:
138 case oasys_record_is_symbol_enum:
139 {
140 int flag = record.header.type == (int) oasys_record_is_local_enum ?
141 (BSF_LOCAL) : (BSF_GLOBAL | BSF_EXPORT);
142
143
144 size_t length = oasys_string_length (&record);
145 switch (record.symbol.relb & RELOCATION_TYPE_BITS)
146 {
147 case RELOCATION_TYPE_ABS:
148 dest = dest_defined--;
149 dest->section = bfd_abs_section_ptr;
150 dest->flags = 0;
151
152 break;
153 case RELOCATION_TYPE_REL:
154 dest = dest_defined--;
155 dest->section =
156 OASYS_DATA (abfd)->sections[record.symbol.relb &
157 RELOCATION_SECT_BITS];
158 if (record.header.type == (int) oasys_record_is_local_enum)
159 {
160 dest->flags = BSF_LOCAL;
161 if (dest->section == (asection *) (~0))
162 {
163 /* It seems that sometimes internal symbols are tied up, but
164 still get output, even though there is no
165 section */
166 dest->section = 0;
167 }
168 }
169 else
170 {
171
172 dest->flags = flag;
173 }
174 break;
175 case RELOCATION_TYPE_UND:
176 dest = data->symbols + bfd_h_get_16 (abfd, record.symbol.refno);
177 dest->section = bfd_und_section_ptr;
178 break;
179 case RELOCATION_TYPE_COM:
180 dest = dest_defined--;
181 dest->name = string_ptr;
182 dest->the_bfd = abfd;
183
184 dest->section = bfd_com_section_ptr;
185
186 break;
187 default:
188 dest = dest_defined--;
189 BFD_ASSERT (0);
190 break;
191 }
192 dest->name = string_ptr;
193 dest->the_bfd = abfd;
194 dest->udata.p = (PTR) NULL;
195 dest->value = bfd_h_get_32 (abfd, record.symbol.value);
196
197 #ifdef UNDERSCORE_HACK
198 if (record.symbol.name[0] != '_')
199 {
200 string_ptr[0] = '_';
201 string_ptr++;
202 }
203 #endif
204 memcpy (string_ptr, record.symbol.name, length);
205
206
207 string_ptr[length] = 0;
208 string_ptr += length + 1;
209 }
210 break;
211 default:
212 loop = false;
213 }
214 }
215 return true;
216 }
217
218 static long
219 oasys_get_symtab_upper_bound (abfd)
220 bfd *CONST abfd;
221 {
222 if (! oasys_slurp_symbol_table (abfd))
223 return -1;
224
225 return (abfd->symcount + 1) * (sizeof (oasys_symbol_type *));
226 }
227
228 /*
229 */
230
231 extern const bfd_target oasys_vec;
232
233 long
234 oasys_get_symtab (abfd, location)
235 bfd *abfd;
236 asymbol **location;
237 {
238 asymbol *symbase;
239 unsigned int counter;
240 if (oasys_slurp_symbol_table (abfd) == false)
241 {
242 return -1;
243 }
244 symbase = OASYS_DATA (abfd)->symbols;
245 for (counter = 0; counter < abfd->symcount; counter++)
246 {
247 *(location++) = symbase++;
248 }
249 *location = 0;
250 return abfd->symcount;
251 }
252
253 /***********************************************************************
254 * archive stuff
255 */
256
257 static const bfd_target *
258 oasys_archive_p (abfd)
259 bfd *abfd;
260 {
261 oasys_archive_header_type header;
262 oasys_extarchive_header_type header_ext;
263 unsigned int i;
264 file_ptr filepos;
265
266 if (bfd_seek (abfd, (file_ptr) 0, false) != 0
267 || (bfd_read ((PTR) & header_ext, 1, sizeof (header_ext), abfd)
268 != sizeof (header_ext)))
269 {
270 if (bfd_get_error () != bfd_error_system_call)
271 bfd_set_error (bfd_error_wrong_format);
272 return NULL;
273 }
274
275 header.version = bfd_h_get_32 (abfd, header_ext.version);
276 header.mod_count = bfd_h_get_32 (abfd, header_ext.mod_count);
277 header.mod_tbl_offset = bfd_h_get_32 (abfd, header_ext.mod_tbl_offset);
278 header.sym_tbl_size = bfd_h_get_32 (abfd, header_ext.sym_tbl_size);
279 header.sym_count = bfd_h_get_32 (abfd, header_ext.sym_count);
280 header.sym_tbl_offset = bfd_h_get_32 (abfd, header_ext.sym_tbl_offset);
281 header.xref_count = bfd_h_get_32 (abfd, header_ext.xref_count);
282 header.xref_lst_offset = bfd_h_get_32 (abfd, header_ext.xref_lst_offset);
283
284 /*
285 There isn't a magic number in an Oasys archive, so the best we
286 can do to verify reasnableness is to make sure that the values in
287 the header are too weird
288 */
289
290 if (header.version > 10000 ||
291 header.mod_count > 10000 ||
292 header.sym_count > 100000 ||
293 header.xref_count > 100000)
294 return (const bfd_target *) NULL;
295
296 /*
297 That all worked, let's buy the space for the header and read in
298 the headers.
299 */
300 {
301 oasys_ar_data_type *ar =
302 (oasys_ar_data_type *) bfd_alloc (abfd, sizeof (oasys_ar_data_type));
303
304 oasys_module_info_type *module =
305 (oasys_module_info_type *)
306 bfd_alloc (abfd, sizeof (oasys_module_info_type) * header.mod_count);
307 oasys_module_table_type record;
308
309 if (!ar || !module)
310 return NULL;
311
312 abfd->tdata.oasys_ar_data = ar;
313 ar->module = module;
314 ar->module_count = header.mod_count;
315
316 filepos = header.mod_tbl_offset;
317 for (i = 0; i < header.mod_count; i++)
318 {
319 if (bfd_seek (abfd, filepos, SEEK_SET) != 0)
320 return NULL;
321
322 /* There are two ways of specifying the archive header */
323
324 if (0)
325 {
326 oasys_extmodule_table_type_a_type record_ext;
327 if (bfd_read ((PTR) & record_ext, 1, sizeof (record_ext), abfd)
328 != sizeof (record_ext))
329 return NULL;
330
331 record.mod_size = bfd_h_get_32 (abfd, record_ext.mod_size);
332 record.file_offset = bfd_h_get_32 (abfd, record_ext.file_offset);
333
334 record.dep_count = bfd_h_get_32 (abfd, record_ext.dep_count);
335 record.depee_count = bfd_h_get_32 (abfd, record_ext.depee_count);
336 record.sect_count = bfd_h_get_32 (abfd, record_ext.sect_count);
337
338 module[i].name = bfd_alloc (abfd, 33);
339 if (!module[i].name)
340 return NULL;
341
342 memcpy (module[i].name, record_ext.mod_name, 33);
343 filepos +=
344 sizeof (record_ext) +
345 record.dep_count * 4 +
346 record.depee_count * 4 +
347 record.sect_count * 8 + 187;
348 }
349 else
350 {
351 oasys_extmodule_table_type_b_type record_ext;
352 if (bfd_read ((PTR) & record_ext, 1, sizeof (record_ext), abfd)
353 != sizeof (record_ext))
354 return NULL;
355
356 record.mod_size = bfd_h_get_32 (abfd, record_ext.mod_size);
357 record.file_offset = bfd_h_get_32 (abfd, record_ext.file_offset);
358
359 record.dep_count = bfd_h_get_32 (abfd, record_ext.dep_count);
360 record.depee_count = bfd_h_get_32 (abfd, record_ext.depee_count);
361 record.sect_count = bfd_h_get_32 (abfd, record_ext.sect_count);
362 record.module_name_size = bfd_h_get_32 (abfd, record_ext.mod_name_length);
363
364 module[i].name = bfd_alloc (abfd, record.module_name_size + 1);
365 if (!module[i].name)
366 return NULL;
367 if (bfd_read ((PTR) module[i].name, 1, record.module_name_size,
368 abfd)
369 != record.module_name_size)
370 return NULL;
371 module[i].name[record.module_name_size] = 0;
372 filepos +=
373 sizeof (record_ext) +
374 record.dep_count * 4 +
375 record.module_name_size + 1;
376
377 }
378
379
380 module[i].size = record.mod_size;
381 module[i].pos = record.file_offset;
382 module[i].abfd = 0;
383 }
384
385 }
386 return abfd->xvec;
387 }
388
389 static boolean
390 oasys_mkobject (abfd)
391 bfd *abfd;
392 {
393
394 abfd->tdata.oasys_obj_data = (oasys_data_type *) bfd_alloc (abfd, sizeof (oasys_data_type));
395 return abfd->tdata.oasys_obj_data ? true : false;
396 }
397
398 #define MAX_SECS 16
399 static const bfd_target *
400 oasys_object_p (abfd)
401 bfd *abfd;
402 {
403 oasys_data_type *oasys;
404 oasys_data_type *save = OASYS_DATA (abfd);
405 boolean loop = true;
406 boolean had_usefull = false;
407
408 abfd->tdata.oasys_obj_data = 0;
409 oasys_mkobject (abfd);
410 oasys = OASYS_DATA (abfd);
411 memset ((PTR) oasys->sections, 0xff, sizeof (oasys->sections));
412
413 /* Point to the start of the file */
414 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
415 goto fail;
416 oasys->symbol_string_length = 0;
417 /* Inspect the records, but only keep the section info -
418 remember the size of the symbols
419 */
420 oasys->first_data_record = 0;
421 while (loop)
422 {
423 oasys_record_union_type record;
424 if (! oasys_read_record (abfd, &record))
425 goto fail;
426 if ((size_t) record.header.length < (size_t) sizeof (record.header))
427 goto fail;
428
429
430 switch ((oasys_record_enum_type) (record.header.type))
431 {
432 case oasys_record_is_header_enum:
433 had_usefull = true;
434 break;
435 case oasys_record_is_symbol_enum:
436 case oasys_record_is_local_enum:
437 /* Count symbols and remember their size for a future malloc */
438 abfd->symcount++;
439 oasys->symbol_string_length += 1 + oasys_string_length (&record);
440 had_usefull = true;
441 break;
442 case oasys_record_is_section_enum:
443 {
444 asection *s;
445 char *buffer;
446 unsigned int section_number;
447 if (record.section.header.length != sizeof (record.section))
448 {
449 goto fail;
450 }
451 buffer = bfd_alloc (abfd, 3);
452 if (!buffer)
453 goto fail;
454 section_number = record.section.relb & RELOCATION_SECT_BITS;
455 sprintf (buffer, "%u", section_number);
456 s = bfd_make_section (abfd, buffer);
457 oasys->sections[section_number] = s;
458 switch (record.section.relb & RELOCATION_TYPE_BITS)
459 {
460 case RELOCATION_TYPE_ABS:
461 case RELOCATION_TYPE_REL:
462 break;
463 case RELOCATION_TYPE_UND:
464 case RELOCATION_TYPE_COM:
465 BFD_FAIL ();
466 }
467
468 s->_raw_size = bfd_h_get_32 (abfd, record.section.value);
469 s->vma = bfd_h_get_32 (abfd, record.section.vma);
470 s->flags = 0;
471 had_usefull = true;
472 }
473 break;
474 case oasys_record_is_data_enum:
475 oasys->first_data_record = bfd_tell (abfd) - record.header.length;
476 case oasys_record_is_debug_enum:
477 case oasys_record_is_module_enum:
478 case oasys_record_is_named_section_enum:
479 case oasys_record_is_end_enum:
480 if (had_usefull == false)
481 goto fail;
482 loop = false;
483 break;
484 default:
485 goto fail;
486 }
487 }
488 oasys->symbols = (asymbol *) NULL;
489 /*
490 Oasys support several architectures, but I can't see a simple way
491 to discover which one is in a particular file - we'll guess
492 */
493 bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0);
494 if (abfd->symcount != 0)
495 {
496 abfd->flags |= HAS_SYMS;
497 }
498
499 /*
500 We don't know if a section has data until we've read it..
501 */
502
503 oasys_slurp_section_data (abfd);
504
505
506 return abfd->xvec;
507
508 fail:
509 (void) bfd_release (abfd, oasys);
510 abfd->tdata.oasys_obj_data = save;
511 return (const bfd_target *) NULL;
512 }
513
514
515 static void
516 oasys_get_symbol_info (ignore_abfd, symbol, ret)
517 bfd *ignore_abfd;
518 asymbol *symbol;
519 symbol_info *ret;
520 {
521 bfd_symbol_info (symbol, ret);
522 if (!symbol->section)
523 ret->type = (symbol->flags & BSF_LOCAL) ? 'a' : 'A';
524 }
525
526 static void
527 oasys_print_symbol (ignore_abfd, afile, symbol, how)
528 bfd *ignore_abfd;
529 PTR afile;
530 asymbol *symbol;
531 bfd_print_symbol_type how;
532 {
533 FILE *file = (FILE *) afile;
534
535 switch (how)
536 {
537 case bfd_print_symbol_name:
538 case bfd_print_symbol_more:
539 fprintf (file, "%s", symbol->name);
540 break;
541 case bfd_print_symbol_all:
542 {
543 CONST char *section_name = symbol->section == (asection *) NULL ?
544 (CONST char *) "*abs" : symbol->section->name;
545
546 bfd_print_symbol_vandf ((PTR) file, symbol);
547
548 fprintf (file, " %-5s %s",
549 section_name,
550 symbol->name);
551 }
552 break;
553 }
554 }
555 /*
556 The howto table is build using the top two bits of a reloc byte to
557 index into it. The bits are PCREL,WORD/LONG
558 */
559 static reloc_howto_type howto_table[] =
560 {
561
562 HOWTO (0, 0, 1, 16, false, 0, complain_overflow_bitfield, 0, "abs16", true, 0x0000ffff, 0x0000ffff, false),
563 HOWTO (0, 0, 2, 32, false, 0, complain_overflow_bitfield, 0, "abs32", true, 0xffffffff, 0xffffffff, false),
564 HOWTO (0, 0, 1, 16, true, 0, complain_overflow_signed, 0, "pcrel16", true, 0x0000ffff, 0x0000ffff, false),
565 HOWTO (0, 0, 2, 32, true, 0, complain_overflow_signed, 0, "pcrel32", true, 0xffffffff, 0xffffffff, false)
566 };
567
568 /* Read in all the section data and relocation stuff too */
569 static boolean
570 oasys_slurp_section_data (abfd)
571 bfd *CONST abfd;
572 {
573 oasys_record_union_type record;
574 oasys_data_type *data = OASYS_DATA (abfd);
575 boolean loop = true;
576
577 oasys_per_section_type *per;
578
579 asection *s;
580
581 /* See if the data has been slurped already .. */
582 for (s = abfd->sections; s != (asection *) NULL; s = s->next)
583 {
584 per = oasys_per_section (s);
585 if (per->initialized == true)
586 return true;
587 }
588
589 if (data->first_data_record == 0)
590 return true;
591
592 if (bfd_seek (abfd, data->first_data_record, SEEK_SET) != 0)
593 return false;
594 while (loop)
595 {
596 if (! oasys_read_record (abfd, &record))
597 return false;
598 switch (record.header.type)
599 {
600 case oasys_record_is_header_enum:
601 break;
602 case oasys_record_is_data_enum:
603 {
604
605 bfd_byte *src = record.data.data;
606 bfd_byte *end_src = ((bfd_byte *) & record) + record.header.length;
607 bfd_byte *dst_ptr;
608 bfd_byte *dst_base_ptr;
609 unsigned int relbit;
610 unsigned int count;
611 asection *section =
612 data->sections[record.data.relb & RELOCATION_SECT_BITS];
613 bfd_vma dst_offset;
614
615 per = oasys_per_section (section);
616
617 if (per->initialized == false)
618 {
619 per->data = (bfd_byte *) bfd_zalloc (abfd, section->_raw_size);
620 if (!per->data)
621 return false;
622 per->reloc_tail_ptr = (oasys_reloc_type **) & (section->relocation);
623 per->had_vma = false;
624 per->initialized = true;
625 section->reloc_count = 0;
626 section->flags = SEC_ALLOC;
627 }
628
629 dst_offset = bfd_h_get_32 (abfd, record.data.addr);
630 if (per->had_vma == false)
631 {
632 /* Take the first vma we see as the base */
633 section->vma = dst_offset;
634 per->had_vma = true;
635 }
636
637 dst_offset -= section->vma;
638
639 dst_base_ptr = oasys_per_section (section)->data;
640 dst_ptr = oasys_per_section (section)->data +
641 dst_offset;
642
643 if (src < end_src)
644 {
645 section->flags |= SEC_LOAD | SEC_HAS_CONTENTS;
646 }
647 while (src < end_src)
648 {
649 unsigned char mod_byte = *src++;
650 size_t gap = end_src - src;
651
652 count = 8;
653 if (mod_byte == 0 && gap >= 8)
654 {
655 dst_ptr[0] = src[0];
656 dst_ptr[1] = src[1];
657 dst_ptr[2] = src[2];
658 dst_ptr[3] = src[3];
659 dst_ptr[4] = src[4];
660 dst_ptr[5] = src[5];
661 dst_ptr[6] = src[6];
662 dst_ptr[7] = src[7];
663 dst_ptr += 8;
664 src += 8;
665 }
666 else
667 {
668 for (relbit = 1; count-- != 0 && src < end_src; relbit <<= 1)
669 {
670 if (relbit & mod_byte)
671 {
672 unsigned char reloc = *src;
673 /* This item needs to be relocated */
674 switch (reloc & RELOCATION_TYPE_BITS)
675 {
676 case RELOCATION_TYPE_ABS:
677
678 break;
679
680 case RELOCATION_TYPE_REL:
681 {
682 /* Relocate the item relative to the section */
683 oasys_reloc_type *r =
684 (oasys_reloc_type *)
685 bfd_alloc (abfd,
686 sizeof (oasys_reloc_type));
687 if (!r)
688 return false;
689 *(per->reloc_tail_ptr) = r;
690 per->reloc_tail_ptr = &r->next;
691 r->next = (oasys_reloc_type *) NULL;
692 /* Reference to undefined symbol */
693 src++;
694 /* There is no symbol */
695 r->symbol = 0;
696 /* Work out the howto */
697 abort ();
698 #if 0
699 r->relent.section =
700 data->sections[reloc &
701 RELOCATION_SECT_BITS];
702
703 r->relent.addend = -
704 r->relent.section->vma;
705 #endif
706 r->relent.address = dst_ptr - dst_base_ptr;
707 r->relent.howto = &howto_table[reloc >> 6];
708 r->relent.sym_ptr_ptr = (asymbol **) NULL;
709 section->reloc_count++;
710
711 /* Fake up the data to look like it's got the -ve pc in it, this makes
712 it much easier to convert into other formats. This is done by
713 hitting the addend.
714 */
715 if (r->relent.howto->pc_relative == true)
716 {
717 r->relent.addend -= dst_ptr - dst_base_ptr;
718 }
719
720
721 }
722 break;
723
724
725 case RELOCATION_TYPE_UND:
726 {
727 oasys_reloc_type *r =
728 (oasys_reloc_type *)
729 bfd_alloc (abfd,
730 sizeof (oasys_reloc_type));
731 if (!r)
732 return false;
733 *(per->reloc_tail_ptr) = r;
734 per->reloc_tail_ptr = &r->next;
735 r->next = (oasys_reloc_type *) NULL;
736 /* Reference to undefined symbol */
737 src++;
738 /* Get symbol number */
739 r->symbol = (src[0] << 8) | src[1];
740 /* Work out the howto */
741 abort ();
742
743 #if 0
744 r->relent.section = (asection
745 *) NULL;
746 #endif
747 r->relent.addend = 0;
748 r->relent.address = dst_ptr - dst_base_ptr;
749 r->relent.howto = &howto_table[reloc >> 6];
750 r->relent.sym_ptr_ptr = (asymbol **) NULL;
751 section->reloc_count++;
752
753 src += 2;
754 /* Fake up the data to look like it's got the -ve pc in it, this makes
755 it much easier to convert into other formats. This is done by
756 hitting the addend.
757 */
758 if (r->relent.howto->pc_relative == true)
759 {
760 r->relent.addend -= dst_ptr - dst_base_ptr;
761 }
762
763
764
765 }
766 break;
767 case RELOCATION_TYPE_COM:
768 BFD_FAIL ();
769 }
770 }
771 *dst_ptr++ = *src++;
772 }
773 }
774 }
775 }
776 break;
777 case oasys_record_is_local_enum:
778 case oasys_record_is_symbol_enum:
779 case oasys_record_is_section_enum:
780 break;
781 default:
782 loop = false;
783 }
784 }
785
786 return true;
787
788 }
789
790 static boolean
791 oasys_new_section_hook (abfd, newsect)
792 bfd *abfd;
793 asection *newsect;
794 {
795 newsect->used_by_bfd = (PTR)
796 bfd_alloc (abfd, sizeof (oasys_per_section_type));
797 if (!newsect->used_by_bfd)
798 return false;
799 oasys_per_section (newsect)->data = (bfd_byte *) NULL;
800 oasys_per_section (newsect)->section = newsect;
801 oasys_per_section (newsect)->offset = 0;
802 oasys_per_section (newsect)->initialized = false;
803 newsect->alignment_power = 1;
804 /* Turn the section string into an index */
805
806 sscanf (newsect->name, "%u", &newsect->target_index);
807
808 return true;
809 }
810
811
812 static long
813 oasys_get_reloc_upper_bound (abfd, asect)
814 bfd *abfd;
815 sec_ptr asect;
816 {
817 if (! oasys_slurp_section_data (abfd))
818 return -1;
819 return (asect->reloc_count + 1) * sizeof (arelent *);
820 }
821
822 static boolean
823 oasys_get_section_contents (abfd, section, location, offset, count)
824 bfd *abfd;
825 sec_ptr section;
826 PTR location;
827 file_ptr offset;
828 bfd_size_type count;
829 {
830 oasys_per_section_type *p = (oasys_per_section_type *) section->used_by_bfd;
831 oasys_slurp_section_data (abfd);
832 if (p->initialized == false)
833 {
834 (void) memset (location, 0, (int) count);
835 }
836 else
837 {
838 (void) memcpy (location, (PTR) (p->data + offset), (int) count);
839 }
840 return true;
841 }
842
843
844 long
845 oasys_canonicalize_reloc (ignore_abfd, section, relptr, symbols)
846 bfd *ignore_abfd;
847 sec_ptr section;
848 arelent **relptr;
849 asymbol **symbols;
850 {
851 unsigned int reloc_count = 0;
852 oasys_reloc_type *src = (oasys_reloc_type *) (section->relocation);
853 while (src != (oasys_reloc_type *) NULL)
854 {
855 abort ();
856
857 #if 0
858 if (src->relent.section == (asection *) NULL)
859 {
860 src->relent.sym_ptr_ptr = symbols + src->symbol;
861 }
862 #endif
863
864 *relptr++ = &src->relent;
865 src = src->next;
866 reloc_count++;
867 }
868 *relptr = (arelent *) NULL;
869 return section->reloc_count = reloc_count;
870 }
871
872
873
874
875 /* Writing */
876
877
878 /* Calculate the checksum and write one record */
879 static boolean
880 oasys_write_record (abfd, type, record, size)
881 bfd *abfd;
882 oasys_record_enum_type type;
883 oasys_record_union_type *record;
884 size_t size;
885 {
886 int checksum;
887 size_t i;
888 unsigned char *ptr;
889
890 record->header.length = size;
891 record->header.type = (int) type;
892 record->header.check_sum = 0;
893 record->header.fill = 0;
894 ptr = (unsigned char *) &record->pad[0];
895 checksum = 0;
896 for (i = 0; i < size; i++)
897 {
898 checksum += *ptr++;
899 }
900 record->header.check_sum = 0xff & (-checksum);
901 if (bfd_write ((PTR) record, 1, size, abfd) != size)
902 return false;
903 return true;
904 }
905
906
907 /* Write out all the symbols */
908 static boolean
909 oasys_write_syms (abfd)
910 bfd *abfd;
911 {
912 unsigned int count;
913 asymbol **generic = bfd_get_outsymbols (abfd);
914 unsigned int index = 0;
915 for (count = 0; count < bfd_get_symcount (abfd); count++)
916 {
917
918 oasys_symbol_record_type symbol;
919 asymbol *CONST g = generic[count];
920
921 CONST char *src = g->name;
922 char *dst = symbol.name;
923 unsigned int l = 0;
924
925 if (bfd_is_com_section (g->section))
926 {
927 symbol.relb = RELOCATION_TYPE_COM;
928 bfd_h_put_16 (abfd, index, symbol.refno);
929 index++;
930 }
931 else if (bfd_is_abs_section (g->section))
932 {
933 symbol.relb = RELOCATION_TYPE_ABS;
934 bfd_h_put_16 (abfd, 0, symbol.refno);
935
936 }
937 else if (bfd_is_und_section (g->section))
938 {
939 symbol.relb = RELOCATION_TYPE_UND;
940 bfd_h_put_16 (abfd, index, symbol.refno);
941 /* Overload the value field with the output index number */
942 index++;
943 }
944 else if (g->flags & BSF_DEBUGGING)
945 {
946 /* throw it away */
947 continue;
948 }
949 else
950 {
951 if (g->section == (asection *) NULL)
952 {
953 /* Sometime, the oasys tools give out a symbol with illegal
954 bits in it, we'll output it in the same broken way */
955
956 symbol.relb = RELOCATION_TYPE_REL | 0;
957 }
958 else
959 {
960 symbol.relb = RELOCATION_TYPE_REL | g->section->output_section->target_index;
961 }
962 bfd_h_put_16 (abfd, 0, symbol.refno);
963 }
964 #ifdef UNDERSCORE_HACK
965 if (src[l] == '_')
966 dst[l++] = '.';
967 #endif
968 while (src[l])
969 {
970 dst[l] = src[l];
971 l++;
972 }
973
974 bfd_h_put_32 (abfd, g->value, symbol.value);
975
976
977 if (g->flags & BSF_LOCAL)
978 {
979 if (! oasys_write_record (abfd,
980 oasys_record_is_local_enum,
981 (oasys_record_union_type *) & symbol,
982 offsetof (oasys_symbol_record_type,
983 name[0]) + l))
984 return false;
985 }
986 else
987 {
988 if (! oasys_write_record (abfd,
989 oasys_record_is_symbol_enum,
990 (oasys_record_union_type *) & symbol,
991 offsetof (oasys_symbol_record_type,
992 name[0]) + l))
993 return false;
994 }
995 g->value = index - 1;
996 }
997
998 return true;
999 }
1000
1001
1002 /* Write a section header for each section */
1003 static boolean
1004 oasys_write_sections (abfd)
1005 bfd *abfd;
1006 {
1007 asection *s;
1008 static oasys_section_record_type out;
1009
1010 for (s = abfd->sections; s != (asection *) NULL; s = s->next)
1011 {
1012 if (!isdigit (s->name[0]))
1013 {
1014 (*_bfd_error_handler)
1015 ("%s: can not represent section `%s' in oasys",
1016 bfd_get_filename (abfd), s->name);
1017 bfd_set_error (bfd_error_nonrepresentable_section);
1018 return false;
1019 }
1020 out.relb = RELOCATION_TYPE_REL | s->target_index;
1021 bfd_h_put_32 (abfd, s->_cooked_size, out.value);
1022 bfd_h_put_32 (abfd, s->vma, out.vma);
1023
1024 if (! oasys_write_record (abfd,
1025 oasys_record_is_section_enum,
1026 (oasys_record_union_type *) & out,
1027 sizeof (out)))
1028 return false;
1029 }
1030 return true;
1031 }
1032
1033 static boolean
1034 oasys_write_header (abfd)
1035 bfd *abfd;
1036 {
1037 /* Create and write the header */
1038 oasys_header_record_type r;
1039 size_t length = strlen (abfd->filename);
1040 if (length > (size_t) sizeof (r.module_name))
1041 {
1042 length = sizeof (r.module_name);
1043 }
1044
1045 (void) memcpy (r.module_name,
1046 abfd->filename,
1047 length);
1048 (void) memset (r.module_name + length,
1049 ' ',
1050 sizeof (r.module_name) - length);
1051
1052 r.version_number = OASYS_VERSION_NUMBER;
1053 r.rev_number = OASYS_REV_NUMBER;
1054 if (! oasys_write_record (abfd,
1055 oasys_record_is_header_enum,
1056 (oasys_record_union_type *) & r,
1057 offsetof (oasys_header_record_type,
1058 description[0])))
1059 return false;
1060
1061 return true;
1062 }
1063
1064 static boolean
1065 oasys_write_end (abfd)
1066 bfd *abfd;
1067 {
1068 oasys_end_record_type end;
1069 unsigned char null = 0;
1070 end.relb = RELOCATION_TYPE_ABS;
1071 bfd_h_put_32 (abfd, abfd->start_address, end.entry);
1072 bfd_h_put_16 (abfd, 0, end.fill);
1073 end.zero = 0;
1074 if (! oasys_write_record (abfd,
1075 oasys_record_is_end_enum,
1076 (oasys_record_union_type *) & end,
1077 sizeof (end)))
1078 return false;
1079 if (bfd_write ((PTR) & null, 1, 1, abfd) != 1)
1080 return false;
1081 return true;
1082 }
1083
1084 static int
1085 comp (ap, bp)
1086 CONST PTR ap;
1087 CONST PTR bp;
1088 {
1089 arelent *a = *((arelent **) ap);
1090 arelent *b = *((arelent **) bp);
1091 return a->address - b->address;
1092 }
1093
1094 /*
1095 Writing data..
1096
1097 */
1098 static boolean
1099 oasys_write_data (abfd)
1100 bfd *abfd;
1101 {
1102 asection *s;
1103 for (s = abfd->sections; s != (asection *) NULL; s = s->next)
1104 {
1105 if (s->flags & SEC_LOAD)
1106 {
1107 bfd_byte *raw_data = oasys_per_section (s)->data;
1108 oasys_data_record_type processed_data;
1109 bfd_size_type current_byte_index = 0;
1110 unsigned int relocs_to_go = s->reloc_count;
1111 arelent **p = s->orelocation;
1112 if (s->reloc_count != 0)
1113 {
1114 /* Sort the reloc records so it's easy to insert the relocs into the
1115 data */
1116
1117 qsort (s->orelocation,
1118 s->reloc_count,
1119 sizeof (arelent **),
1120 comp);
1121 }
1122 current_byte_index = 0;
1123 processed_data.relb = s->target_index | RELOCATION_TYPE_REL;
1124
1125 while (current_byte_index < s->_cooked_size)
1126 {
1127 /* Scan forwards by eight bytes or however much is left and see if
1128 there are any relocations going on */
1129 bfd_byte *mod = &processed_data.data[0];
1130 bfd_byte *dst = &processed_data.data[1];
1131
1132 unsigned int i = 0;
1133 *mod = 0;
1134
1135
1136 bfd_h_put_32 (abfd, s->vma + current_byte_index,
1137 processed_data.addr);
1138
1139 /* Don't start a relocation unless you're sure you can finish it
1140 within the same data record. The worst case relocation is a
1141 4-byte relocatable value which is split across two modification
1142 bytes (1 relocation byte + 2 symbol reference bytes + 2 data +
1143 1 modification byte + 2 data = 8 bytes total). That's where
1144 the magic number 8 comes from.
1145 */
1146 while (current_byte_index < s->_raw_size && dst <=
1147 &processed_data.data[sizeof (processed_data.data) - 8])
1148 {
1149
1150
1151 if (relocs_to_go != 0)
1152 {
1153 arelent *r = *p;
1154 reloc_howto_type *const how = r->howto;
1155 /* There is a relocation, is it for this byte ? */
1156 if (r->address == current_byte_index)
1157 {
1158 unsigned char rel_byte;
1159
1160 p++;
1161 relocs_to_go--;
1162
1163 *mod |= (1 << i);
1164 if (how->pc_relative)
1165 {
1166 rel_byte = RELOCATION_PCREL_BIT;
1167
1168 /* Also patch the raw data so that it doesn't have
1169 the -ve stuff any more */
1170 if (how->size != 2)
1171 {
1172 bfd_put_16 (abfd,
1173 bfd_get_16 (abfd, raw_data) +
1174 current_byte_index, raw_data);
1175 }
1176
1177 else
1178 {
1179 bfd_put_32 (abfd,
1180 bfd_get_32 (abfd, raw_data) +
1181 current_byte_index, raw_data);
1182 }
1183 }
1184 else
1185 {
1186 rel_byte = 0;
1187 }
1188 if (how->size == 2)
1189 {
1190 rel_byte |= RELOCATION_32BIT_BIT;
1191 }
1192
1193 /* Is this a section relative relocation, or a symbol
1194 relative relocation ? */
1195 abort ();
1196
1197 #if 0
1198 if (r->section != (asection *) NULL)
1199 {
1200 /* The relent has a section attached, so it must be section
1201 relative */
1202 rel_byte |= RELOCATION_TYPE_REL;
1203 rel_byte |= r->section->output_section->target_index;
1204 *dst++ = rel_byte;
1205 }
1206 else
1207 #endif
1208 {
1209 asymbol *p = *(r->sym_ptr_ptr);
1210
1211 /* If this symbol has a section attached, then it
1212 has already been resolved. Change from a symbol
1213 ref to a section ref */
1214 if (p->section != (asection *) NULL)
1215 {
1216 rel_byte |= RELOCATION_TYPE_REL;
1217 rel_byte |=
1218 p->section->output_section->target_index;
1219 *dst++ = rel_byte;
1220 }
1221 else
1222 {
1223 rel_byte |= RELOCATION_TYPE_UND;
1224 *dst++ = rel_byte;
1225 /* Next two bytes are a symbol index - we can get
1226 this from the symbol value which has been zapped
1227 into the symbol index in the table when the
1228 symbol table was written
1229 */
1230 *dst++ = p->value >> 8;
1231 *dst++ = p->value;
1232 }
1233 }
1234 #define ADVANCE { if (++i >= 8) { i = 0; mod = dst++; *mod = 0; } current_byte_index++; }
1235 /* relocations never occur from an unloadable section,
1236 so we can assume that raw_data is not NULL
1237 */
1238 *dst++ = *raw_data++;
1239 ADVANCE
1240 * dst++ = *raw_data++;
1241 ADVANCE
1242 if (how->size == 2)
1243 {
1244 *dst++ = *raw_data++;
1245 ADVANCE
1246 * dst++ = *raw_data++;
1247 ADVANCE
1248 }
1249 continue;
1250 }
1251 }
1252 /* If this is coming from an unloadable section then copy
1253 zeros */
1254 if (raw_data == NULL)
1255 {
1256 *dst++ = 0;
1257 }
1258 else
1259 {
1260 *dst++ = *raw_data++;
1261 }
1262 ADVANCE
1263 }
1264
1265 /* Don't write a useless null modification byte */
1266 if (dst == mod + 1)
1267 {
1268 --dst;
1269 }
1270
1271 if (! oasys_write_record (abfd,
1272 oasys_record_is_data_enum,
1273 ((oasys_record_union_type *)
1274 & processed_data),
1275 dst - (bfd_byte *) & processed_data))
1276 return false;
1277 }
1278 }
1279 }
1280
1281 return true;
1282 }
1283
1284 static boolean
1285 oasys_write_object_contents (abfd)
1286 bfd *abfd;
1287 {
1288 if (! oasys_write_header (abfd))
1289 return false;
1290 if (! oasys_write_syms (abfd))
1291 return false;
1292 if (! oasys_write_sections (abfd))
1293 return false;
1294 if (! oasys_write_data (abfd))
1295 return false;
1296 if (! oasys_write_end (abfd))
1297 return false;
1298 return true;
1299 }
1300
1301
1302
1303
1304 /** exec and core file sections */
1305
1306 /* set section contents is complicated with OASYS since the format is
1307 * not a byte image, but a record stream.
1308 */
1309 static boolean
1310 oasys_set_section_contents (abfd, section, location, offset, count)
1311 bfd *abfd;
1312 sec_ptr section;
1313 PTR location;
1314 file_ptr offset;
1315 bfd_size_type count;
1316 {
1317 if (count != 0)
1318 {
1319 if (oasys_per_section (section)->data == (bfd_byte *) NULL)
1320 {
1321 oasys_per_section (section)->data =
1322 (bfd_byte *) (bfd_alloc (abfd, section->_cooked_size));
1323 if (!oasys_per_section (section)->data)
1324 return false;
1325 }
1326 (void) memcpy ((PTR) (oasys_per_section (section)->data + offset),
1327 location,
1328 (size_t) count);
1329 }
1330 return true;
1331 }
1332
1333
1334
1335 /* Native-level interface to symbols. */
1336
1337 /* We read the symbols into a buffer, which is discarded when this
1338 function exits. We read the strings into a buffer large enough to
1339 hold them all plus all the cached symbol entries. */
1340
1341 static asymbol *
1342 oasys_make_empty_symbol (abfd)
1343 bfd *abfd;
1344 {
1345
1346 oasys_symbol_type *new =
1347 (oasys_symbol_type *) bfd_zalloc (abfd, sizeof (oasys_symbol_type));
1348 if (!new)
1349 return NULL;
1350 new->symbol.the_bfd = abfd;
1351 return &new->symbol;
1352 }
1353 \f
1354
1355
1356
1357 /* User should have checked the file flags; perhaps we should return
1358 BFD_NO_MORE_SYMBOLS if there are none? */
1359
1360 static bfd *
1361 oasys_openr_next_archived_file (arch, prev)
1362 bfd *arch;
1363 bfd *prev;
1364 {
1365 oasys_ar_data_type *ar = OASYS_AR_DATA (arch);
1366 oasys_module_info_type *p;
1367 /* take the next one from the arch state, or reset */
1368 if (prev == (bfd *) NULL)
1369 {
1370 /* Reset the index - the first two entries are bogus*/
1371 ar->module_index = 0;
1372 }
1373
1374 p = ar->module + ar->module_index;
1375 ar->module_index++;
1376
1377 if (ar->module_index <= ar->module_count)
1378 {
1379 if (p->abfd == (bfd *) NULL)
1380 {
1381 p->abfd = _bfd_create_empty_archive_element_shell (arch);
1382 p->abfd->origin = p->pos;
1383 p->abfd->filename = p->name;
1384
1385 /* Fixup a pointer to this element for the member */
1386 p->abfd->arelt_data = (PTR) p;
1387 }
1388 return p->abfd;
1389 }
1390 else
1391 {
1392 bfd_set_error (bfd_error_no_more_archived_files);
1393 return (bfd *) NULL;
1394 }
1395 }
1396
1397 static boolean
1398 oasys_find_nearest_line (abfd,
1399 section,
1400 symbols,
1401 offset,
1402 filename_ptr,
1403 functionname_ptr,
1404 line_ptr)
1405 bfd *abfd;
1406 asection *section;
1407 asymbol **symbols;
1408 bfd_vma offset;
1409 char **filename_ptr;
1410 char **functionname_ptr;
1411 unsigned int *line_ptr;
1412 {
1413 return false;
1414
1415 }
1416
1417 static int
1418 oasys_generic_stat_arch_elt (abfd, buf)
1419 bfd *abfd;
1420 struct stat *buf;
1421 {
1422 oasys_module_info_type *mod = (oasys_module_info_type *) abfd->arelt_data;
1423 if (mod == (oasys_module_info_type *) NULL)
1424 {
1425 bfd_set_error (bfd_error_invalid_operation);
1426 return -1;
1427 }
1428 else
1429 {
1430 buf->st_size = mod->size;
1431 buf->st_mode = 0666;
1432 return 0;
1433 }
1434 }
1435
1436 static int
1437 oasys_sizeof_headers (abfd, exec)
1438 bfd *abfd;
1439 boolean exec;
1440 {
1441 return 0;
1442 }
1443
1444 #define oasys_close_and_cleanup _bfd_generic_close_and_cleanup
1445 #define oasys_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
1446
1447 #define oasys_slurp_armap bfd_true
1448 #define oasys_slurp_extended_name_table bfd_true
1449 #define oasys_construct_extended_name_table \
1450 ((boolean (*) PARAMS ((bfd *, char **, bfd_size_type *, const char **))) \
1451 bfd_true)
1452 #define oasys_truncate_arname bfd_dont_truncate_arname
1453 #define oasys_write_armap \
1454 ((boolean (*) \
1455 PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int))) \
1456 bfd_true)
1457 #define oasys_read_ar_hdr bfd_nullvoidptr
1458 #define oasys_get_elt_at_index _bfd_generic_get_elt_at_index
1459 #define oasys_update_armap_timestamp bfd_true
1460
1461 #define oasys_bfd_is_local_label bfd_generic_is_local_label
1462 #define oasys_get_lineno _bfd_nosymbols_get_lineno
1463 #define oasys_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
1464 #define oasys_read_minisymbols _bfd_generic_read_minisymbols
1465 #define oasys_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
1466
1467 #define oasys_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
1468
1469 #define oasys_set_arch_mach bfd_default_set_arch_mach
1470
1471 #define oasys_get_section_contents_in_window \
1472 _bfd_generic_get_section_contents_in_window
1473
1474 #define oasys_bfd_get_relocated_section_contents \
1475 bfd_generic_get_relocated_section_contents
1476 #define oasys_bfd_relax_section bfd_generic_relax_section
1477 #define oasys_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
1478 #define oasys_bfd_link_add_symbols _bfd_generic_link_add_symbols
1479 #define oasys_bfd_final_link _bfd_generic_final_link
1480 #define oasys_bfd_link_split_section _bfd_generic_link_split_section
1481
1482 /*SUPPRESS 460 */
1483 const bfd_target oasys_vec =
1484 {
1485 "oasys", /* name */
1486 bfd_target_oasys_flavour,
1487 BFD_ENDIAN_BIG, /* target byte order */
1488 BFD_ENDIAN_BIG, /* target headers byte order */
1489 (HAS_RELOC | EXEC_P | /* object flags */
1490 HAS_LINENO | HAS_DEBUG |
1491 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1492 (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1493 | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1494 0, /* leading underscore */
1495 ' ', /* ar_pad_char */
1496 16, /* ar_max_namelen */
1497 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1498 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1499 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
1500 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1501 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1502 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
1503
1504 {_bfd_dummy_target,
1505 oasys_object_p, /* bfd_check_format */
1506 oasys_archive_p,
1507 _bfd_dummy_target,
1508 },
1509 { /* bfd_set_format */
1510 bfd_false,
1511 oasys_mkobject,
1512 _bfd_generic_mkarchive,
1513 bfd_false
1514 },
1515 { /* bfd_write_contents */
1516 bfd_false,
1517 oasys_write_object_contents,
1518 _bfd_write_archive_contents,
1519 bfd_false,
1520 },
1521
1522 BFD_JUMP_TABLE_GENERIC (oasys),
1523 BFD_JUMP_TABLE_COPY (_bfd_generic),
1524 BFD_JUMP_TABLE_CORE (_bfd_nocore),
1525 BFD_JUMP_TABLE_ARCHIVE (oasys),
1526 BFD_JUMP_TABLE_SYMBOLS (oasys),
1527 BFD_JUMP_TABLE_RELOCS (oasys),
1528 BFD_JUMP_TABLE_WRITE (oasys),
1529 BFD_JUMP_TABLE_LINK (oasys),
1530 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1531
1532 (PTR) 0
1533 };