* mmo.c (mmo_write_section_description): New function broken out
[deliverable/binutils-gdb.git] / bfd / mmo.c
CommitLineData
3c3bdf30 1/* BFD back-end for mmo objects (MMIX-specific object-format).
72adc230 2 Copyright 2001, 2002, 2003, 2004
3c3bdf30
NC
3 Free Software Foundation, Inc.
4 Written by Hans-Peter Nilsson (hp@bitrange.com).
5 Infrastructure and other bits originally copied from srec.c and
6 binary.c.
7
8This file is part of BFD, the Binary File Descriptor library.
9
10This program is free software; you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation; either version 2 of the License, or
13(at your option) any later version.
14
15This program is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23
24/*
25SECTION
26 mmo backend
27
28 The mmo object format is used exclusively together with Professor
29 Donald E.@: Knuth's educational 64-bit processor MMIX. The simulator
6eeb40b2
HPN
30 @command{mmix} which is available at
31 @url{http://www-cs-faculty.stanford.edu/~knuth/programs/mmix.tar.gz}
3c3bdf30 32 understands this format. That package also includes a combined
6eeb40b2 33 assembler and linker called @command{mmixal}. The mmo format has
3c3bdf30
NC
34 no advantages feature-wise compared to e.g. ELF. It is a simple
35 non-relocatable object format with no support for archives or
36 debugging information, except for symbol value information and
37 line numbers (which is not yet implemented in BFD). See
6eeb40b2 38 @url{http://www-cs-faculty.stanford.edu/~knuth/mmix.html} for more
3c3bdf30
NC
39 information about MMIX. The ELF format is used for intermediate
40 object files in the BFD implementation.
41
42@c We want to xref the symbol table node. A feature in "chew"
43@c requires that "commands" do not contain spaces in the
44@c arguments. Hence the hyphen in "Symbol-table".
45@menu
46@* File layout::
47@* Symbol-table::
48@* mmo section mapping::
49@end menu
50
51INODE
52File layout, Symbol-table, mmo, mmo
53SUBSECTION
54 File layout
55
56 The mmo file contents is not partitioned into named sections as
57 with e.g.@: ELF. Memory areas is formed by specifying the
58 location of the data that follows. Only the memory area
59 @samp{0x0000@dots{}00} to @samp{0x01ff@dots{}ff} is executable, so
60 it is used for code (and constants) and the area
61 @samp{0x2000@dots{}00} to @samp{0x20ff@dots{}ff} is used for
62 writable data. @xref{mmo section mapping}.
63
830866af
HPN
64 There is provision for specifying ``special data'' of 65536
65 different types. We use type 80 (decimal), arbitrarily chosen the
66 same as the ELF <<e_machine>> number for MMIX, filling it with
67 section information normally found in ELF objects. @xref{mmo
68 section mapping}.
69
3c3bdf30
NC
70 Contents is entered as 32-bit words, xor:ed over previous
71 contents, always zero-initialized. A word that starts with the
72 byte @samp{0x98} forms a command called a @samp{lopcode}, where
73 the next byte distinguished between the thirteen lopcodes. The
74 two remaining bytes, called the @samp{Y} and @samp{Z} fields, or
75 the @samp{YZ} field (a 16-bit big-endian number), are used for
76 various purposes different for each lopcode. As documented in
6eeb40b2 77 @url{http://www-cs-faculty.stanford.edu/~knuth/mmixal-intro.ps.gz},
3c3bdf30
NC
78 the lopcodes are:
79
3c3bdf30
NC
80 @table @code
81 @item lop_quote
82 0x98000001. The next word is contents, regardless of whether it
83 starts with 0x98 or not.
84
85 @item lop_loc
86 0x9801YYZZ, where @samp{Z} is 1 or 2. This is a location
87 directive, setting the location for the next data to the next
88 32-bit word (for @math{Z = 1}) or 64-bit word (for @math{Z = 2}),
89 plus @math{Y * 2^56}. Normally @samp{Y} is 0 for the text segment
90 and 2 for the data segment.
91
92 @item lop_skip
93 0x9802YYZZ. Increase the current location by @samp{YZ} bytes.
94
95 @item lop_fixo
96 0x9803YYZZ, where @samp{Z} is 1 or 2. Store the current location
97 as 64 bits into the location pointed to by the next 32-bit
98 (@math{Z = 1}) or 64-bit (@math{Z = 2}) word, plus @math{Y *
99 2^56}.
100
101 @item lop_fixr
102 0x9804YYZZ. @samp{YZ} is stored into the current location plus
103 @math{2 - 4 * YZ}.
104
105 @item lop_fixrx
106 0x980500ZZ. @samp{Z} is 16 or 24. A value @samp{L} derived from
107 the following 32-bit word are used in a manner similar to
108 @samp{YZ} in lop_fixr: it is xor:ed into the current location
109 minus @math{4 * L}. The first byte of the word is 0 or 1. If it
110 is 1, then @math{L = (@var{lowest 24 bits of word}) - 2^Z}, if 0,
111 then @math{L = (@var{lowest 24 bits of word})}.
112
113 @item lop_file
114 0x9806YYZZ. @samp{Y} is the file number, @samp{Z} is count of
115 32-bit words. Set the file number to @samp{Y} and the line
116 counter to 0. The next @math{Z * 4} bytes contain the file name,
117 padded with zeros if the count is not a multiple of four. The
118 same @samp{Y} may occur multiple times, but @samp{Z} must be 0 for
119 all but the first occurrence.
120
121 @item lop_line
122 0x9807YYZZ. @samp{YZ} is the line number. Together with
123 lop_file, it forms the source location for the next 32-bit word.
124 Note that for each non-lopcode 32-bit word, line numbers are
125 assumed incremented by one.
126
127 @item lop_spec
128 0x9808YYZZ. @samp{YZ} is the type number. Data until the next
129 lopcode other than lop_quote forms special data of type @samp{YZ}.
130 @xref{mmo section mapping}.
131
132 Other types than 80, (or type 80 with a content that does not
133 parse) is stored in sections named <<.MMIX.spec_data.@var{n}>>
134 where @var{n} is the @samp{YZ}-type. The flags for such a
135 sections say not to allocate or load the data. The vma is 0.
136 Contents of multiple occurrences of special data @var{n} is
137 concatenated to the data of the previous lop_spec @var{n}s. The
138 location in data or code at which the lop_spec occurred is lost.
139
140 @item lop_pre
141 0x980901ZZ. The first lopcode in a file. The @samp{Z} field forms the
142 length of header information in 32-bit words, where the first word
143 tells the time in seconds since @samp{00:00:00 GMT Jan 1 1970}.
144
145 @item lop_post
146 0x980a00ZZ. @math{Z > 32}. This lopcode follows after all
147 content-generating lopcodes in a program. The @samp{Z} field
148 denotes the value of @samp{rG} at the beginning of the program.
149 The following @math{256 - Z} big-endian 64-bit words are loaded
150 into global registers @samp{$G} @dots{} @samp{$255}.
151
152 @item lop_stab
153 0x980b0000. The next-to-last lopcode in a program. Must follow
154 immediately after the lop_post lopcode and its data. After this
155 lopcode follows all symbols in a compressed format
156 (@pxref{Symbol-table}).
157
158 @item lop_end
159 0x980cYYZZ. The last lopcode in a program. It must follow the
160 lop_stab lopcode and its data. The @samp{YZ} field contains the
161 number of 32-bit words of symbol table information after the
162 preceding lop_stab lopcode.
163 @end table
164
165 Note that the lopcode "fixups"; <<lop_fixr>>, <<lop_fixrx>> and
166 <<lop_fixo>> are not generated by BFD, but are handled. They are
167 generated by <<mmixal>>.
168
169EXAMPLE
170 This trivial one-label, one-instruction file:
171
172| :Main TRAP 1,2,3
173
174 can be represented this way in mmo:
175
176| 0x98090101 - lop_pre, one 32-bit word with timestamp.
177| <timestamp>
178| 0x98010002 - lop_loc, text segment, using a 64-bit address.
179| Note that mmixal does not emit this for the file above.
180| 0x00000000 - Address, high 32 bits.
181| 0x00000000 - Address, low 32 bits.
182| 0x98060002 - lop_file, 2 32-bit words for file-name.
183| 0x74657374 - "test"
184| 0x2e730000 - ".s\0\0"
185| 0x98070001 - lop_line, line 1.
186| 0x00010203 - TRAP 1,2,3
187| 0x980a00ff - lop_post, setting $255 to 0.
188| 0x00000000
189| 0x00000000
190| 0x980b0000 - lop_stab for ":Main" = 0, serial 1.
191| 0x203a4040 @xref{Symbol-table}.
192| 0x10404020
193| 0x4d206120
194| 0x69016e00
195| 0x81000000
196| 0x980c0005 - lop_end; symbol table contained five 32-bit words. */
197
198#include "bfd.h"
199#include "sysdep.h"
200#include "libbfd.h"
201#include "libiberty.h"
202#include "elf/mmix.h"
203#include "opcode/mmix.h"
3c3bdf30
NC
204
205#define LOP 0x98
206#define LOP_QUOTE 0
207#define LOP_LOC 1
208#define LOP_SKIP 2
209#define LOP_FIXO 3
210#define LOP_FIXR 4
211#define LOP_FIXRX 5
212#define LOP_FILE 6
213#define LOP_LINE 7
214#define LOP_SPEC 8
215#define LOP_PRE 9
216#define LOP_POST 10
217#define LOP_STAB 11
218#define LOP_END 12
219
220#define LOP_QUOTE_NEXT ((LOP << 24) | (LOP_QUOTE << 16) | 1)
221#define SPEC_DATA_SECTION 80
222#define LOP_SPEC_SECTION \
223 ((LOP << 24) | (LOP_SPEC << 16) | SPEC_DATA_SECTION)
224
225/* Must be a power of two. If you change this to be >= 64k, you need a
226 new test-case; the ld test b-loc64k.d touches chunk-size problem areas. */
227#define MMO_SEC_CONTENTS_CHUNK_SIZE (1 << 15)
228
229/* An arbitrary number for the maximum length section name size. */
230#define MAX_SECTION_NAME_SIZE (1024 * 1024)
231
232/* A quite arbitrary number for the maximum length section size. */
233#define MAX_ARTIFICIAL_SECTION_SIZE (1024 * 1024 * 1024)
234
235#define MMO3_WCHAR 0x80
236#define MMO3_LEFT 0x40
237#define MMO3_MIDDLE 0x20
238#define MMO3_RIGHT 0x10
239#define MMO3_TYPEBITS 0xf
240#define MMO3_REGQUAL_BITS 0xf
241#define MMO3_UNDEF 2
242#define MMO3_DATA 8
243#define MMO3_SYMBITS 0x2f
244
245/* Put these everywhere in new code. */
246#define FATAL_DEBUG \
247 _bfd_abort (__FILE__, __LINE__, \
248 "Internal: Non-debugged code (test-case missing)")
249
250#define BAD_CASE(x) \
251 _bfd_abort (__FILE__, __LINE__, \
252 "bad case for " #x)
253
254enum mmo_sym_type { mmo_reg_sym, mmo_undef_sym, mmo_data_sym, mmo_abs_sym};
255
256/* When scanning the mmo file, a linked list of mmo_symbol
257 structures is built to represent the symbol table (if there is
258 one). */
259
260struct mmo_symbol
261 {
262 struct mmo_symbol *next;
3f9c735e 263 const char *name;
3c3bdf30
NC
264 bfd_vma value;
265 enum mmo_sym_type sym_type;
266 unsigned int serno;
267 };
268
269struct mmo_data_list_struct
270 {
271 struct mmo_data_list_struct *next;
272 bfd_vma where;
273 bfd_size_type size;
274 bfd_size_type allocated_size;
275 bfd_byte data[1];
276 };
277
278typedef struct mmo_data_list_struct mmo_data_list_type;
279
280struct mmo_symbol_trie
281 {
282 struct mmo_symbol_trie *left;
283 struct mmo_symbol_trie *right;
284 struct mmo_symbol_trie *middle;
285
286 bfd_byte symchar;
287
288 /* A zero name means there's nothing here. */
289 struct mmo_symbol sym;
290 };
291
292/* The mmo tdata information. */
293
294struct mmo_data_struct
295 {
296 struct mmo_symbol *symbols;
297 struct mmo_symbol *symtail;
298 asymbol *csymbols;
299
300 /* File representation of time (NULL) when this file was created. */
301 bfd_byte created[4];
302
303 /* When we're reading bytes recursively, check this occasionally.
304 Also holds write errors. */
b34976b6 305 bfd_boolean have_error;
3c3bdf30
NC
306
307 /* Max symbol length that may appear in the lop_stab table. Note that
308 this table might just hold a subset of symbols for not-really large
309 programs, as it can only be 65536 * 4 bytes large. */
310 int max_symbol_length;
311
312 /* Here's the symbol we build in lop_stab. */
313 char *lop_stab_symbol;
314
315 /* Index into lop_stab_symbol for the next character when parsing the
316 symbol information. */
317 int symbol_position;
318
319 /* When creating arbitrary sections, we need to count section numbers. */
320 int sec_no;
321
322 /* When writing or reading byte-wise, we need to count the bytes
323 within a 32-bit word. */
324 int byte_no;
325
326 /* We also need a buffer to hold the bytes we count reading or writing. */
327 bfd_byte buf[4];
328 };
329
330typedef struct mmo_data_struct tdata_type;
331
332struct mmo_section_data_struct
333 {
334 mmo_data_list_type *head;
335 mmo_data_list_type *tail;
336 };
337
68bfbfcc
AM
338#define mmo_section_data(sec) \
339 ((struct mmo_section_data_struct *) (sec)->used_by_bfd)
340
3c3bdf30
NC
341/* These structures are used in bfd_map_over_sections constructs. */
342
343/* Used when writing out sections; all but the register contents section
344 which is stored in reg_section. */
345struct mmo_write_sec_info
346 {
347 asection *reg_section;
b34976b6 348 bfd_boolean retval;
3c3bdf30
NC
349 };
350
351/* Used when trying to find a section corresponding to addr. */
352struct mmo_find_sec_info
353 {
354 asection *sec;
355 bfd_vma addr;
356 };
357
b34976b6
AM
358static bfd_boolean mmo_bfd_copy_private_bfd_data
359 PARAMS ((bfd *, bfd *));
3c3bdf30
NC
360static void mmo_write_section_unless_reg_contents
361 PARAMS ((bfd *, asection *, PTR));
b34976b6
AM
362static void mmo_find_sec_w_addr
363 PARAMS ((bfd *, asection *, PTR));
364static void mmo_find_sec_w_addr_grow
365 PARAMS ((bfd *, asection *, PTR));
366static asection *mmo_make_section
367 PARAMS ((bfd *, const char *));
368static void mmo_get_symbol_info
369 PARAMS ((bfd *, asymbol *, symbol_info *));
3c3bdf30 370static void mmo_print_symbol
b34976b6
AM
371 PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type));
372static void mmo_init
373 PARAMS ((void));
374static bfd_boolean mmo_mkobject
375 PARAMS ((bfd *));
376static bfd_boolean mmo_scan
377 PARAMS ((bfd *));
378static asection *mmo_decide_section
379 PARAMS ((bfd *, bfd_vma));
380static asection *mmo_get_generic_spec_data_section
381 PARAMS ((bfd *, int));
382static asection *mmo_get_spec_section
383 PARAMS ((bfd *, int));
384static INLINE bfd_byte *mmo_get_loc
385 PARAMS ((asection *, bfd_vma, int));
386static void mmo_xore_64
387 PARAMS ((asection *, bfd_vma vma, bfd_vma value));
388static void mmo_xore_32
389 PARAMS ((asection *, bfd_vma vma, unsigned int));
390static void mmo_xore_16
391 PARAMS ((asection *, bfd_vma vma, unsigned int));
392static const bfd_target *mmo_object_p
393 PARAMS ((bfd *));
394static void mmo_map_set_sizes
395 PARAMS ((bfd *, asection *, PTR));
396static bfd_boolean mmo_get_symbols
397 PARAMS ((bfd *));
398static bfd_boolean mmo_create_symbol
399 PARAMS ((bfd *, const char *, bfd_vma, enum mmo_sym_type, unsigned int));
400static bfd_boolean mmo_get_section_contents
3c3bdf30 401 PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
b34976b6
AM
402static long mmo_get_symtab_upper_bound
403 PARAMS ((bfd *));
6cee3f79 404static long mmo_canonicalize_symtab
b34976b6
AM
405 PARAMS ((bfd *, asymbol **));
406static void mmo_get_symbol_info
407 PARAMS ((bfd *, asymbol *, symbol_info *));
408static void mmo_print_symbol
409 PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type));
410static bfd_boolean mmo_set_section_contents
0f867abe 411 PARAMS ((bfd *, sec_ptr, const PTR, file_ptr, bfd_size_type));
b34976b6
AM
412static int mmo_sizeof_headers
413 PARAMS ((bfd *, bfd_boolean));
414static long mmo_get_reloc_upper_bound
415 PARAMS ((bfd *, asection *));
3c3bdf30 416
b34976b6
AM
417static bfd_boolean mmo_internal_write_header
418 PARAMS ((bfd *));
419static bfd_boolean mmo_internal_write_post
420 PARAMS ((bfd *, int, asection *));
421static bfd_boolean mmo_internal_add_3_sym
422 PARAMS ((bfd *, struct mmo_symbol_trie *, const struct mmo_symbol *));
3c3bdf30 423static unsigned int mmo_internal_3_length
b34976b6 424 PARAMS ((bfd *, struct mmo_symbol_trie *));
3c3bdf30 425static void mmo_internal_3_dump
b34976b6
AM
426 PARAMS ((bfd *, struct mmo_symbol_trie *));
427static void mmo_beb128_out
428 PARAMS ((bfd *, int, int));
429static bfd_boolean mmo_internal_write_section
3c3bdf30 430 PARAMS ((bfd *, asection *));
b34976b6
AM
431static void mmo_write_tetra
432 PARAMS ((bfd *, unsigned int));
433static void mmo_write_tetra_raw
434 PARAMS ((bfd *, unsigned int));
435static void mmo_write_octa
436 PARAMS ((bfd *, bfd_vma));
437static void mmo_write_octa_raw
438 PARAMS ((bfd *, bfd_vma));
439static bfd_boolean mmo_write_chunk
3f9c735e 440 PARAMS ((bfd *, const bfd_byte *, unsigned int));
b34976b6
AM
441static bfd_boolean mmo_flush_chunk
442 PARAMS ((bfd *));
443static bfd_boolean mmo_write_loc_chunk
3f9c735e 444 PARAMS ((bfd *, bfd_vma, const bfd_byte *, unsigned int, bfd_vma *));
b34976b6 445static bfd_boolean mmo_write_chunk_list
3c3bdf30 446 PARAMS ((bfd *, mmo_data_list_type *));
b34976b6
AM
447static bfd_boolean mmo_write_loc_chunk_list
448 PARAMS ((bfd *, mmo_data_list_type *));
449static bfd_boolean mmo_write_symbols_and_terminator
450 PARAMS ((bfd *));
451static flagword mmo_sec_flags_from_bfd_flags
452 PARAMS ((flagword));
453static flagword bfd_sec_flags_from_mmo_flags
454 PARAMS ((flagword));
455static bfd_byte mmo_get_byte
456 PARAMS ((bfd *));
457static void mmo_write_byte
458 PARAMS ((bfd *, bfd_byte));
459static bfd_boolean mmo_new_section_hook
460 PARAMS ((bfd *, asection *));
461static int mmo_sort_mmo_symbols
462 PARAMS ((const PTR, const PTR));
463static bfd_boolean mmo_write_object_contents
464 PARAMS ((bfd *));
3c3bdf30
NC
465static long mmo_canonicalize_reloc
466 PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));
aa69fe43
HPN
467static bfd_boolean mmo_write_section_description
468 PARAMS ((bfd *, asection *));
469static bfd_boolean mmo_has_leading_or_trailing_zero_tetra_p
470 PARAMS ((bfd *, asection *));
3c3bdf30
NC
471
472/* Global "const" variables initialized once. Must not depend on
473 particular input or caller; put such things into the bfd or elsewhere.
474 Look ma, no static per-invocation data! */
475
476static unsigned
477char valid_mmo_symbol_character_set[/* A-Z a-z (we assume consecutive
478 codes; sorry EBCDIC:ers!). */
479 + 'Z' - 'A' + 1 + 'z' - 'a' + 1
480 /* Digits. */
481 + 10
482 /* ':' and '_'. */
483 + 1 + 1
484 /* Codes higher than 126. */
485 + 256 - 126
486 /* Ending zero. */
487 + 1];
488
489
490/* Get section SECNAME or create one if it doesn't exist. When creating
491 one, new memory for the name is allocated. */
492
493static asection *
494mmo_make_section (abfd, secname)
495 bfd *abfd;
3f9c735e 496 const char *secname;
3c3bdf30
NC
497{
498 asection *sec = bfd_get_section_by_name (abfd, secname);
499
500 if (sec == NULL)
501 {
502 char *newsecname = strdup (secname);
503
504 if (newsecname == NULL)
505 {
506 (*_bfd_error_handler)
507 (_("%s: No core to allocate section name %s\n"),
508 bfd_get_filename (abfd), secname);
509 bfd_set_error (bfd_error_system_call);
510 return NULL;
511 }
512 sec = bfd_make_section (abfd, newsecname);
513 }
514
515 return sec;
516}
517
518/* Nothing to do, but keep as a placeholder if we need it.
519 Note that state that might differ between bfd:s must not be initialized
520 here, nor must it be static. Add it to tdata information instead. */
521
522static void
523mmo_init ()
524{
b34976b6 525 static bfd_boolean inited = FALSE;
3c3bdf30
NC
526 int i = 0;
527 int j = 0;
528 static const char letters[]
529 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789:_";
530
82e51918 531 if (inited)
930b4cb2 532 return;
b34976b6 533 inited = TRUE;
3c3bdf30
NC
534
535 /* Fill in the set of valid symbol characters. */
536 strcpy (valid_mmo_symbol_character_set, letters);
537 i = strlen (letters);
538
539 for (j = 126; j < 256; j++)
540 valid_mmo_symbol_character_set[i++] = j;
541}
542
543/* Check whether an existing file is an mmo file. */
544
3f9c735e 545static const bfd_target *
3c3bdf30
NC
546mmo_object_p (abfd)
547 bfd *abfd;
548{
549 struct stat statbuf;
550 bfd_byte b[4];
551
552 mmo_init ();
553
554 if (bfd_stat (abfd, &statbuf) < 0
555 || bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
556 || bfd_bread (b, 4, abfd) != 4)
557 goto bad_final;
558
559 /* All mmo files are a multiple of four bytes long.
560 Only recognize version one. */
561 if ((statbuf.st_size % 4) != 0
562 || b[0] != LOP || b[1] != LOP_PRE || b[2] != 1)
563 goto bad_format;
564
565 /* Get the last 32-bit word. */
566 if (bfd_seek (abfd, (file_ptr) statbuf.st_size - 4, SEEK_SET) != 0
567 || bfd_bread (b, 4, abfd) != 4)
568 goto bad_final;
569
570 /* Check if the file ends in a lop_end lopcode. */
571 if (b[0] != LOP || b[1] != LOP_END || ! mmo_mkobject (abfd))
572 goto bad_format;
573
574 /* Compute an upper bound on the max symbol length. Not really
575 important as all of the symbol information can only be 256k. */
576 abfd->tdata.mmo_data->max_symbol_length = (b[2] * 256 + b[3]) * 4;
577 abfd->tdata.mmo_data->lop_stab_symbol
578 = bfd_malloc (abfd->tdata.mmo_data->max_symbol_length + 1);
579
580 if (abfd->tdata.mmo_data->lop_stab_symbol == NULL)
581 {
582 (*_bfd_error_handler)
583 (_("%s: No core to allocate a symbol %d bytes long\n"),
584 bfd_get_filename (abfd), abfd->tdata.mmo_data->max_symbol_length);
585 goto bad_final;
586 }
587
588 /* Read in everything. */
589 if (! mmo_scan (abfd))
590 goto bad_format_free;
591
592 if (abfd->symcount > 0)
593 abfd->flags |= HAS_SYMS;
594
595 /* You'll have to tweak this if you want to use this format for other
596 arches (not recommended due to its small-size limitations). Look at
597 the ELF format for how to make it target-generic. */
598 if (! bfd_default_set_arch_mach (abfd, bfd_arch_mmix, 0))
599 goto bad_format_free;
600
601 return abfd->xvec;
602
603 bad_format_free:
604 free (abfd->tdata.mmo_data->lop_stab_symbol);
605 bad_format:
606 bfd_set_error (bfd_error_wrong_format);
607 bad_final:
608 return NULL;
609}
610
611/* Set up the mmo tdata information. */
612
b34976b6 613static bfd_boolean
3c3bdf30
NC
614mmo_mkobject (abfd)
615 bfd *abfd;
616{
617 mmo_init ();
618
619 if (abfd->tdata.mmo_data == NULL)
620 {
621 time_t created;
622
623 /* All fields are zero-initialized, so we don't have to explicitly
624 initialize most. */
625 tdata_type *tdata = (tdata_type *) bfd_zmalloc (sizeof (tdata_type));
626 if (tdata == NULL)
b34976b6 627 return FALSE;
3c3bdf30
NC
628
629 created = time (NULL);
630 bfd_put_32 (abfd, created, tdata->created);
631
632 abfd->tdata.mmo_data = tdata;
633 }
634
b34976b6 635 return TRUE;
3c3bdf30
NC
636}
637
b34976b6 638static bfd_boolean
3c3bdf30
NC
639mmo_bfd_copy_private_bfd_data (ibfd, obfd)
640 bfd *ibfd;
641 bfd *obfd;
642{
643 if (bfd_get_flavour (ibfd) != bfd_target_mmo_flavour
644 || bfd_get_flavour (obfd) != bfd_target_mmo_flavour)
b34976b6 645 return TRUE;
3c3bdf30
NC
646
647 /* Copy the time the copied-from file was created. If people want the
648 time the file was last *modified*, they have that in the normal file
649 information. */
650 memcpy (obfd->tdata.mmo_data->created, ibfd->tdata.mmo_data->created,
651 sizeof (obfd->tdata.mmo_data->created));
b34976b6 652 return TRUE;
3c3bdf30
NC
653}
654
655/* Helper functions for mmo_decide_section, used through
656 bfd_map_over_sections. */
657
658static void
659mmo_find_sec_w_addr (abfd, sec, p)
660 bfd *abfd ATTRIBUTE_UNUSED;
661 asection *sec;
662 PTR p;
663{
664 struct mmo_find_sec_info *infop = (struct mmo_find_sec_info *) p;
665 bfd_vma vma = bfd_get_section_vma (abfd, sec);
666
667 /* Ignore sections that aren't loaded. */
668 if ((bfd_get_section_flags (abfd, sec) & (SEC_LOAD | SEC_ALLOC))
669 != (SEC_LOAD | SEC_ALLOC))
670 return;
671
eea6121a 672 if (infop->addr >= vma && infop->addr < vma + sec->size)
3c3bdf30
NC
673 infop->sec = sec;
674}
675
676static void
677mmo_find_sec_w_addr_grow (abfd, sec, p)
678 bfd *abfd ATTRIBUTE_UNUSED;
679 asection *sec;
680 PTR p;
681{
682 struct mmo_find_sec_info *infop = (struct mmo_find_sec_info *) p;
683 bfd_vma vma = bfd_get_section_vma (abfd, sec);
684
685 /* Ignore sections that aren't loaded. */
686 if ((bfd_get_section_flags (abfd, sec) & (SEC_LOAD | SEC_ALLOC))
687 != (SEC_LOAD | SEC_ALLOC))
688 return;
689
690 if (infop->addr >= vma && infop->addr < vma + MAX_ARTIFICIAL_SECTION_SIZE)
691 infop->sec = sec;
692}
693
694/* Find a section that corresponds to a VMA. Automatically create .text
695 or .data and set current section to it, depending on what vma. If we
696 can't deduce a section, make one up as ".MMIX.sec.N", where N is an
697 increasing number. */
698
699static asection *
700mmo_decide_section (abfd, vma)
701 bfd *abfd;
702 bfd_vma vma;
703{
704 asection *sec = NULL;
705 char sec_name[sizeof (".MMIX.sec.") + 20];
706 struct mmo_find_sec_info info;
707
708 info.addr = vma;
709 info.sec = NULL;
710
711 /* First see if there's a section that would match exactly. */
712 bfd_map_over_sections (abfd, mmo_find_sec_w_addr, &info);
713
714 if (info.sec != NULL)
715 return info.sec;
716
717 /* If there's no such section, try and expand one of the existing ones,
718 up to a limit. Make sure we have .text and .data before we try that;
719 create them corresponding to expected addresses and set flags to make
720 them match the "loaded and with contents" expectation. */
721 if ((vma >> 56) == 0)
722 {
723 sec = bfd_make_section_old_way (abfd, MMO_TEXT_SECTION_NAME);
724
725 if (sec == NULL)
726 return NULL;
727
728 if (! sec->user_set_vma)
729 bfd_set_section_vma (abfd, sec, vma);
730 if (! bfd_set_section_flags (abfd, sec,
731 bfd_get_section_flags (abfd, sec)
732 | SEC_CODE | SEC_LOAD | SEC_ALLOC))
733 return NULL;
734 }
735 else if ((vma >> 56) == 0x20)
736 {
737 sec = bfd_make_section_old_way (abfd, MMO_DATA_SECTION_NAME);
738
739 if (sec == NULL)
740 return NULL;
741
742 if (! sec->user_set_vma)
743 bfd_set_section_vma (abfd, sec, vma);
744 if (! bfd_set_section_flags (abfd, sec,
745 bfd_get_section_flags (abfd, sec)
746 | SEC_LOAD | SEC_ALLOC))
747 return NULL;
748 }
749
750 bfd_map_over_sections (abfd, mmo_find_sec_w_addr_grow, &info);
751
752 if (info.sec != NULL)
753 return info.sec;
754
755 /* If there's still no suitable section, make a new one. */
756 sprintf (sec_name, ".MMIX.sec.%d", abfd->tdata.mmo_data->sec_no++);
757 sec = mmo_make_section (abfd, sec_name);
758 if (! sec->user_set_vma)
759 bfd_set_section_vma (abfd, sec, vma);
760
761 if (! bfd_set_section_flags (abfd, sec,
762 bfd_get_section_flags (abfd, sec)
763 | SEC_LOAD | SEC_ALLOC))
764 return NULL;
765 return sec;
766}
767
768/* Xor in a 64-bit value VALUE at VMA. */
769
770static INLINE void
771mmo_xore_64 (sec, vma, value)
772 asection *sec;
773 bfd_vma vma;
774 bfd_vma value;
775{
776 bfd_byte *loc = mmo_get_loc (sec, vma, 8);
777 bfd_vma prev = bfd_get_64 (sec->owner, loc);
778
779 value ^= prev;
780 bfd_put_64 (sec->owner, value, loc);
781}
782
783/* Xor in a 32-bit value VALUE at VMA. */
784
785static INLINE void
786mmo_xore_32 (sec, vma, value)
787 asection *sec;
788 bfd_vma vma;
789 unsigned int value;
790{
791 bfd_byte *loc = mmo_get_loc (sec, vma, 4);
792 unsigned int prev = bfd_get_32 (sec->owner, loc);
793
794 value ^= prev;
795 bfd_put_32 (sec->owner, value, loc);
796}
797
798/* Xor in a 16-bit value VALUE at VMA. */
799
800static INLINE void
801mmo_xore_16 (sec, vma, value)
802 asection *sec;
803 bfd_vma vma;
804 unsigned int value;
805{
806 bfd_byte *loc = mmo_get_loc (sec, vma, 2);
807 unsigned int prev = bfd_get_16 (sec->owner, loc);
808
809 value ^= prev;
810 bfd_put_16 (sec->owner, value, loc);
811}
812
813/* Write a 32-bit word to output file, no lop_quote generated. */
814
815static INLINE void
816mmo_write_tetra_raw (abfd, value)
817 bfd *abfd;
818 unsigned int value;
819{
820 bfd_byte buf[4];
821
822 bfd_put_32 (abfd, value, buf);
823
824 if (bfd_bwrite ((PTR) buf, 4, abfd) != 4)
b34976b6 825 abfd->tdata.mmo_data->have_error = TRUE;
3c3bdf30
NC
826}
827
828/* Write a 32-bit word to output file; lop_quote if necessary. */
829
830static INLINE void
831mmo_write_tetra (abfd, value)
832 bfd *abfd;
833 unsigned int value;
834{
835 if (((value >> 24) & 0xff) == LOP)
836 mmo_write_tetra_raw (abfd, LOP_QUOTE_NEXT);
837
838 mmo_write_tetra_raw (abfd, value);
839}
840
841/* Write a 64-bit word to output file, perhaps with lop_quoting. */
842
843static INLINE void
844mmo_write_octa (abfd, value)
845 bfd *abfd;
846 bfd_vma value;
847{
848 mmo_write_tetra (abfd, (unsigned int) (value >> 32));
849 mmo_write_tetra (abfd, (unsigned int) value);
850}
851
852/* Write a 64-bit word to output file, without lop_quoting. */
853
854static INLINE void
855mmo_write_octa_raw (abfd, value)
856 bfd *abfd;
857 bfd_vma value;
858{
859 mmo_write_tetra_raw (abfd, (unsigned int) (value >> 32));
860 mmo_write_tetra_raw (abfd, (unsigned int) value);
861}
862
dfa36a69
HPN
863/* Write quoted contents. Intended to be called multiple times in
864 sequence, followed by a call to mmo_flush_chunk. */
3c3bdf30 865
b34976b6 866static INLINE bfd_boolean
3c3bdf30
NC
867mmo_write_chunk (abfd, loc, len)
868 bfd *abfd;
3f9c735e 869 const bfd_byte *loc;
3c3bdf30
NC
870 unsigned int len;
871{
b34976b6 872 bfd_boolean retval = TRUE;
dfa36a69
HPN
873
874 /* Fill up a tetra from bytes remaining from a previous chunk. */
875 if (abfd->tdata.mmo_data->byte_no != 0)
876 {
877 while (abfd->tdata.mmo_data->byte_no < 4 && len != 0)
878 {
879 abfd->tdata.mmo_data->buf[abfd->tdata.mmo_data->byte_no++] = *loc++;
880 len--;
881 }
882
883 if (abfd->tdata.mmo_data->byte_no == 4)
884 {
885 mmo_write_tetra (abfd,
886 bfd_get_32 (abfd, abfd->tdata.mmo_data->buf));
887 abfd->tdata.mmo_data->byte_no = 0;
888 }
889 }
3c3bdf30
NC
890
891 while (len >= 4)
892 {
893 if (loc[0] == LOP)
894 mmo_write_tetra_raw (abfd, LOP_QUOTE_NEXT);
895
82e51918
AM
896 retval = (retval
897 && ! abfd->tdata.mmo_data->have_error
898 && 4 == bfd_bwrite ((PTR) loc, 4, abfd));
3c3bdf30
NC
899
900 loc += 4;
901 len -= 4;
902 }
903
904 if (len)
905 {
dfa36a69
HPN
906 memcpy (abfd->tdata.mmo_data->buf, loc, len);
907 abfd->tdata.mmo_data->byte_no = len;
3c3bdf30
NC
908 }
909
82e51918 910 if (! retval)
b34976b6 911 abfd->tdata.mmo_data->have_error = TRUE;
3c3bdf30
NC
912 return retval;
913}
914
dfa36a69
HPN
915/* Flush remaining bytes, from a previous mmo_write_chunk, zero-padded to
916 4 bytes. */
917
b34976b6 918static INLINE bfd_boolean
dfa36a69
HPN
919mmo_flush_chunk (abfd)
920 bfd *abfd;
921{
922 if (abfd->tdata.mmo_data->byte_no != 0)
923 {
924 memset (abfd->tdata.mmo_data->buf + abfd->tdata.mmo_data->byte_no,
925 0, 4 - abfd->tdata.mmo_data->byte_no);
926 mmo_write_tetra (abfd,
927 bfd_get_32 (abfd, abfd->tdata.mmo_data->buf));
928 abfd->tdata.mmo_data->byte_no = 0;
929 }
930
82e51918 931 return ! abfd->tdata.mmo_data->have_error;
dfa36a69
HPN
932}
933
3c3bdf30
NC
934/* Same, but from a list. */
935
b34976b6 936static INLINE bfd_boolean
3c3bdf30
NC
937mmo_write_chunk_list (abfd, datap)
938 bfd *abfd;
939 mmo_data_list_type *datap;
940{
941 for (; datap != NULL; datap = datap->next)
942 if (! mmo_write_chunk (abfd, datap->data, datap->size))
b34976b6 943 return FALSE;
3c3bdf30 944
dfa36a69 945 return mmo_flush_chunk (abfd);
3c3bdf30
NC
946}
947
dfa36a69
HPN
948/* Write a lop_loc and some contents. A caller needs to call
949 mmo_flush_chunk after calling this function. The location is only
950 output if different than *LAST_VMAP, which is updated after this call. */
3c3bdf30 951
b34976b6 952static bfd_boolean
dfa36a69 953mmo_write_loc_chunk (abfd, vma, loc, len, last_vmap)
3c3bdf30
NC
954 bfd *abfd;
955 bfd_vma vma;
3f9c735e 956 const bfd_byte *loc;
3c3bdf30 957 unsigned int len;
dfa36a69 958 bfd_vma *last_vmap;
3c3bdf30 959{
3c3bdf30
NC
960 /* Find an initial and trailing section of zero tetras; we don't need to
961 write out zeros. FIXME: When we do this, we should emit section size
dfa36a69 962 and address specifiers, else objcopy can't always perform an identity
8d28f606
HPN
963 translation. Only do this if we *don't* have left-over data from a
964 previous write or the vma of this chunk is *not* the next address,
965 because then data isn't tetrabyte-aligned and we're concatenating to
966 that left-over data. */
967
968 if (abfd->tdata.mmo_data->byte_no == 0 || vma != *last_vmap)
3c3bdf30 969 {
8d28f606
HPN
970 while (len >= 4 && bfd_get_32 (abfd, loc) == 0)
971 {
972 vma += 4;
973 len -= 4;
974 loc += 4;
975 }
3c3bdf30 976
8d28f606
HPN
977 while (len >= 4 && bfd_get_32 (abfd, loc + len - 4) == 0)
978 len -= 4;
979 }
3c3bdf30 980
dfa36a69
HPN
981 /* Only write out the location if it's different than the one the caller
982 (supposedly) previously handled, accounting for omitted leading zeros. */
983 if (vma != *last_vmap)
984 {
985 /* We might be in the middle of a sequence. */
986 mmo_flush_chunk (abfd);
987
988 /* We always write the location as 64 bits; no use saving bytes
989 here. */
990 mmo_write_tetra_raw (abfd, (LOP << 24) | (LOP_LOC << 16) | 2);
991 mmo_write_octa_raw (abfd, vma);
992 }
993
994 /* Update to reflect end of this chunk, with trailing zeros omitted. */
995 *last_vmap = vma + len;
996
82e51918
AM
997 return (! abfd->tdata.mmo_data->have_error
998 && mmo_write_chunk (abfd, loc, len));
3c3bdf30
NC
999}
1000
1001/* Same, but from a list. */
1002
b34976b6 1003static INLINE bfd_boolean
3c3bdf30
NC
1004mmo_write_loc_chunk_list (abfd, datap)
1005 bfd *abfd;
1006 mmo_data_list_type *datap;
1007{
dfa36a69
HPN
1008 /* Get an address different than the address of the first chunk. */
1009 bfd_vma last_vma = datap ? datap->where - 1 : 0;
1010
3c3bdf30 1011 for (; datap != NULL; datap = datap->next)
dfa36a69
HPN
1012 if (! mmo_write_loc_chunk (abfd, datap->where, datap->data, datap->size,
1013 &last_vma))
b34976b6 1014 return FALSE;
3c3bdf30 1015
dfa36a69 1016 return mmo_flush_chunk (abfd);
3c3bdf30
NC
1017}
1018
1019/* Make a .MMIX.spec_data.N section. */
1020
1021static asection *
1022mmo_get_generic_spec_data_section (abfd, spec_data_number)
1023 bfd *abfd;
1024 int spec_data_number;
1025{
1026 asection *sec;
1027 char secname[sizeof (MMIX_OTHER_SPEC_SECTION_PREFIX) + 20]
1028 = MMIX_OTHER_SPEC_SECTION_PREFIX;
1029
1030 sprintf (secname + strlen (MMIX_OTHER_SPEC_SECTION_PREFIX),
1031 "%d", spec_data_number);
1032
1033 sec = mmo_make_section (abfd, secname);
1034
1035 return sec;
1036}
1037
1038/* Make a special section for SPEC_DATA_NUMBER. If it is the one we use
1039 ourselves, parse some of its data to get at the section name. */
1040
1041static asection *
1042mmo_get_spec_section (abfd, spec_data_number)
1043 bfd *abfd;
1044 int spec_data_number;
1045{
1046 bfd_byte *secname;
1047 asection *sec;
1048 bfd_byte buf[4];
1049 unsigned int secname_length;
1050 unsigned int i;
1051 bfd_vma section_length;
1052 bfd_vma section_vma;
1053 mmo_data_list_type *loc;
1054 flagword flags;
1055 long orig_pos;
1056
1057 /* If this isn't the "special" special data, then make a placeholder
1058 section. */
1059 if (spec_data_number != SPEC_DATA_SECTION)
1060 return mmo_get_generic_spec_data_section (abfd, spec_data_number);
1061
1062 /* Seek back to this position if there was a format error. */
1063 orig_pos = bfd_tell (abfd);
1064
1065 /* Read the length (in 32-bit words). */
1066 if (bfd_bread (buf, 4, abfd) != 4)
1067 goto format_error;
1068
1069 if (buf[0] == LOP)
1070 {
1071 if (buf[1] != LOP_QUOTE)
1072 goto format_error;
1073
1074 if (bfd_bread (buf, 4, abfd) != 4)
1075 goto format_error;
1076 }
1077
1078 /* We don't care to keep the name length accurate. It's
1079 zero-terminated. */
1080 secname_length = bfd_get_32 (abfd, buf) * 4;
1081
1082 /* Check section name length for sanity. */
1083 if (secname_length > MAX_SECTION_NAME_SIZE)
1084 goto format_error;
1085
1086 /* This should be free'd regardless if a section is created. */
1087 secname = bfd_malloc (secname_length + 1);
1088 secname[secname_length] = 0;
1089
1090 for (i = 0; i < secname_length / 4; i++)
1091 {
1092 if (bfd_bread (secname + i * 4, 4, abfd) != 4)
1093 goto format_error_free;
1094
1095 if (secname[i * 4] == LOP)
1096 {
1097 /* A bit of overkill, but we handle char 0x98 in a section name,
1098 and recognize misparsing. */
1099 if (secname[i * 4 + 1] != LOP_QUOTE
1100 || bfd_bread (secname + i * 4, 4, abfd) != 4)
1101 /* Whoops. We thought this was a name, and now we found a
1102 non-lop_quote lopcode before we parsed the whole length of
1103 the name. Signal end-of-file in the same manner. */
1104 goto format_error_free;
1105 }
1106 }
1107
1108 /* Get the section flags. */
1109 if (bfd_bread (buf, 4, abfd) != 4
1110 || (buf[0] == LOP
1111 && (buf[1] != LOP_QUOTE || bfd_bread (buf, 4, abfd) != 4)))
1112 goto format_error_free;
1113
1114 flags = bfd_get_32 (abfd, buf);
1115
1116 /* Get the section length. */
1117 if (bfd_bread (buf, 4, abfd) != 4
1118 || (buf[0] == LOP
1119 && (buf[1] != LOP_QUOTE || bfd_bread (buf, 4, abfd) != 4)))
1120 goto format_error_free;
1121
1122 section_length = (bfd_vma) bfd_get_32 (abfd, buf) << 32;
1123
1124 /* That's the first, high-part. Now get the low part. */
1125
1126 if (bfd_bread (buf, 4, abfd) != 4
1127 || (buf[0] == LOP
1128 && (buf[1] != LOP_QUOTE || bfd_bread (buf, 4, abfd) != 4)))
1129 goto format_error_free;
1130
1131 section_length |= (bfd_vma) bfd_get_32 (abfd, buf);
1132
1133 /* Check the section length for sanity. */
1134 if (section_length > MAX_ARTIFICIAL_SECTION_SIZE)
1135 goto format_error_free;
1136
1137 /* Get the section VMA. */
1138 if (bfd_bread (buf, 4, abfd) != 4
1139 || (buf[0] == LOP
1140 && (buf[1] != LOP_QUOTE || bfd_bread (buf, 4, abfd) != 4)))
1141 goto format_error_free;
1142
1143 section_vma = (bfd_vma) bfd_get_32 (abfd, buf) << 32;
1144
1145 /* That's the first, high-part. Now get the low part. */
1146 if (bfd_bread (buf, 4, abfd) != 4
1147 || (buf[0] == LOP
1148 && (buf[1] != LOP_QUOTE || bfd_bread (buf, 4, abfd) != 4)))
1149 goto format_error_free;
1150
1151 section_vma |= (bfd_vma) bfd_get_32 (abfd, buf);
1152
1153 sec = mmo_make_section (abfd, secname);
1154 free (secname);
1155 if (sec == NULL)
1156 goto format_error;
1157
1158 /* We allocate a buffer here for the advertised size, with head room for
1159 tetrabyte alignment. */
1160 loc = bfd_zmalloc (section_length + 3
1161 + sizeof (struct mmo_data_list_struct));
1162 if (loc == NULL)
1163 goto format_error;
1164
1165 /* Use a TETRA-rounded size for the allocated buffer; we set the
1166 "visible" section size below. */
1167 loc->size = (section_length + 3) & ~3;
1168
1169 /* Add in the section flags we found to those bfd entered during this
1170 process and set the contents. */
1171 if (! bfd_set_section_flags (abfd, sec,
1172 bfd_sec_flags_from_mmo_flags (flags)
1173 | bfd_get_section_flags (abfd, sec)
1174 | (section_length != 0 ? SEC_HAS_CONTENTS : 0))
eea6121a 1175 || ! bfd_set_section_size (abfd, sec, sec->size + section_length)
3c3bdf30
NC
1176 /* Set VMA only for the first occurrence. */
1177 || (! sec->user_set_vma
1178 && ! bfd_set_section_vma (abfd, sec, section_vma)))
1179 {
1180 /* If we get an error for any of the calls above, signal more than
1181 just a format error for the spec section. */
1182 return NULL;
1183 }
1184
1185 loc->next = NULL;
68bfbfcc
AM
1186 if (mmo_section_data (sec)->tail != NULL)
1187 mmo_section_data (sec)->tail->next = loc;
3c3bdf30 1188 else
68bfbfcc
AM
1189 mmo_section_data (sec)->head = loc;
1190 mmo_section_data (sec)->tail = loc;
3c3bdf30
NC
1191 loc->where = section_vma;
1192
1193 return sec;
1194
1195 format_error_free:
1196 free (secname);
1197 format_error:
1198 if (bfd_seek (abfd, orig_pos, SEEK_SET) != 0)
1199 return NULL;
1200
1201 return mmo_get_generic_spec_data_section (abfd, spec_data_number);
1202}
1203
1204/* Read a byte, but read from file in multiples of 32-bit words. */
1205
1206static bfd_byte
1207mmo_get_byte (abfd)
1208 bfd *abfd;
1209{
1210 bfd_byte retval;
1211
1212 if (abfd->tdata.mmo_data->byte_no == 0)
1213 {
82e51918 1214 if (! abfd->tdata.mmo_data->have_error
3c3bdf30
NC
1215 && bfd_bread (abfd->tdata.mmo_data->buf, 4, abfd) != 4)
1216 {
b34976b6 1217 abfd->tdata.mmo_data->have_error = TRUE;
3c3bdf30
NC
1218
1219 /* A value somewhat safe against tripping on some inconsistency
1220 when mopping up after this error. */
1221 return 128;
1222 }
1223 }
1224
1225 retval = abfd->tdata.mmo_data->buf[abfd->tdata.mmo_data->byte_no];
1226 abfd->tdata.mmo_data->byte_no = (abfd->tdata.mmo_data->byte_no + 1) % 4;
1227
1228 return retval;
1229}
1230
1231/* Write a byte, in multiples of 32-bit words. */
1232
1233static void
1234mmo_write_byte (abfd, value)
1235 bfd *abfd;
1236 bfd_byte value;
1237{
1238 abfd->tdata.mmo_data->buf[(abfd->tdata.mmo_data->byte_no++ % 4)] = value;
1239 if ((abfd->tdata.mmo_data->byte_no % 4) == 0)
1240 {
82e51918 1241 if (! abfd->tdata.mmo_data->have_error
3c3bdf30 1242 && bfd_bwrite (abfd->tdata.mmo_data->buf, 4, abfd) != 4)
b34976b6 1243 abfd->tdata.mmo_data->have_error = TRUE;
3c3bdf30
NC
1244 }
1245}
1246
1247/* Create a symbol. */
1248
b34976b6 1249static bfd_boolean
3c3bdf30
NC
1250mmo_create_symbol (abfd, symname, addr, sym_type, serno)
1251 bfd *abfd;
3f9c735e 1252 const char *symname;
3c3bdf30
NC
1253 bfd_vma addr;
1254 enum mmo_sym_type sym_type;
1255 unsigned int serno;
1256{
1257 struct mmo_symbol *n;
1258
1259 n = (struct mmo_symbol *) bfd_alloc (abfd, sizeof (struct mmo_symbol));
1260 if (n == NULL)
b34976b6 1261 return FALSE;
3c3bdf30
NC
1262
1263 n->name = bfd_alloc (abfd, strlen (symname) + 1);
1264 if (n->name == NULL)
b34976b6 1265 return FALSE;
3c3bdf30
NC
1266
1267 strcpy ((PTR) n->name, symname);
1268
1269 n->value = addr;
1270 n->sym_type = sym_type;
1271 n->serno = serno;
1272
1273 if (abfd->tdata.mmo_data->symbols == NULL)
1274 abfd->tdata.mmo_data->symbols = n;
1275 else
1276 abfd->tdata.mmo_data->symtail->next = n;
1277 abfd->tdata.mmo_data->symtail = n;
1278 n->next = NULL;
1279
1280 ++abfd->symcount;
1281
1282 /* Check that :Main equals the last octa of the .MMIX.reg_contents
1283 section, as it's the one place we're sure to pass when reading a mmo
1284 object. For written objects, we do it while setting the symbol
1285 table. */
1286 if (strcmp (symname, MMIX_START_SYMBOL_NAME) == 0
1287 && bfd_get_start_address (abfd) != addr)
1288 {
1289 (*_bfd_error_handler)
1290 (_("%s: invalid mmo file: initialization value for $255 is not `Main'\n"),
1291 bfd_get_filename (abfd));
1292 bfd_set_error (bfd_error_bad_value);
b34976b6 1293 return FALSE;
3c3bdf30
NC
1294 }
1295
b34976b6 1296 return TRUE;
3c3bdf30
NC
1297}
1298
1299/* Read in symbols. */
1300
b34976b6 1301static bfd_boolean
3c3bdf30
NC
1302mmo_get_symbols (abfd)
1303 bfd *abfd;
1304{
1305/*
1306INODE
1307Symbol-table, mmo section mapping, File layout, mmo
1308SUBSECTION
1309 Symbol table format
1310
1311 From mmixal.w (or really, the generated mmixal.tex) in
6eeb40b2 1312 @url{http://www-cs-faculty.stanford.edu/~knuth/programs/mmix.tar.gz}):
3c3bdf30
NC
1313 ``Symbols are stored and retrieved by means of a @samp{ternary
1314 search trie}, following ideas of Bentley and Sedgewick. (See
1315 ACM--SIAM Symp.@: on Discrete Algorithms @samp{8} (1997), 360--369;
1316 R.@:Sedgewick, @samp{Algorithms in C} (Reading, Mass.@:
1317 Addison--Wesley, 1998), @samp{15.4}.) Each trie node stores a
1318 character, and there are branches to subtries for the cases where
1319 a given character is less than, equal to, or greater than the
1320 character in the trie. There also is a pointer to a symbol table
1321 entry if a symbol ends at the current node.''
1322
1323 So it's a tree encoded as a stream of bytes. The stream of bytes
1324 acts on a single virtual global symbol, adding and removing
1325 characters and signalling complete symbol points. Here, we read
1326 the stream and create symbols at the completion points.
1327
1328 First, there's a control byte <<m>>. If any of the listed bits
1329 in <<m>> is nonzero, we execute what stands at the right, in
1330 the listed order:
1331
1332| (MMO3_LEFT)
1333| 0x40 - Traverse left trie.
1334| (Read a new command byte and recurse.)
1335|
1336| (MMO3_SYMBITS)
1337| 0x2f - Read the next byte as a character and store it in the
1338| current character position; increment character position.
1339| Test the bits of <<m>>:
1340|
1341| (MMO3_WCHAR)
1342| 0x80 - The character is 16-bit (so read another byte,
1343| merge into current character.
1344|
1345| (MMO3_TYPEBITS)
1346| 0xf - We have a complete symbol; parse the type, value
1347| and serial number and do what should be done
1348| with a symbol. The type and length information
1349| is in j = (m & 0xf).
1350|
1351| (MMO3_REGQUAL_BITS)
1352| j == 0xf: A register variable. The following
1353| byte tells which register.
1354| j <= 8: An absolute symbol. Read j bytes as the
1355| big-endian number the symbol equals.
1356| A j = 2 with two zero bytes denotes an
1357| unknown symbol.
1358| j > 8: As with j <= 8, but add (0x20 << 56)
1359| to the value in the following j - 8
1360| bytes.
1361|
1362| Then comes the serial number, as a variant of
1363| uleb128, but better named ubeb128:
1364| Read bytes and shift the previous value left 7
1365| (multiply by 128). Add in the new byte, repeat
1366| until a byte has bit 7 set. The serial number
1367| is the computed value minus 128.
1368|
1369| (MMO3_MIDDLE)
1370| 0x20 - Traverse middle trie. (Read a new command byte
1371| and recurse.) Decrement character position.
1372|
1373| (MMO3_RIGHT)
1374| 0x10 - Traverse right trie. (Read a new command byte and
1375| recurse.)
1376
1377 Let's look again at the <<lop_stab>> for the trivial file
1378 (@pxref{File layout}).
1379
1380| 0x980b0000 - lop_stab for ":Main" = 0, serial 1.
1381| 0x203a4040
1382| 0x10404020
1383| 0x4d206120
1384| 0x69016e00
1385| 0x81000000
1386
1387 This forms the trivial trie (note that the path between ``:'' and
1388 ``M'' is redundant):
1389
1390| 203a ":"
1391| 40 /
1392| 40 /
1393| 10 \
1394| 40 /
1395| 40 /
1396| 204d "M"
1397| 2061 "a"
1398| 2069 "i"
1399| 016e "n" is the last character in a full symbol, and
1400| with a value represented in one byte.
1401| 00 The value is 0.
1402| 81 The serial number is 1. */
1403
1404 bfd_byte m = mmo_get_byte (abfd);
1405
1406 /* Check first if we have a bad hair day. */
82e51918 1407 if (abfd->tdata.mmo_data->have_error)
b34976b6 1408 return FALSE;
3c3bdf30
NC
1409
1410 if (m & MMO3_LEFT)
1411 /* Traverse left trie. */
1412 mmo_get_symbols (abfd);
1413
1414 if (m & MMO3_SYMBITS)
1415 {
1416 bfd_byte c = mmo_get_byte (abfd);
1417 bfd_byte j = m & MMO3_TYPEBITS;
1418 bfd_vma addr = 0;
1419 enum mmo_sym_type sym_type;
1420 unsigned int serno = 0;
1421 bfd_byte k;
1422
1423 if (m & MMO3_WCHAR)
1424 {
1425 bfd_byte c2 = mmo_get_byte (abfd);
1426
1427 /* A two-byte character. We can't grok this, but neither can
1428 mmotype, for other cases than the second byte being zero. */
1429
1430 if (c != 0)
1431 {
1432 abfd->tdata.mmo_data->lop_stab_symbol
1433 [abfd->tdata.mmo_data->symbol_position] = 0;
1434
1435 (*_bfd_error_handler)
1436 (_("%s: unsupported wide character sequence\
1437 0x%02X 0x%02X after symbol name starting with `%s'\n"),
1438 bfd_get_filename (abfd), c, c2,
1439 abfd->tdata.mmo_data->lop_stab_symbol);
1440 bfd_set_error (bfd_error_bad_value);
b34976b6
AM
1441 abfd->tdata.mmo_data->have_error = TRUE;
1442 return FALSE;
3c3bdf30
NC
1443 }
1444 else
1445 c = c2;
1446 }
1447
1448 abfd->tdata.mmo_data->lop_stab_symbol[abfd->tdata.mmo_data->symbol_position++] = c;
1449 abfd->tdata.mmo_data->lop_stab_symbol[abfd->tdata.mmo_data->symbol_position] = 0;
1450
1451 if (j & MMO3_REGQUAL_BITS)
1452 {
1453 if (j == MMO3_REGQUAL_BITS)
1454 {
1455 sym_type = mmo_reg_sym;
1456 addr = mmo_get_byte (abfd);
1457 }
1458 else if (j <= 8)
1459 {
1460 unsigned int i;
1461
1462 for (i = 0; i < j; i++)
1463 addr = (addr << 8) + mmo_get_byte (abfd);
1464
1465 if (addr == 0 && j == MMO3_UNDEF)
1466 sym_type = mmo_undef_sym;
1467 else
1468 sym_type = mmo_abs_sym;
1469 }
1470 else
1471 {
1472 unsigned int i;
1473
1474 for (i = MMO3_DATA; i < j; i++)
1475 addr = (addr << 8) + mmo_get_byte (abfd);
1476
1477 addr += (bfd_vma) 0x20 << 56;
1478 sym_type = mmo_data_sym;
1479 }
1480
1481 /* Get the serial number. */
1482 do
1483 {
1484 k = mmo_get_byte (abfd);
1485 serno = (serno << 7) + k;
1486 }
1487 while (k < 128);
1488 serno -= 128;
1489
1490 /* Got it. Now enter it. Skip a leading ":". */
82e51918 1491 if (! abfd->tdata.mmo_data->have_error
3c3bdf30
NC
1492 && ! mmo_create_symbol (abfd,
1493 abfd->tdata.mmo_data->lop_stab_symbol
1494 + 1,
1495 addr, sym_type, serno))
b34976b6 1496 abfd->tdata.mmo_data->have_error = TRUE;
3c3bdf30
NC
1497 }
1498
1499 if (m & MMO3_MIDDLE)
1500 /* Traverse middle trie. */
1501 mmo_get_symbols (abfd);
1502
1503 abfd->tdata.mmo_data->symbol_position--;
1504 }
1505
1506 if (m & MMO3_RIGHT)
1507 /* Traverse right trie. */
1508 mmo_get_symbols (abfd);
1509
82e51918 1510 return ! abfd->tdata.mmo_data->have_error;
3c3bdf30
NC
1511}
1512
1513/* Get the location of memory area [VMA..VMA + SIZE - 1], which we think
1514 is in section SEC. Adjust and reallocate zero-initialized contents.
1515 If there's new contents, allocate to the next multiple of
1516 MMO_SEC_CONTENTS_CHUNK_SIZE. */
1517
1518static INLINE bfd_byte *
1519mmo_get_loc (sec, vma, size)
1520 asection *sec;
1521 bfd_vma vma;
1522 int size;
1523{
1524 bfd_size_type allocated_size;
68bfbfcc 1525 struct mmo_section_data_struct *sdatap = mmo_section_data (sec);
3c3bdf30
NC
1526 struct mmo_data_list_struct *datap = sdatap->head;
1527 struct mmo_data_list_struct *entry;
1528
dfa36a69
HPN
1529 /* First search the list to see if we have the requested chunk in one
1530 piece, or perhaps if we have a suitable chunk with room to fit. */
3c3bdf30
NC
1531 for (; datap != NULL; datap = datap->next)
1532 {
1533 if (datap->where <= vma
1534 && datap->where + datap->size >= vma + size)
1535 return datap->data + vma - datap->where;
1536 else if (datap->where <= vma
1537 && datap->where + datap->allocated_size >= vma + size
1538 /* Only munch on the "allocated size" if it does not
1539 overlap the next chunk. */
1540 && (datap->next == NULL || datap->next->where >= vma + size))
1541 {
1542 /* There was room allocated, but the size wasn't set to include
1543 it. Do that now. */
1544 datap->size += (vma + size) - (datap->where + datap->size);
1545
dfa36a69
HPN
1546 /* Update the section size. This happens only if we update the
1547 32-bit-aligned chunk size. Callers that have
1548 non-32-bit-aligned sections should do all allocation and
1549 size-setting by themselves or at least set the section size
1550 after the last allocating call to this function. */
eea6121a
AM
1551 if (vma + size > sec->vma + sec->size)
1552 sec->size += (vma + size) - (sec->vma + sec->size);
3c3bdf30
NC
1553
1554 return datap->data + vma - datap->where;
1555 }
1556 }
1557
1558 /* Not found; allocate a new block. First check in case we get a
1559 request for a size split up over several blocks; we'll have to return
1560 NULL for those cases, requesting the caller to split up the request.
1561 Requests with an address aligned on MMO_SEC_CONTENTS_CHUNK_SIZE bytes and
1562 for no more than MMO_SEC_CONTENTS_CHUNK_SIZE will always get resolved. */
1563
1564 for (datap = sdatap->head; datap != NULL; datap = datap->next)
1565 if ((datap->where <= vma && datap->where + datap->size > vma)
1566 || (datap->where < vma + size
1567 && datap->where + datap->size >= vma + size))
1568 return NULL;
1569
1570 allocated_size
1571 = (size + MMO_SEC_CONTENTS_CHUNK_SIZE - 1) & ~(MMO_SEC_CONTENTS_CHUNK_SIZE - 1);
1572 entry = (mmo_data_list_type *)
1573 bfd_zalloc (sec->owner, sizeof (mmo_data_list_type) + allocated_size);
1574 if (entry == NULL)
c295a511 1575 return NULL;
3c3bdf30
NC
1576 entry->where = vma;
1577 entry->size = size;
1578 entry->allocated_size = allocated_size;
1579
1580 datap = sdatap->head;
1581
1582 /* Sort the records by address. Optimize for the common case of adding
1583 a record to the end of the list. */
1584 if (sdatap->tail != NULL && entry->where >= sdatap->tail->where)
1585 {
1586 sdatap->tail->next = entry;
1587 entry->next = NULL;
1588 sdatap->tail = entry;
1589 }
1590 else
1591 {
1592 mmo_data_list_type **look;
1593 for (look = &sdatap->head;
1594 *look != NULL && (*look)->where < entry->where;
1595 look = &(*look)->next)
1596 ;
1597 entry->next = *look;
1598 *look = entry;
1599 if (entry->next == NULL)
1600 {
1601 sdatap->tail = entry;
1602
1603 /* We get here for the first time (at other times too) for this
1604 section. Say we have contents. */
1605 if (! bfd_set_section_flags (sec->owner, sec,
1606 bfd_get_section_flags (sec->owner, sec)
1607 | SEC_HAS_CONTENTS))
1608 return NULL;
1609 }
1610 }
1611
dfa36a69
HPN
1612 /* Update the section size. This happens only when we add contents and
1613 re-size as we go. The section size will then be aligned to 32 bits. */
eea6121a
AM
1614 if (vma + size > sec->vma + sec->size)
1615 sec->size += (vma + size) - (sec->vma + sec->size);
3c3bdf30
NC
1616 return entry->data;
1617}
1618
1619/* Set sizes once we've read in all sections. */
1620
1621static void
1622mmo_map_set_sizes (abfd, sec, ignored)
1623 bfd *abfd ATTRIBUTE_UNUSED;
1624 asection *sec;
1625 PTR ignored ATTRIBUTE_UNUSED;
1626{
3c3bdf30
NC
1627 sec->lma = sec->vma;
1628}
1629
1630/* Read the mmo file and turn it into sections. */
1631
b34976b6 1632static bfd_boolean
3c3bdf30
NC
1633mmo_scan (abfd)
1634 bfd *abfd;
1635{
1636 unsigned int i;
1637 unsigned int lineno = 1;
b34976b6 1638 bfd_boolean error = FALSE;
3c3bdf30
NC
1639 bfd_vma vma = 0;
1640 asection *sec = bfd_make_section_old_way (abfd, MMO_TEXT_SECTION_NAME);
1641 asection *non_spec_sec = NULL;
1642 bfd_vma non_spec_vma = 0;
1643 char *current_filename = NULL;
1644 bfd_size_type nbytes_read = 0;
1645 /* Buffer with room to read a 64-bit value. */
1646 bfd_byte buf[8];
1647 long stab_loc = -1;
1648 char *file_names[256];
1649
1650 memset (file_names, 0, sizeof (file_names));
1651
1652 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
1653 goto error_return;
1654
1655 while ((nbytes_read = bfd_bread (buf, 4, abfd)) == 4)
1656 {
1657 if (buf[0] == LOP)
1658 {
1659 unsigned int y = bfd_get_8 (abfd, buf + 2);
1660 unsigned int z = bfd_get_8 (abfd, buf + 3);
1661
1662 /* Change back to the original section for lopcodes other
1663 than LOP_QUOTE that comes after a LOP_SPEC. */
1664 if ((buf[1] != LOP_QUOTE || y != 0 || z != 1)
1665 && non_spec_sec != NULL)
1666 {
1667 sec = non_spec_sec;
1668 vma = non_spec_vma;
1669 non_spec_sec = NULL;
1670 }
1671
1672 switch (buf[1])
1673 {
1674 default:
1675 (*_bfd_error_handler)
1676 (_("%s: invalid mmo file: unsupported lopcode `%d'\n"),
1677 bfd_get_filename (abfd), buf[1]);
1678 bfd_set_error (bfd_error_bad_value);
1679 goto error_return;
1680
1681 case LOP_QUOTE:
1682 /* Quote the next 32-bit word. */
1683 if (y != 0 || z != 1)
1684 {
1685 (*_bfd_error_handler)
1686 (_("%s: invalid mmo file: expected YZ = 1 got YZ = %d for lop_quote\n"),
1687 bfd_get_filename (abfd), y*256+z);
1688 bfd_set_error (bfd_error_bad_value);
1689 goto error_return;
1690 }
1691 if (bfd_bread (buf, 4, abfd) != 4)
1692 goto error_return;
1693
1694 mmo_xore_32 (sec, vma, bfd_get_32 (abfd, buf));
1695 vma += 4;
1696 vma &= ~3;
1697 lineno++;
1698 break;
1699
1700 case LOP_LOC:
1701 /* Set vma (and section). */
1702 vma = (bfd_vma) y << 56;
1703 if (z == 1)
1704 {
1705 /* Get a 32-bit value. */
1706 if (bfd_bread (buf, 4, abfd) != 4)
1707 goto error_return;
1708
1709 vma += bfd_get_32 (abfd, buf);
1710 }
1711 else if (z == 2)
1712 {
1713 /* Get a 64-bit value. */
1714 if (bfd_bread (buf, 8, abfd) != 8)
1715 goto error_return;
1716
1717 vma += bfd_get_64 (abfd, buf);
1718 }
1719 else
1720 {
1721 (*_bfd_error_handler)
1722 (_("%s: invalid mmo file: expected z = 1 or z = 2, got z = %d for lop_loc\n"),
1723 bfd_get_filename (abfd), z);
1724 bfd_set_error (bfd_error_bad_value);
1725 goto error_return;
1726 }
1727
1728 sec = mmo_decide_section (abfd, vma);
1729 if (sec == NULL)
1730 goto error_return;
1731 break;
1732
1733 case LOP_SKIP:
1734 /* Move forward within the same section. */
1735 vma += y * 256 + z;
1736
1737 sec = mmo_decide_section (abfd, vma);
1738 if (sec == NULL)
1739 goto error_return;
1740 break;
1741
1742 case LOP_FIXO:
1743 /* A fixup: Store the current vma somewhere. Position using
1744 same format as LOP_LOC. */
1745 {
1746 bfd_vma p = (bfd_vma) y << 56;
1747 asection *fixosec;
1748
1749 if (z == 1)
1750 {
1751 /* Get a 32-bit value. */
1752 if (bfd_bread (buf, 4, abfd) != 4)
1753 goto error_return;
1754
1755 p += bfd_get_32 (abfd, buf);
1756 }
1757 else if (z == 2)
1758 {
1759 /* Get a 64-bit value. */
1760 if (bfd_bread (buf, 8, abfd) != 8)
1761 goto error_return;
1762
1763 p += bfd_get_64 (abfd, buf);
1764 }
1765 else
1766 {
1767 (*_bfd_error_handler)
1768 (_("%s: invalid mmo file: expected z = 1 or z = 2, got z = %d for lop_fixo\n"),
1769 bfd_get_filename (abfd), z);
1770 bfd_set_error (bfd_error_bad_value);
1771 goto error_return;
1772 }
1773
1774 /* The section where we store this address might be a
1775 different one than the current section. */
1776 fixosec = mmo_decide_section (abfd, p);
1777 if (fixosec == NULL)
1778 goto error_return;
1779 mmo_xore_64 (fixosec, p, vma);
1780 }
1781 break;
1782
1783 case LOP_FIXR:
1784 /* A fixup: Store YZ of this lopcode into YZ at vma - 4 * yz. */
1785 {
1786 unsigned int yz = (y * 256 + z);
1787 bfd_vma p = vma + 2 - 4 * yz;
1788 asection *fixrsec = mmo_decide_section (abfd, p);
1789 if (fixrsec == NULL)
1790 goto error_return;
1791 mmo_xore_16 (fixrsec, p, yz);
1792 }
1793 break;
1794
1795 case LOP_FIXRX:
1796 /* A fixup, similar to lop_fixr, but taking larger numbers
1797 and can change branches into the opposite direction
1798 (gasp!). */
1799 {
1800 bfd_vma delta;
1801 bfd_vma p;
1802 asection *fixrsec;
1803
1804 if (y != 0)
1805 {
1806 (*_bfd_error_handler)
1807 (_("%s: invalid mmo file: expected y = 0, got y = %d for lop_fixrx\n"),
1808 bfd_get_filename (abfd), y);
1809 bfd_set_error (bfd_error_bad_value);
1810 goto error_return;
1811 }
1812
1813 if (z != 16 && z != 24)
1814 {
1815 (*_bfd_error_handler)
1816 (_("%s: invalid mmo file: expected z = 16 or z = 24, got z = %d for lop_fixrx\n"),
1817 bfd_get_filename (abfd), z);
1818 bfd_set_error (bfd_error_bad_value);
1819 goto error_return;
1820 }
1821
1822 /* Get the next 32-bit value. */
1823 if (bfd_bread (buf, 4, abfd) != 4)
1824 goto error_return;
1825
1826 delta = bfd_get_32 (abfd, buf);
1827
1828 /* Do an, ehm, involved calculation for the location of
1829 the fixup. See mmixal documentation for a verbose
1830 explanation. We follow it verbosely here for the
1831 readers delight. */
1832 if (buf[0] == 0)
1833 p = vma - 4 * delta;
1834 else if (buf[0] == 1)
1835 p = vma - 4 * ((delta & 0xffffff) - (1 << z));
1836 else
1837 {
1838 (*_bfd_error_handler)
1839 (_("%s: invalid mmo file: leading byte of operand word must be 0 or 1, got %d for lop_fixrx\n"),
1840 bfd_get_filename (abfd), buf[0]);
1841 bfd_set_error (bfd_error_bad_value);
1842 goto error_return;
1843 }
1844
1845 fixrsec = mmo_decide_section (abfd, vma);
1846 if (fixrsec == NULL)
1847 goto error_return;
1848 mmo_xore_32 (fixrsec, p, delta);
1849 }
1850 break;
1851
1852 case LOP_FILE:
1853 /* Set current file and perhaps the file name. Reset line
1854 number. */
1855 if (z != 0)
1856 {
1857 char *fname = bfd_malloc (z * 4 + 1);
1858
1859 if (fname == NULL)
1860 {
1861 (*_bfd_error_handler)
1862 (_("%s: cannot allocate file name for file number %d, %d bytes\n"),
1863 bfd_get_filename (abfd), y, z * 4 + 1);
1864 bfd_set_error (bfd_error_system_call);
1865 goto error_return;
1866 }
1867
1868 fname[z * 4] = 0;
1869
1870 for (i = 0; i < z; i++)
1871 {
1872 if (bfd_bread (fname + i * 4, 4, abfd) != 4)
1873 {
1874 free (fname);
1875 goto error_return;
1876 }
1877 }
1878
1879 if (file_names[y] != NULL)
1880 {
1881 (*_bfd_error_handler)
1882 (_("%s: invalid mmo file: file number %d `%s',\
1883 was already entered as `%s'\n"),
1884 bfd_get_filename (abfd), y, fname, file_names[y]);
1885 bfd_set_error (bfd_error_bad_value);
1886 goto error_return;
1887 }
1888
1889 file_names[y] = fname;
1890 }
1891
1892 if (file_names[y] == NULL)
1893 {
1894 (*_bfd_error_handler)
1895 (_("%s: invalid mmo file: file name for number %d\
1896 was not specified before use\n"),
1897 bfd_get_filename (abfd), y);
1898 bfd_set_error (bfd_error_bad_value);
1899 goto error_return;
1900 }
1901
1902 current_filename = file_names[y];
1903 lineno = 0;
1904 break;
1905
1906 case LOP_LINE:
1907 /* Set line number. */
1908 lineno = y * 256 + z;
1909 /* FIXME: Create a sequence of mmo-specific line number
1910 entries for each section, then translate into canonical
1911 format. */
1912 break;
1913
1914 case LOP_SPEC:
1915 /* Special data follows until the next non-lop_quote
1916 lopcode. */
1917 non_spec_sec = sec;
1918 non_spec_vma = vma;
1919 sec = mmo_get_spec_section (abfd, y * 256 + z);
1920 if (sec == NULL)
1921 goto error_return;
1922
1923 vma = sec->vma;
1924 break;
1925
1926 case LOP_PRE:
1927 {
1928 /* We ignore header information, except we read in the
1929 creation time from the first 32-bit word with the time
1930 in seconds since era. */
1931 if (z >= 1
1932 && bfd_bread (abfd->tdata.mmo_data->created, 4,
1933 abfd) != 4)
1934 goto error_return;
1935
1936 for (i = 1; i < z; i++)
1937 if (bfd_bread (buf, 4, abfd) != 4)
1938 goto error_return;
1939 }
1940 break;
1941
1942 case LOP_POST:
1943 /* This tells of the contents of registers $Z..$255 at
1944 startup. We make a section out of it, with VMA = Z * 8,
1945 but only if Z != 255 or the contents is non-zero. */
1946 {
1947 asection *rsec;
1948 bfd_byte *loc;
1949 bfd_vma first_octa;
1950 bfd_vma startaddr_octa;
1951
1952 /* Read first octaword outside loop to simplify logic when
1953 excluding the Z == 255, octa == 0 case. */
1954 if (bfd_bread (buf, 8, abfd) != 8)
1955 goto error_return;
1956
1957 first_octa = bfd_get_64 (abfd, buf);
1958
1959 /* Don't emit contents for the trivial case which is
1960 always present; $255 pointing to Main. */
1961 if (z != 255)
1962 {
1963 rsec
1964 = bfd_make_section_old_way (abfd,
1965 MMIX_REG_CONTENTS_SECTION_NAME);
1966 rsec->vma = z * 8;
1967 loc = mmo_get_loc (rsec, z * 8, (255 - z) * 8);
1968 bfd_put_64 (abfd, first_octa, loc);
1969
1970 for (i = z + 1; i < 255; i++)
1971 {
1972 if (bfd_bread (loc + (i - z) * 8, 8, abfd) != 8)
1973 goto error_return;
1974 }
1975
1976 /* Read out the last octabyte, and use it to set the
1977 start address. */
1978 if (bfd_bread (buf, 8, abfd) != 8)
1979 goto error_return;
1980
1981 startaddr_octa = bfd_get_64 (abfd, buf);
1982 }
1983 else
1984 startaddr_octa = first_octa;
1985
1986 if (! bfd_set_start_address (abfd, startaddr_octa))
1987 {
1988 /* Currently this can't fail, but this should handle
1989 future failures. */
1990 bfd_set_error (bfd_error_bad_value);
1991 goto error_return;
1992 }
1993 }
1994 break;
1995
1996 case LOP_STAB:
1997 /* We read in the symbols now, not later. */
1998 if (y != 0 || z != 0)
1999 {
2000 (*_bfd_error_handler)
2001 (_("%s: invalid mmo file: fields y and z of lop_stab\
2002 non-zero, y: %d, z: %d\n"),
2003 bfd_get_filename (abfd), y, z);
2004 bfd_set_error (bfd_error_bad_value);
2005 goto error_return;
2006 }
2007
2008 /* Save the location, so we can check that YZ in the LOP_END
2009 is correct. */
2010 stab_loc = bfd_tell (abfd);
2011
2012 /* It's not said that an MMO can be without symbols (though
2013 mmixal will refuse to assemble files without Main), but
2014 it seems it would still be a valid mmo-file, so allow it.
2015 We detect the absence of a symbol area in that the upper
2016 limit is computed (from the lop_end YZ field) as 0.
2017 Don't call mmo_get_symbols; it can only detect the end of
2018 a valid symbol trie, not the absence of one. */
2019 if (abfd->tdata.mmo_data->max_symbol_length != 0
2020 && ! mmo_get_symbols (abfd))
2021 goto error_return;
2022 break;
2023
2024 case LOP_END:
2025 {
2026 /* This must be the last 32-bit word in an mmo file.
2027 Let's find out. */
2028 struct stat statbuf;
2029 long curpos = bfd_tell (abfd);
2030
2031 if (bfd_stat (abfd, &statbuf) < 0)
2032 goto error_return;
2033
2034 if (statbuf.st_size != curpos)
2035 {
2036 (*_bfd_error_handler)
2037 (_("%s: invalid mmo file: lop_end not last item in\
2038 file\n"),
2039 bfd_get_filename (abfd));
2040 bfd_set_error (bfd_error_bad_value);
2041 goto error_return;
2042 }
2043
2044 /* Check that the YZ field is right. Subtract the size of
2045 this LOP_END in the calculation; YZ does not include
2046 it. */
2047 if ((long) (y * 256 + z) * 4 != (curpos - stab_loc) - 4)
2048 {
2049 (*_bfd_error_handler)
2050 (_("%s: invalid mmo file: YZ of lop_end (%ld)\
2051 not equal to the number of tetras to the preceding lop_stab (%ld)\n"),
2052 bfd_get_filename (abfd), (long) (y * 256 + z),
2053 (curpos - stab_loc - 4)/4);
2054 bfd_set_error (bfd_error_bad_value);
2055 goto error_return;
2056 }
2057
2058 bfd_map_over_sections (abfd, mmo_map_set_sizes, NULL);
2059 goto done;
2060 }
2061 }
2062 }
2063 else
2064 {
2065 /* This wasn't a lopcode, so store it in the current section. */
2066 mmo_xore_32 (sec, vma & ~3, bfd_get_32 (abfd, buf));
2067 vma += 4;
2068 vma &= ~3;
2069 lineno++;
2070 }
2071 }
2072
2073 /* We know this file is a multiple of four bytes (checked in
2074 mmo_object_p), so if we got something other than 0, this was a bad
2075 file (although it's more likely we'll get 0 in that case too).
2076 If we got end-of-file, then there was no lop_stab, so the file has
2077 invalid format. */
2078
2079 if (nbytes_read != 0)
2080 bfd_set_error (bfd_error_system_call);
2081 else
2082 bfd_set_error (bfd_error_bad_value);
2083
2084 error_return:
b34976b6 2085 error = TRUE;
3c3bdf30
NC
2086 done:
2087 /* Mark the .text and .data section with their normal attribute if they
2088 contain anything. This is not redundant wrt. mmo_decide_section,
2089 since that code might never execute, and conversely the alloc+code
2090 section flags must be set then. */
2091 sec = bfd_get_section_by_name (abfd, MMO_TEXT_SECTION_NAME);
2092 if (sec != NULL
2093 && (bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS)
2094 && ! bfd_set_section_flags (abfd, sec,
2095 bfd_get_section_flags (abfd, sec)
2096 | SEC_ALLOC | SEC_LOAD | SEC_CODE))
b34976b6 2097 error = TRUE;
3c3bdf30
NC
2098
2099 sec = bfd_get_section_by_name (abfd, MMO_DATA_SECTION_NAME);
2100 if (sec != NULL
2101 && (bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS)
2102 && ! bfd_set_section_flags (abfd, sec,
2103 bfd_get_section_flags (abfd, sec)
2104 | SEC_ALLOC | SEC_LOAD))
b34976b6 2105 error = TRUE;
3c3bdf30
NC
2106
2107 /* Free whatever resources we took. */
2108 for (i = 0; i < sizeof (file_names) / sizeof (file_names[0]); i++)
2109 if (file_names[i])
2110 free (file_names[i]);
82e51918 2111 return ! error;
3c3bdf30
NC
2112}
2113
2114/* A hook to set up object file dependent section information. For mmo,
2115 we point out the shape of allocated section contents. */
2116
b34976b6 2117static bfd_boolean
3c3bdf30
NC
2118mmo_new_section_hook (abfd, newsect)
2119 bfd *abfd ATTRIBUTE_UNUSED;
2120 asection *newsect;
2121{
2122 /* We zero-fill all fields and assume NULL is represented by an all
2123 zero-bit pattern. */
2124 newsect->used_by_bfd =
2125 (PTR) bfd_zalloc (abfd, sizeof (struct mmo_section_data_struct));
2126
2127 if (!newsect->used_by_bfd)
b34976b6 2128 return FALSE;
3c3bdf30
NC
2129
2130 /* Always align to at least 32-bit words. */
2131 newsect->alignment_power = 2;
b34976b6 2132 return TRUE;
3c3bdf30
NC
2133}
2134
2135/* We already have section contents loaded for sections that have
2136 contents. */
2137
b34976b6 2138static bfd_boolean
3c3bdf30
NC
2139mmo_get_section_contents (abfd, sec, location, offset, bytes_to_do)
2140 bfd *abfd ATTRIBUTE_UNUSED;
2141 asection *sec ATTRIBUTE_UNUSED;
2142 PTR location ATTRIBUTE_UNUSED;
2143 file_ptr offset ATTRIBUTE_UNUSED;
2144 bfd_size_type bytes_to_do ATTRIBUTE_UNUSED;
2145{
2146 /* Iterate over diminishing chunk sizes, copying contents, like
2147 mmo_set_section_contents. */
2148 while (bytes_to_do)
2149 {
2150 /* A minor song-and-dance to make sure we're not bitten by the
2151 distant possibility of the cast from bfd_vma to int making the
2152 chunk zero-sized. */
2153 int chunk_size
2154 = (int) bytes_to_do != 0 ? bytes_to_do : MMO_SEC_CONTENTS_CHUNK_SIZE;
2155 bfd_byte *loc;
2156
2157 do
2158 loc = mmo_get_loc (sec, sec->vma + offset, chunk_size);
2159 while (loc == NULL && (chunk_size /= 2) != 0);
2160
2161 if (chunk_size == 0)
b34976b6 2162 return FALSE;
3c3bdf30
NC
2163
2164 memcpy (location, loc, chunk_size);
2165
2166 location += chunk_size;
2167 bytes_to_do -= chunk_size;
2168 offset += chunk_size;
2169 }
b34976b6 2170 return TRUE;
3c3bdf30
NC
2171}
2172
2173/* Return the amount of memory needed to read the symbol table. */
2174
2175static long
2176mmo_get_symtab_upper_bound (abfd)
2177 bfd *abfd ATTRIBUTE_UNUSED;
2178{
2179 return (abfd->symcount + 1) * sizeof (asymbol *);
2180}
2181
2182/* Sort mmo symbols by serial number. */
2183
2184static int
2185mmo_sort_mmo_symbols (arg1, arg2)
3f9c735e
AM
2186 const PTR arg1;
2187 const PTR arg2;
3c3bdf30 2188{
3f9c735e
AM
2189 const struct mmo_symbol *sym1 = *(const struct mmo_symbol **) arg1;
2190 const struct mmo_symbol *sym2 = *(const struct mmo_symbol **) arg2;
3c3bdf30
NC
2191
2192 /* Sort by serial number first. */
2193 if (sym1->serno < sym2->serno)
2194 return -1;
2195 else if (sym1->serno > sym2->serno)
2196 return 1;
2197
2198 /* Then sort by address of the table entries. */
3f9c735e 2199 return ((const char *) arg1 - (const char *) arg2);
3c3bdf30
NC
2200}
2201
2202/* Translate the symbol table. */
2203
2204static long
6cee3f79 2205mmo_canonicalize_symtab (abfd, alocation)
3c3bdf30
NC
2206 bfd *abfd;
2207 asymbol **alocation;
2208{
2209 unsigned int symcount = bfd_get_symcount (abfd);
2210 asymbol *csymbols;
2211 unsigned int i;
2212
2213 csymbols = abfd->tdata.mmo_data->csymbols;
2214 if (csymbols == NULL)
2215 {
2216 asymbol *c;
2217 struct mmo_symbol *s;
2218 struct mmo_symbol **msp;
2219
2220 /* First we store the symbols into the table we'll return, then we
2221 qsort it on the serial number, with secondary on the address of
2222 the symbol, to preserve order if there would be non-unique serial
2223 numbers. */
2224 for (s = abfd->tdata.mmo_data->symbols,
2225 msp = (struct mmo_symbol **) alocation;
2226 s != NULL;
2227 s = s->next, ++msp)
2228 *msp = s;
2229
2230 *msp = NULL;
2231
2232 qsort (alocation, symcount, sizeof (struct mmo_symbol *),
2233 mmo_sort_mmo_symbols);
2234
2235 csymbols = (asymbol *) bfd_alloc (abfd, symcount * sizeof (asymbol));
2236 if (csymbols == NULL && symcount != 0)
b34976b6 2237 return FALSE;
3c3bdf30
NC
2238 abfd->tdata.mmo_data->csymbols = csymbols;
2239
2240 for (msp = (struct mmo_symbol **) alocation, c = csymbols;
2241 *msp != NULL;
2242 msp++, ++c)
2243 {
2244 s = *msp;
2245 c->the_bfd = abfd;
2246 c->name = s->name;
2247 c->value = s->value;
2248 c->flags = BSF_GLOBAL;
2249
2250 if (s->sym_type == mmo_data_sym)
2251 {
2252 c->section
2253 = bfd_get_section_by_name (abfd, MMO_DATA_SECTION_NAME);
2254
2255 if (c->section == NULL)
2256 c->section = bfd_abs_section_ptr;
2257 else
2258 c->value -= c->section->vma;
2259 }
2260 else if (s->sym_type == mmo_undef_sym)
2261 c->section = bfd_und_section_ptr;
2262 else if (s->sym_type == mmo_reg_sym)
2263 {
2264 c->section
2265 = bfd_make_section_old_way (abfd, MMIX_REG_SECTION_NAME);
2266 }
2267 else
2268 {
2269 asection *textsec
2270 = bfd_get_section_by_name (abfd, MMO_TEXT_SECTION_NAME);
aa69fe43 2271 asection *datasec;
3c3bdf30
NC
2272
2273 if (textsec != NULL
2274 && c->value >= textsec->vma
eea6121a 2275 && c->value <= textsec->vma + textsec->size)
3c3bdf30
NC
2276 {
2277 c->section = textsec;
2278 c->value -= c->section->vma;
2279 }
aa69fe43
HPN
2280 /* In mmo, symbol types depend on the VMA. Therefore, if
2281 the data section isn't within the usual bounds, its
2282 symbols are marked as absolute. Correct that. This
2283 means we can't have absolute symbols with values matching
2284 data section addresses, but we also can't have with
2285 absolute symbols with values matching text section
2286 addresses. For such needs, use the ELF format. */
2287 else if ((datasec
2288 = bfd_get_section_by_name (abfd,
2289 MMO_DATA_SECTION_NAME))
2290 != NULL
2291 && c->value >= datasec->vma
2292 && c->value <= datasec->vma + datasec->size)
2293 {
2294 c->section = datasec;
2295 c->value -= c->section->vma;
2296 }
3c3bdf30
NC
2297 else
2298 c->section = bfd_abs_section_ptr;
2299 }
2300
2301 c->udata.p = NULL;
2302 }
2303 }
2304
2305 /* Last, overwrite the incoming table with the right-type entries. */
2306 for (i = 0; i < symcount; i++)
2307 *alocation++ = csymbols++;
2308 *alocation = NULL;
2309
2310 return symcount;
2311}
2312
3c3bdf30
NC
2313/* Get information about a symbol. */
2314
2315static void
2316mmo_get_symbol_info (ignore_abfd, symbol, ret)
2317 bfd *ignore_abfd ATTRIBUTE_UNUSED;
2318 asymbol *symbol;
2319 symbol_info *ret;
2320{
2321 bfd_symbol_info (symbol, ret);
2322}
2323
2324static void
2325mmo_print_symbol (abfd, afile, symbol, how)
2326 bfd *abfd;
2327 PTR afile;
2328 asymbol *symbol;
2329 bfd_print_symbol_type how;
2330{
2331 FILE *file = (FILE *) afile;
2332
2333 switch (how)
2334 {
2335 case bfd_print_symbol_name:
2336 fprintf (file, "%s", symbol->name);
2337 break;
2338 default:
2339 bfd_print_symbol_vandf (abfd, (PTR) file, symbol);
2340
2341 fprintf (file, " %-5s %s",
2342 symbol->section->name,
2343 symbol->name);
2344 }
2345}
2346
2347/* We can't map a file directly into executable code, so the
2348 size of header information is irrelevant. */
2349
2350static int
2351mmo_sizeof_headers (abfd, exec)
2352 bfd *abfd ATTRIBUTE_UNUSED;
b34976b6 2353 bfd_boolean exec ATTRIBUTE_UNUSED;
3c3bdf30
NC
2354{
2355 return 0;
2356}
2357
2358/* Write the (section-neutral) file preamble. */
2359
b34976b6 2360static bfd_boolean
3c3bdf30
NC
2361mmo_internal_write_header (abfd)
2362 bfd *abfd;
2363{
3f9c735e 2364 const char lop_pre_bfd[] = { LOP, LOP_PRE, 1, 1};
3c3bdf30
NC
2365
2366 if (bfd_bwrite (lop_pre_bfd, 4, abfd) != 4)
b34976b6 2367 return FALSE;
3c3bdf30
NC
2368
2369 /* Copy creation time of original file. */
2370 if (bfd_bwrite (abfd->tdata.mmo_data->created, 4, abfd) != 4)
b34976b6 2371 return FALSE;
3c3bdf30 2372
b34976b6 2373 return TRUE;
3c3bdf30
NC
2374}
2375
2376/* Write the LOP_POST record, with global register initializations.
2377 Z is the Z field of the LOP_POST, corresponding to 255 - number of
2378 registers at DATA. The Z = 255 field is filled in with the
2379 start-address. */
2380
b34976b6 2381static bfd_boolean
3c3bdf30
NC
2382mmo_internal_write_post (abfd, z, sec)
2383 bfd *abfd;
2384 int z;
2385 asection *sec;
2386{
2387 int i;
2388 bfd_byte buf[8];
2389 mmo_write_tetra_raw (abfd, (LOP << 24) | (LOP_POST << 16) | z);
2390
2391 for (i = z; i < 255; i++)
2392 {
2393 bfd_byte *data = mmo_get_loc (sec, i * 8, 8);
2394
2395 if (bfd_bwrite (data, 8, abfd) != 8)
b34976b6 2396 return FALSE;
3c3bdf30
NC
2397 }
2398
2399 /* For Z == $255, we always emit the start location; supposedly Main,
2400 but we have it handy at bfd_get_start_address. If we're called with
2401 Z == 255, don't assume DATA is valid. */
2402 bfd_put_64 (abfd, bfd_get_start_address (abfd), buf);
2403
82e51918 2404 return ! abfd->tdata.mmo_data->have_error && bfd_bwrite (buf, 8, abfd) == 8;
3c3bdf30
NC
2405}
2406
2407/* Translate to and from BFD flags. This is to make sure that we don't
2408 get bitten by BFD flag number changes. */
2409
2410static flagword
2411mmo_sec_flags_from_bfd_flags (flags)
2412 flagword flags;
2413{
2414 flagword oflags = 0;
2415
2416 if (flags & SEC_ALLOC)
2417 oflags |= MMO_SEC_ALLOC;
2418 if (flags & SEC_LOAD)
2419 oflags |= MMO_SEC_LOAD;
2420 if (flags & SEC_RELOC)
2421 oflags |= MMO_SEC_RELOC;
2422 if (flags & SEC_READONLY)
2423 oflags |= MMO_SEC_READONLY;
2424 if (flags & SEC_CODE)
2425 oflags |= MMO_SEC_CODE;
2426 if (flags & SEC_DATA)
2427 oflags |= MMO_SEC_DATA;
2428 if (flags & SEC_NEVER_LOAD)
2429 oflags |= MMO_SEC_NEVER_LOAD;
2430 if (flags & SEC_IS_COMMON)
2431 oflags |= MMO_SEC_IS_COMMON;
2432 if (flags & SEC_DEBUGGING)
2433 oflags |= MMO_SEC_DEBUGGING;
2434
2435 return oflags;
2436}
2437
2438static flagword
2439bfd_sec_flags_from_mmo_flags (flags)
2440 flagword flags;
2441{
2442 flagword oflags = 0;
2443
2444 if (flags & MMO_SEC_ALLOC)
2445 oflags |= SEC_ALLOC;
2446 if (flags & MMO_SEC_LOAD)
2447 oflags |= SEC_LOAD;
2448 if (flags & MMO_SEC_RELOC)
2449 oflags |= SEC_RELOC;
2450 if (flags & MMO_SEC_READONLY)
2451 oflags |= SEC_READONLY;
2452 if (flags & MMO_SEC_CODE)
2453 oflags |= SEC_CODE;
2454 if (flags & MMO_SEC_DATA)
2455 oflags |= SEC_DATA;
2456 if (flags & MMO_SEC_NEVER_LOAD)
2457 oflags |= SEC_NEVER_LOAD;
2458 if (flags & MMO_SEC_IS_COMMON)
2459 oflags |= SEC_IS_COMMON;
2460 if (flags & MMO_SEC_DEBUGGING)
2461 oflags |= SEC_DEBUGGING;
2462
2463 return oflags;
2464}
2465
aa69fe43
HPN
2466/* Return TRUE iff the leading or trailing tetrabyte in SEC is defined and
2467 is 0. */
2468
2469static bfd_boolean
2470mmo_has_leading_or_trailing_zero_tetra_p (abfd, sec)
2471 bfd *abfd;
2472 asection *sec;
2473{
2474 bfd_vma secaddr = bfd_get_section_vma (abfd, sec);
2475
2476 if (sec->size < 4)
2477 return FALSE;
2478
2479 if (bfd_get_32 (abfd, mmo_get_loc (sec, secaddr, 4)) == 0
2480 && bfd_get_32 (abfd,
2481 mmo_get_loc (sec, secaddr + sec->size - 4, 4)) == 0)
2482 return TRUE;
2483
2484 return FALSE;
2485}
2486
3c3bdf30
NC
2487/* Write a section. */
2488
b34976b6 2489static bfd_boolean
3c3bdf30
NC
2490mmo_internal_write_section (abfd, sec)
2491 bfd *abfd;
2492 asection *sec;
2493{
2494 /* We do it differently depending on what section this is:
2495
2496 ".text": Output, prepended by information about the first source file
2497 (not yet implemented.)
2498
2499 ".data": Output.
2500
2501 (".MMIX.reg_contents": Not handled here.)
2502
2503 Anything else: Output inside a lop_spec 80, in the format described
2504 above. */
2505
2506 if (strcmp (sec->name, MMO_TEXT_SECTION_NAME) == 0)
aa69fe43
HPN
2507 {
2508 bfd_vma secaddr = bfd_get_section_vma (abfd, sec);
2509
2510 /* Because leading and trailing zeros are omitted in output, we need to
2511 specify the section boundaries so they're correct when the file
2512 is read in again. That's also the case if this section is
2513 specified as not within its usual boundaries or alignments. */
2514 if (sec->size != 0
2515 && (secaddr + sec->size >= (bfd_vma) 1 << 56
2516 || (secaddr & 3) != 0
2517 || (sec->size & 3) != 0
2518 || mmo_has_leading_or_trailing_zero_tetra_p (abfd, sec)))
2519 {
2520 if (!mmo_write_section_description (abfd, sec))
2521 return FALSE;
2522 }
2523
2524 /* FIXME: Output source file name and line number. */
2525 return mmo_write_loc_chunk_list (abfd, mmo_section_data (sec)->head);
2526 }
3c3bdf30 2527 else if (strcmp (sec->name, MMO_DATA_SECTION_NAME) == 0)
aa69fe43
HPN
2528 {
2529 bfd_vma secaddr = bfd_get_section_vma (abfd, sec);
2530
2531 /* Same goes as for MMO_TEXT_SECTION_NAME above. */
2532 if (sec->size != 0
2533 && (secaddr < (bfd_vma) 0x20 << 56
2534 || secaddr + sec->size >= (bfd_vma) 0x21 << 56
2535 || (secaddr & 3) != 0
2536 || (sec->size & 3) != 0
2537 || mmo_has_leading_or_trailing_zero_tetra_p (abfd, sec)))
2538 {
2539 if (!mmo_write_section_description (abfd, sec))
2540 return FALSE;
2541 }
2542
2543 return mmo_write_loc_chunk_list (abfd, mmo_section_data (sec)->head);
2544 }
3c3bdf30
NC
2545 else if (strcmp (sec->name, MMIX_REG_CONTENTS_SECTION_NAME) == 0)
2546 /* Not handled here. */
2547 {
2548 /* This would normally be an abort call since this can't happen, but
2549 we don't do that. */
2550 bfd_set_error (bfd_error_bad_value);
b34976b6 2551 return FALSE;
3c3bdf30
NC
2552 }
2553 else if (strncmp (sec->name, MMIX_OTHER_SPEC_SECTION_PREFIX,
2554 strlen (MMIX_OTHER_SPEC_SECTION_PREFIX)) == 0)
2555 {
2556 int n = atoi (sec->name + strlen (MMIX_OTHER_SPEC_SECTION_PREFIX));
2557 mmo_write_tetra_raw (abfd, (LOP << 24) | (LOP_SPEC << 16) | n);
82e51918 2558 return (! abfd->tdata.mmo_data->have_error
68bfbfcc 2559 && mmo_write_chunk_list (abfd, mmo_section_data (sec)->head));
3c3bdf30
NC
2560 }
2561 /* Ignore sections that are just allocated or empty; we write out
2562 _contents_ here. */
2563 else if ((bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS) != 0
eea6121a 2564 && sec->size != 0)
3c3bdf30 2565 {
aa69fe43
HPN
2566 if (!mmo_write_section_description (abfd, sec))
2567 return FALSE;
2568
2569 /* Writing a LOP_LOC ends the LOP_SPEC data, and makes data actually
2570 loaded. */
2571 if (bfd_get_section_flags (abfd, sec) & SEC_LOAD)
2572 return (! abfd->tdata.mmo_data->have_error
2573 && mmo_write_loc_chunk_list (abfd,
2574 mmo_section_data (sec)->head));
2575 return (! abfd->tdata.mmo_data->have_error
2576 && mmo_write_chunk_list (abfd, mmo_section_data (sec)->head));
2577 }
2578
2579 /* Some section without contents. */
2580 return TRUE;
2581}
2582
2583/* Write the description of a section, extended-mmo-style. */
2584
2585static bfd_boolean
2586mmo_write_section_description (abfd, sec)
2587 bfd *abfd;
2588 asection *sec;
2589{
2590 /* Keep the following document-comment formatted the way it is. */
3c3bdf30
NC
2591/*
2592INODE
2593mmo section mapping, , Symbol-table, mmo
2594SUBSECTION
2595 mmo section mapping
2596
2597 The implementation in BFD uses special data type 80 (decimal) to
2598 encapsulate and describe named sections, containing e.g.@: debug
2599 information. If needed, any datum in the encapsulation will be
2600 quoted using lop_quote. First comes a 32-bit word holding the
2601 number of 32-bit words containing the zero-terminated zero-padded
2602 segment name. After the name there's a 32-bit word holding flags
2603 describing the section type. Then comes a 64-bit big-endian word
2604 with the section length (in bytes), then another with the section
2605 start address. Depending on the type of section, the contents
2606 might follow, zero-padded to 32-bit boundary. For a loadable
2607 section (such as data or code), the contents might follow at some
2608 later point, not necessarily immediately, as a lop_loc with the
2609 same start address as in the section description, followed by the
2610 contents. This in effect forms a descriptor that must be emitted
2611 before the actual contents. Sections described this way must not
2612 overlap.
2613
2614 For areas that don't have such descriptors, synthetic sections are
2615 formed by BFD. Consecutive contents in the two memory areas
2616 @samp{0x0000@dots{}00} to @samp{0x01ff@dots{}ff} and
2617 @samp{0x2000@dots{}00} to @samp{0x20ff@dots{}ff} are entered in
2618 sections named <<.text>> and <<.data>> respectively. If an area
2619 is not otherwise described, but would together with a neighboring
2620 lower area be less than @samp{0x40000000} bytes long, it is joined
2621 with the lower area and the gap is zero-filled. For other cases,
2622 a new section is formed, named <<.MMIX.sec.@var{n}>>. Here,
2623 @var{n} is a number, a running count through the mmo file,
2624 starting at 0.
2625
2626EXAMPLE
2627 A loadable section specified as:
2628
2629| .section secname,"ax"
2630| TETRA 1,2,3,4,-1,-2009
2631| BYTE 80
2632
2633 and linked to address @samp{0x4}, is represented by the sequence:
2634
2635| 0x98080050 - lop_spec 80
2636| 0x00000002 - two 32-bit words for the section name
2637| 0x7365636e - "secn"
2638| 0x616d6500 - "ame\0"
2639| 0x00000033 - flags CODE, READONLY, LOAD, ALLOC
2640| 0x00000000 - high 32 bits of section length
2641| 0x0000001c - section length is 28 bytes; 6 * 4 + 1 + alignment to 32 bits
2642| 0x00000000 - high 32 bits of section address
2643| 0x00000004 - section address is 4
2644| 0x98010002 - 64 bits with address of following data
dfa36a69
HPN
2645| 0x00000000 - high 32 bits of address
2646| 0x00000004 - low 32 bits: data starts at address 4
3c3bdf30
NC
2647| 0x00000001 - 1
2648| 0x00000002 - 2
2649| 0x00000003 - 3
2650| 0x00000004 - 4
2651| 0xffffffff - -1
2652| 0xfffff827 - -2009
2653| 0x50000000 - 80 as a byte, padded with zeros.
2654
2655 Note that the lop_spec wrapping does not include the section
2656 contents. Compare this to a non-loaded section specified as:
2657
2658| .section thirdsec
2659| TETRA 200001,100002
2660| BYTE 38,40
2661
2662 This, when linked to address @samp{0x200000000000001c}, is
2663 represented by:
2664
2665| 0x98080050 - lop_spec 80
2666| 0x00000002 - two 32-bit words for the section name
2667| 0x7365636e - "thir"
2668| 0x616d6500 - "dsec"
2669| 0x00000010 - flag READONLY
2670| 0x00000000 - high 32 bits of section length
2671| 0x0000000c - section length is 12 bytes; 2 * 4 + 2 + alignment to 32 bits
dfa36a69
HPN
2672| 0x20000000 - high 32 bits of address
2673| 0x0000001c - low 32 bits of address 0x200000000000001c
3c3bdf30
NC
2674| 0x00030d41 - 200001
2675| 0x000186a2 - 100002
2676| 0x26280000 - 38, 40 as bytes, padded with zeros
2677
dfa36a69 2678 For the latter example, the section contents must not be
3c3bdf30
NC
2679 loaded in memory, and is therefore specified as part of the
2680 special data. The address is usually unimportant but might
2681 provide information for e.g.@: the DWARF 2 debugging format. */
2682
aa69fe43
HPN
2683 mmo_write_tetra_raw (abfd, LOP_SPEC_SECTION);
2684 mmo_write_tetra (abfd, (strlen (sec->name) + 3) / 4);
2685 mmo_write_chunk (abfd, sec->name, strlen (sec->name));
2686 mmo_flush_chunk (abfd);
2687 /* FIXME: We can get debug sections (.debug_line & Co.) with a section
2688 flag still having SEC_RELOC set. Investigate. This might be true
2689 for all alien sections; perhaps mmo.em should clear that flag. Might
2690 be related to weak references. */
2691 mmo_write_tetra (abfd,
2692 mmo_sec_flags_from_bfd_flags
2693 (bfd_get_section_flags (abfd, sec)));
2694 mmo_write_octa (abfd, sec->size);
2695 mmo_write_octa (abfd, bfd_get_section_vma (abfd, sec));
b34976b6 2696 return TRUE;
3c3bdf30
NC
2697}
2698
2699/* We save up all data before output. */
2700
b34976b6 2701static bfd_boolean
3c3bdf30
NC
2702mmo_set_section_contents (abfd, sec, location, offset, bytes_to_do)
2703 bfd *abfd ATTRIBUTE_UNUSED;
2704 sec_ptr sec;
0f867abe 2705 const PTR location;
3c3bdf30
NC
2706 file_ptr offset;
2707 bfd_size_type bytes_to_do;
2708{
2709 /* Iterate over diminishing chunk sizes, copying contents. */
2710 while (bytes_to_do)
2711 {
2712 /* A minor song-and-dance to make sure we're not bitten by the
2713 distant possibility of the cast from bfd_vma to int making the
2714 chunk zero-sized. */
2715 int chunk_size
2716 = (int) bytes_to_do != 0 ? bytes_to_do : MMO_SEC_CONTENTS_CHUNK_SIZE;
2717 bfd_byte *loc;
2718
2719 do
2720 loc = mmo_get_loc (sec, sec->vma + offset, chunk_size);
2721 while (loc == NULL && (chunk_size /= 2) != 0);
2722
2723 if (chunk_size == 0)
b34976b6 2724 return FALSE;
3c3bdf30
NC
2725
2726 memcpy (loc, location, chunk_size);
2727
2728 location += chunk_size;
2729 bytes_to_do -= chunk_size;
2730 offset += chunk_size;
2731 }
b34976b6 2732 return TRUE;
3c3bdf30
NC
2733}
2734
2735/* Add a symbol to a trie-tree. */
2736
b34976b6 2737static bfd_boolean
3c3bdf30
NC
2738mmo_internal_add_3_sym (abfd, rootp, symp)
2739 bfd *abfd;
2740 struct mmo_symbol_trie *rootp;
3f9c735e 2741 const struct mmo_symbol *symp;
3c3bdf30 2742{
3f9c735e 2743 const char *name = symp->name;
3c3bdf30
NC
2744 struct mmo_symbol_trie *trie = rootp;
2745 struct mmo_symbol_trie **triep = NULL;
2746
2747 while (*name && trie != NULL)
2748 {
2749 if (*name < trie->symchar)
2750 {
2751 triep = &trie->left;
2752 trie = trie->left;
2753 }
2754 else if (*name > trie->symchar)
2755 {
2756 triep = &trie->right;
2757 trie = trie->right;
2758 }
2759 else if (*name == trie->symchar)
2760 {
2761 triep = &trie->middle;
2762 name++;
2763
2764 /* Make sure "trie" points to where we should fill in the
2765 current symbol whenever we've iterated through "name". We
2766 would lose the right position if we encounter "foobar" then
2767 "foo". */
2768 if (*name)
2769 trie = trie->middle;
2770 }
2771 }
2772
2773 while (*name != 0)
2774 {
2775 /* Create middle branches for the rest of the characters. */
2776 trie = bfd_zalloc (abfd, sizeof (struct mmo_symbol_trie));
2777 *triep = trie;
2778 trie->symchar = *name++;
2779 triep = &trie->middle;
2780 }
2781
2782 /* We discover a duplicate symbol rather late in the process, but still;
2783 we discover it and bail out. */
2784 if (trie->sym.name != NULL)
2785 {
2786 (*_bfd_error_handler)
2787 (_("%s: invalid symbol table: duplicate symbol `%s'\n"),
2788 bfd_get_filename (abfd), trie->sym.name);
2789 bfd_set_error (bfd_error_bad_value);
b34976b6 2790 return FALSE;
3c3bdf30
NC
2791 }
2792
2793 memcpy (&trie->sym, symp, sizeof *symp);
b34976b6 2794 return TRUE;
3c3bdf30
NC
2795}
2796
2797/* Find out the length of the serialized version of a trie in bytes. */
2798
2799static unsigned int
2800mmo_internal_3_length (abfd, trie)
2801 bfd *abfd;
2802 struct mmo_symbol_trie *trie;
2803{
2804 /* First, one for the control byte. */
2805 unsigned int length = 1;
2806
2807 if (trie == NULL)
2808 return 0;
2809
2810 /* Add in the recursion to the left. */
2811 length += mmo_internal_3_length (abfd, trie->left);
2812
2813 /* Add in the middle trie and the character. */
2814 length += 1 + mmo_internal_3_length (abfd, trie->middle);
2815
2816 /* Add in the recursion to the right. */
2817 length += mmo_internal_3_length (abfd, trie->right);
2818
2819 /* Add in bytes for the symbol (if this is an endnode). */
2820 if (trie->sym.name != NULL)
2821 {
2822 unsigned int serno = trie->sym.serno;
2823
2824 /* First what it takes to encode the value. */
2825 if (trie->sym.sym_type == mmo_reg_sym)
2826 length++;
2827 else if (trie->sym.sym_type == mmo_undef_sym)
2828 length += 2;
2829 else
2830 {
2831 bfd_vma value = trie->sym.value;
2832
2833 /* Coded in one to eight following bytes. */
2834 if (trie->sym.sym_type == mmo_data_sym)
2835 value -= (bfd_vma) 0x20 << 56;
2836
2837 do
2838 {
2839 value >>= 8;
2840 length++;
2841 }
2842 while (value != 0);
2843 }
2844
2845 /* Find out what it takes to encode the serial number. */
2846 do
2847 {
2848 serno >>= 7;
2849 length++;
2850 }
2851 while (serno != 0);
2852 }
2853
2854 return length;
2855}
2856
2857/* Helper function for outputting the serial number of a symbol, output as
2858 a variant of leb128 (see dwarf2 documentation) which could be called
2859 beb128. Using a helper function and recursion simplifies debugging. */
2860
2861static void
2862mmo_beb128_out (abfd, serno, marker)
2863 bfd *abfd;
2864 int serno;
2865 int marker;
2866{
2867 if (serno & ~0x7f)
2868 mmo_beb128_out (abfd, serno >> 7, 0);
2869 mmo_write_byte (abfd, marker | (serno & 0x7f));
2870}
2871
2872/* Serialize a trie. */
2873
2874static void
2875mmo_internal_3_dump (abfd, trie)
2876 bfd *abfd;
2877 struct mmo_symbol_trie *trie;
2878{
2879 bfd_byte control = 0;
2880
2881 if (trie == NULL)
2882 return;
2883
2884 if (trie->left)
2885 control |= MMO3_LEFT;
2886
2887 if (trie->middle)
2888 control |= MMO3_MIDDLE;
2889
2890 if (trie->right)
2891 control |= MMO3_RIGHT;
2892
2893 if (trie->sym.name != NULL)
2894 {
2895 /* Encode the symbol type and length of value bytes. */
2896 if (trie->sym.sym_type == mmo_reg_sym)
2897 control |= MMO3_REGQUAL_BITS;
2898 else if (trie->sym.sym_type == mmo_undef_sym)
2899 control |= MMO3_UNDEF;
2900 else
2901 {
2902 bfd_vma value = trie->sym.value;
2903
2904 /* Coded in 1..8 following bytes. */
2905 if (trie->sym.sym_type == mmo_data_sym)
2906 {
2907 control |= MMO3_DATA;
2908 value -= (bfd_vma) 0x20 << 56;
2909 }
2910
2911 do
2912 {
2913 value >>= 8;
2914 control++;
2915 }
2916 while (value != 0);
2917 }
2918 }
2919
2920 /* The control byte is output before recursing. */
2921 mmo_write_byte (abfd, control);
2922
2923 mmo_internal_3_dump (abfd, trie->left);
2924
2925 if (control & MMO3_SYMBITS)
2926 {
2927 mmo_write_byte (abfd, trie->symchar);
2928
2929 if (trie->sym.name != NULL)
2930 {
2931 if (trie->sym.sym_type == mmo_reg_sym)
2932 mmo_write_byte (abfd, trie->sym.value);
2933 else if (trie->sym.sym_type == mmo_undef_sym)
2934 {
2935 mmo_write_byte (abfd, 0);
2936 mmo_write_byte (abfd, 0);
2937 }
2938 else
2939 {
2940 bfd_vma value = trie->sym.value;
2941
2942 bfd_byte byte_n = control & 15;
2943
2944 /* Coded in 1..8 following bytes. Note that the value is
2945 shifted out big-endian. */
2946 if (trie->sym.sym_type == mmo_data_sym)
2947 {
2948 value -= (bfd_vma) 0x20 << 56;
2949 byte_n -= 8;
2950 }
2951
2952 do
2953 {
2954 mmo_write_byte (abfd, (value >> ((byte_n - 1) * 8)) & 0xff);
2955 byte_n--;
2956 }
2957 while (byte_n != 0);
2958 }
2959
2960 mmo_beb128_out (abfd, trie->sym.serno, 128);
2961 }
2962 mmo_internal_3_dump (abfd, trie->middle);
2963 }
2964 mmo_internal_3_dump (abfd, trie->right);
2965}
2966
dfa36a69 2967/* Write symbols in mmo format. Also write the lop_end terminator. */
3c3bdf30 2968
b34976b6 2969static bfd_boolean
3c3bdf30
NC
2970mmo_write_symbols_and_terminator (abfd)
2971 bfd *abfd;
2972{
2973 int count = bfd_get_symcount (abfd);
dfa36a69 2974 asymbol *maintable[2];
3c3bdf30 2975 asymbol **table;
dfa36a69
HPN
2976 asymbol **orig_table = bfd_get_outsymbols (abfd);
2977 int serno;
3c3bdf30
NC
2978 struct mmo_symbol_trie root;
2979 int trie_len;
2980 int i;
2981 bfd_byte buf[4];
2982
2983 /* Create a symbol for "Main". */
dfa36a69 2984 asymbol *fakemain = bfd_make_empty_symbol (abfd);
3c3bdf30 2985
dfa36a69
HPN
2986 fakemain->flags = BSF_GLOBAL;
2987 fakemain->value = bfd_get_start_address (abfd);
2988 fakemain->name = MMIX_START_SYMBOL_NAME;
2989 fakemain->section = bfd_abs_section_ptr;
2990 maintable[0] = fakemain;
2991 maintable[1] = NULL;
3c3bdf30
NC
2992
2993 memset (&root, 0, sizeof (root));
2994
2995 /* Make all symbols take a left turn. */
2996 root.symchar = 0xff;
2997
dfa36a69
HPN
2998 /* There must always be a ":Main", so we'll add one if there are no
2999 symbols. Make sure we have room for it. */
3000 table = bfd_alloc (abfd, (count + 1) * sizeof (asymbol *));
3001 if (table == NULL)
b34976b6 3002 return FALSE;
dfa36a69
HPN
3003
3004 memcpy (table, orig_table, count * sizeof (asymbol *));
3005
3006 /* Move :Main (if there is one) to the first position. This is
3007 necessary to get the same layout of the trie-tree when linking as
3008 when objcopying the result as in the objcopy.exp test "simple objcopy
3009 of executable". It also automatically takes care of assigning serial
3010 number 1 to :Main (as is mandatory). */
3011 for (i = 0; i < count; i++)
3012 if (table[i] != NULL
3013 && strcmp (table[i]->name, MMIX_START_SYMBOL_NAME) == 0
3014 && (table[i]->flags & (BSF_DEBUGGING|BSF_GLOBAL)) == BSF_GLOBAL)
3015 {
3016 asymbol *mainsym = table[i];
3017 memcpy (table + 1, orig_table, i * sizeof (asymbol *));
3018 table[0] = mainsym;
3019
3020 /* Check that the value assigned to :Main is the same as the entry
3021 address. The default linker script asserts this. This is as
3022 good a place as any to check this consistency. */
3023 if ((mainsym->value
3024 + mainsym->section->output_section->vma
3025 + mainsym->section->output_offset)
3026 != bfd_get_start_address (abfd))
3027 {
3028 /* Arbitrary buffer to hold the printable representation of a
3029 vma. */
3030 char vmas_main[40];
3031 char vmas_start[40];
3032 bfd_vma vma_start = bfd_get_start_address (abfd);
3033
3034 sprintf_vma (vmas_main, mainsym->value);
3035 sprintf_vma (vmas_start, vma_start);
3036
3037 (*_bfd_error_handler)
3038 (_("%s: Bad symbol definition: `Main' set to %s rather\
3039 than the start address %s\n"),
3040 bfd_get_filename (abfd), vmas_main, vmas_start);
3041 bfd_set_error (bfd_error_bad_value);
b34976b6 3042 return FALSE;
dfa36a69
HPN
3043 }
3044 break;
3045 }
3046 if (i == count && count != 0)
3c3bdf30 3047 {
dfa36a69
HPN
3048 /* When there are symbols, there must be a :Main. There was no
3049 :Main, so we need to add it manually. */
3050 memcpy (table + 1, orig_table, count * sizeof (asymbol *));
3051 table[0] = fakemain;
3052 count++;
3c3bdf30 3053 }
3c3bdf30 3054
dfa36a69 3055 for (i = 0, serno = 1; i < count && table[i] != NULL; i++)
3c3bdf30
NC
3056 {
3057 asymbol *s = table[i];
3058
3059 /* It's not enough to consult bfd_is_local_label, since it does not
3060 mean "local" in the sense of linkable-and-observable-after-link.
3061 Let's just check the BSF_GLOBAL flag.
3062
3063 Also, don't export symbols with characters not in the allowed set. */
3064 if ((s->flags & (BSF_DEBUGGING|BSF_GLOBAL)) == BSF_GLOBAL
3065 && strspn (s->name,
3066 valid_mmo_symbol_character_set) == strlen (s->name))
3067 {
3068 struct mmo_symbol sym;
3069 memset (&sym, 0, sizeof (sym));
3070
3071 sym.name = s->name;
3072 sym.value =
3073 s->value
3074 + s->section->output_section->vma
3075 + s->section->output_offset;
3076
3077 if (bfd_is_und_section (s->section))
3078 sym.sym_type = mmo_undef_sym;
3079 else if (strcmp (s->section->name, MMO_DATA_SECTION_NAME) == 0
3080 /* The encoding of data symbols require that the "rest"
3081 of the value fits in 6 bytes, so the upper two bytes
3082 must be 0x2000. All other symbols get to be the
3083 absolute type. */
3084 && (sym.value >> 48) == 0x2000)
3085 sym.sym_type = mmo_data_sym;
3086 else if (strcmp (s->section->name, MMIX_REG_SECTION_NAME) == 0)
3087 sym.sym_type = mmo_reg_sym;
3088 else if (strcmp (s->section->name,
3089 MMIX_REG_CONTENTS_SECTION_NAME) == 0)
3090 {
3091 sym.sym_type = mmo_reg_sym;
3092 sym.value /= 8;
3093 }
3094 else
3095 sym.sym_type = mmo_abs_sym;
3096
3097 /* FIXME: We assume the order of the received symbols is an
3098 ordered mapping of the serial numbers. This is not
3099 necessarily true if we e.g. objcopy a mmo file to another and
dfa36a69 3100 there are gaps in the numbering. Not sure if this can
3c3bdf30 3101 happen. Not sure what to do. */
dfa36a69 3102 sym.serno = serno++;
3c3bdf30
NC
3103
3104 if (! mmo_internal_add_3_sym (abfd, &root, &sym))
b34976b6 3105 return FALSE;
3c3bdf30
NC
3106 }
3107 }
3108
3109 /* Change the root node to be a ":"-prefix. */
3110 root.symchar = ':';
3111 root.middle = root.left;
3112 root.right = NULL;
3113 root.left = NULL;
3114
3115 /* We have to find out if we can fit the whole symbol table in the mmo
3116 symtab. It would be bad to assume we can always fit it in 262144
3117 bytes. If we can't, just leave the Main symbol. */
3118 trie_len = (mmo_internal_3_length (abfd, &root) + 3)/4;
3119
3120 if (trie_len > 0xffff)
3121 {
3122 /* Test this code by using a lower limit in the test above and check
3123 that the single "Main" symbol is emitted and handled properly.
3124 There's no specific test-case. */
3125 struct mmo_symbol sym;
3126
3127 (*_bfd_error_handler)
3128 (_("%s: warning: symbol table too large for mmo, larger than 65535\
3129 32-bit words: %d. Only `Main' will be emitted.\n"),
3130 bfd_get_filename (abfd), trie_len);
3131
3132 memset (&sym, 0, sizeof (sym));
3133 sym.sym_type = mmo_abs_sym;
3134 sym.name = MMIX_START_SYMBOL_NAME;
3135 sym.serno = 1;
3136 sym.value = bfd_get_start_address (abfd);
3137
3138 /* Then patch up a symbol table to be just the ":Main" symbol. */
3139 memset (&root, 0, sizeof (root));
3140 root.left = root.middle;
3141 root.symchar = 0xff;
3142 root.middle = NULL;
3143 root.right = NULL;
3144
3145 if (! mmo_internal_add_3_sym (abfd, &root, &sym))
b34976b6 3146 return FALSE;
3c3bdf30
NC
3147
3148 root.symchar = ':';
3149 root.middle = root.left;
3150 root.right = NULL;
3151 root.left = NULL;
3152
3153 trie_len = (mmo_internal_3_length (abfd, &root) + 3)/4;
3154 }
3155
3156 /* Reset the written-bytes counter. */
3157 abfd->tdata.mmo_data->byte_no = 0;
3158
3159 /* Put out the lop_stab mark. */
3160 bfd_put_32 (abfd, (LOP << 24) | (LOP_STAB << 16), buf);
3161 if (bfd_bwrite (buf, 4, abfd) != 4)
b34976b6 3162 return FALSE;
3c3bdf30
NC
3163
3164 /* Dump out symbols. */
3165 mmo_internal_3_dump (abfd, &root);
3166
3167 if (trie_len != (abfd->tdata.mmo_data->byte_no + 3)/4)
3168 {
3169 /* I haven't seen this trig. It seems no use claiming this case
3170 isn't debugged and abort if we get here. Instead emit a
3171 diagnostic and fail "normally". */
3172 (*_bfd_error_handler)
3173 (_("%s: internal error, symbol table changed size from %d to %d\
3174 words\n"),
3175 bfd_get_filename (abfd), trie_len,
3176 (abfd->tdata.mmo_data->byte_no + 3)/4);
3177 bfd_set_error (bfd_error_bad_value);
b34976b6 3178 return FALSE;
3c3bdf30
NC
3179 }
3180
3181 /* Dump out remaining bytes in the buffer and handle I/O errors by
3182 propagating errors. */
3183 if ((abfd->tdata.mmo_data->byte_no % 4) != 0
3184 || abfd->tdata.mmo_data->have_error)
3185 {
3186 memset (abfd->tdata.mmo_data->buf + (abfd->tdata.mmo_data->byte_no % 4),
3187 0, 4 - (abfd->tdata.mmo_data->byte_no % 4));
3188
3189 if (abfd->tdata.mmo_data->have_error
3190 || bfd_bwrite (abfd->tdata.mmo_data->buf, 4, abfd) != 4)
b34976b6 3191 return FALSE;
3c3bdf30
NC
3192 }
3193
3194 bfd_put_32 (abfd, (LOP << 24) | (LOP_END << 16) | trie_len, buf);
3195 return bfd_bwrite (buf, 4, abfd) == 4;
3196}
3197
3198/* Write section unless it is the register contents section. For that, we
3199 instead store the section in the supplied pointer. This function is
3200 used through bfd_map_over_sections. */
3201
3202static void
3203mmo_write_section_unless_reg_contents (abfd, sec, p)
3204 bfd *abfd;
3205 asection *sec;
3206 PTR p;
3207{
3208 struct mmo_write_sec_info *infop = (struct mmo_write_sec_info *) p;
3209
82e51918 3210 if (! infop->retval)
3c3bdf30
NC
3211 return;
3212
3213 if (strcmp (sec->name, MMIX_REG_CONTENTS_SECTION_NAME) == 0)
3214 {
3215 infop->reg_section = sec;
3216 return;
3217 }
3218
3219 /* Exclude the convenience register section. */
3220 if (strcmp (sec->name, MMIX_REG_SECTION_NAME) == 0)
3221 {
3222 if (bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS)
3223 {
3224 /* Make sure it hasn't got contents. It seems impossible to
3225 make it carry contents, so we don't have a test-case for
3226 this. */
3227 (*_bfd_error_handler)
3228 (_("%s: internal error, internal register section %s had\
3229 contents\n"),
3230 bfd_get_filename (abfd), sec->name);
3231 bfd_set_error (bfd_error_bad_value);
b34976b6 3232 infop->retval = FALSE;
3c3bdf30
NC
3233 return;
3234 }
3235
3236 return;
3237 }
3238
3239 infop->retval = mmo_internal_write_section (abfd, sec);
3240}
3241
3242/* Do the actual output of a file. Assumes mmo_set_section_contents is
3243 already called. */
3244
b34976b6 3245static bfd_boolean
3c3bdf30
NC
3246mmo_write_object_contents (abfd)
3247 bfd *abfd;
3248{
3249 struct mmo_write_sec_info wsecinfo;
3250
3251 /* First, there are a few words of preamble. */
3252 if (! mmo_internal_write_header (abfd))
b34976b6 3253 return FALSE;
3c3bdf30
NC
3254
3255 wsecinfo.reg_section = NULL;
b34976b6 3256 wsecinfo.retval = TRUE;
3c3bdf30
NC
3257
3258 bfd_map_over_sections (abfd, mmo_write_section_unless_reg_contents,
3259 (PTR) &wsecinfo);
3260
82e51918 3261 if (! wsecinfo.retval)
b34976b6 3262 return FALSE;
3c3bdf30
NC
3263
3264 if (wsecinfo.reg_section != NULL)
3265 {
3266 asection *sec = wsecinfo.reg_section;
3267 unsigned int z = (unsigned int) (sec->vma / 8);
3268
3269 /* Registers 0..31 must not be global. Do sanity check on the "vma"
3270 of the register contents section and check that it corresponds to
3271 the length of the section. */
3272 if (z < 32 || z >= 255 || (sec->vma & 7) != 0
eea6121a 3273 || sec->vma != 256 * 8 - sec->size - 8)
3c3bdf30
NC
3274 {
3275 bfd_set_error (bfd_error_bad_value);
3276
eea6121a 3277 if (sec->size == 0)
3c3bdf30
NC
3278 /* There must always be at least one such register. */
3279 (*_bfd_error_handler)
3280 (_("%s: no initialized registers; section length 0\n"),
3281 bfd_get_filename (abfd));
3282 else if (sec->vma > (256 - 32) * 8)
3283 /* Provide better error message for the case of too many
3284 global registers. */
3285 (*_bfd_error_handler)
3286 (_("%s: too many initialized registers; section length %ld\n"),
3287 bfd_get_filename (abfd),
eea6121a 3288 (long) sec->size);
3c3bdf30
NC
3289 else
3290 (*_bfd_error_handler)
3291 (_("%s: invalid start address for initialized registers of\
3292 length %ld: 0x%lx%08lx\n"),
3293 bfd_get_filename (abfd),
eea6121a 3294 (long) sec->size,
3c3bdf30
NC
3295 (unsigned long) (sec->vma >> 32), (unsigned long) (sec->vma));
3296
b34976b6 3297 return FALSE;
3c3bdf30
NC
3298 }
3299
3300 if (! mmo_internal_write_post (abfd, z, sec))
b34976b6 3301 return FALSE;
3c3bdf30
NC
3302 }
3303 else
3304 if (! mmo_internal_write_post (abfd, 255, NULL))
b34976b6 3305 return FALSE;
3c3bdf30
NC
3306
3307 return mmo_write_symbols_and_terminator (abfd);
3308}
3309
3310/* Return the size of a NULL pointer, so we support linking in an mmo
3311 object. */
3312
3313static long
3314mmo_get_reloc_upper_bound (abfd, sec)
3315 bfd *abfd ATTRIBUTE_UNUSED;
3316 asection *sec ATTRIBUTE_UNUSED;
3317{
3318 return sizeof (PTR);
3319}
3320
3321/* Similarly canonicalize relocs to empty, filling in the terminating NULL
3322 pointer. */
3323
3324long
3325mmo_canonicalize_reloc (abfd, section, relptr, symbols)
3326 bfd *abfd ATTRIBUTE_UNUSED;
3327 sec_ptr section ATTRIBUTE_UNUSED;
3328 arelent **relptr;
3329 asymbol **symbols ATTRIBUTE_UNUSED;
3330{
3331 *relptr = NULL;
3332 return 0;
3333}
3334
3335/* If there's anything in particular in a mmo bfd that we want to free,
3336 make this a real function. Only do this if you see major memory
3337 thrashing; zealous free:ing will cause unwanted behavior, especially if
3338 you "free" memory allocated with "bfd_alloc", or even "bfd_release" a
3339 block allocated with "bfd_alloc"; they're really allocated from an
3340 obstack, and we don't know what was allocated there since this
3341 particular allocation. */
3342
3343#define mmo_close_and_cleanup _bfd_generic_close_and_cleanup
3344#define mmo_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
3345
3346/* Perhaps we need to adjust this one; mmo labels (originally) without a
3347 leading ':' might more appropriately be called local. */
3348#define mmo_bfd_is_local_label_name bfd_generic_is_local_label_name
3c9458e9
NC
3349#define mmo_bfd_is_target_special_symbol \
3350 ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
3c3bdf30
NC
3351
3352/* Is this one really used or defined by anyone? */
3353#define mmo_get_lineno _bfd_nosymbols_get_lineno
3354
3355/* FIXME: We can do better on this one, if we have a dwarf2 .debug_line
3356 section or if MMO line numbers are implemented. */
3357#define mmo_find_nearest_line _bfd_nosymbols_find_nearest_line
3f3c5c34 3358#define mmo_make_empty_symbol _bfd_generic_make_empty_symbol
3c3bdf30
NC
3359#define mmo_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
3360#define mmo_read_minisymbols _bfd_generic_read_minisymbols
3361#define mmo_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
3362
3363#define mmo_get_section_contents_in_window \
3364 _bfd_generic_get_section_contents_in_window
3365#define mmo_bfd_get_relocated_section_contents \
3366 bfd_generic_get_relocated_section_contents
3367#define mmo_bfd_gc_sections bfd_generic_gc_sections
3368#define mmo_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
e2d34d7d 3369#define mmo_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
3c3bdf30 3370#define mmo_bfd_link_add_symbols _bfd_generic_link_add_symbols
2d653fc7 3371#define mmo_bfd_link_just_syms _bfd_generic_link_just_syms
3c3bdf30
NC
3372#define mmo_bfd_final_link _bfd_generic_final_link
3373#define mmo_bfd_link_split_section _bfd_generic_link_split_section
3374
3375/* Strictly speaking, only MMIX uses this restricted format, but let's not
3376 stop anybody from shooting themselves in the foot. */
3377#define mmo_set_arch_mach bfd_default_set_arch_mach
3378#define mmo_bfd_relax_section bfd_generic_relax_section
3379#define mmo_bfd_merge_sections bfd_generic_merge_sections
72adc230 3380#define mmo_bfd_is_group_section bfd_generic_is_group_section
e61463e1 3381#define mmo_bfd_discard_group bfd_generic_discard_group
082b7297
L
3382#define mmo_section_already_linked \
3383 _bfd_generic_section_already_linked
3c3bdf30
NC
3384
3385/* objcopy will be upset if we return -1 from bfd_get_reloc_upper_bound by
3386 using BFD_JUMP_TABLE_RELOCS (_bfd_norelocs) rather than 0. FIXME: Most
3387 likely a bug in the _bfd_norelocs definition.
3388
3389 On the other hand, we smuggle in an mmo object (because setting up ELF
3390 is too cumbersome) when linking (from other formats, presumably ELF) to
3391 represent the g255 entry. We need to link that object, so need to say
3392 it has no relocs. Upper bound for the size of the relocation table is
3393 the size of a NULL pointer, and we support "canonicalization" for that
3394 pointer. */
3395#define mmo_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
3396
3397/* We want to copy time of creation, otherwise we'd use
3398 BFD_JUMP_TABLE_COPY (_bfd_generic). */
3399#define mmo_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
3400#define mmo_bfd_copy_private_section_data _bfd_generic_bfd_copy_private_section_data
3401#define mmo_bfd_copy_private_symbol_data _bfd_generic_bfd_copy_private_symbol_data
80fccad2 3402#define mmo_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data
3c3bdf30
NC
3403#define mmo_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
3404#define mmo_bfd_print_private_bfd_data _bfd_generic_bfd_print_private_bfd_data
3405
3f9c735e 3406const bfd_target bfd_mmo_vec =
3c3bdf30
NC
3407{
3408 "mmo", /* name */
3409 bfd_target_mmo_flavour,
3410 BFD_ENDIAN_BIG, /* target byte order */
3411 BFD_ENDIAN_BIG, /* target headers byte order */
3412
3413 /* FIXME: Might need adjustments. */
3414 (HAS_RELOC | EXEC_P | /* object flags */
3415 HAS_LINENO | HAS_DEBUG |
3416 HAS_SYMS | HAS_LOCALS | WP_TEXT),
3417
3418 /* FIXME: Might need adjustments. */
3419 (SEC_CODE | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
3420 | SEC_READONLY | SEC_EXCLUDE | SEC_DEBUGGING | SEC_IN_MEMORY),
3421 /* section flags */
3422 0, /* leading underscore */
3423 ' ', /* ar_pad_char */
3424 16, /* ar_max_namelen */
3425 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
3426 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
3427 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
3428 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
3429 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
3430 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
3431
3432 {
3433 _bfd_dummy_target,
3434 mmo_object_p, /* bfd_check_format */
3435 _bfd_dummy_target,
3436 _bfd_dummy_target,
3437 },
3438 {
3439 bfd_false,
3440 mmo_mkobject,
3441 bfd_false,
3442 bfd_false,
3443 },
3444 { /* bfd_write_contents */
3445 bfd_false,
3446 mmo_write_object_contents,
3447 bfd_false,
3448 bfd_false,
3449 },
3450
3451 BFD_JUMP_TABLE_GENERIC (mmo),
3452 BFD_JUMP_TABLE_COPY (mmo),
3453 BFD_JUMP_TABLE_CORE (_bfd_nocore),
3454 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
3455 BFD_JUMP_TABLE_SYMBOLS (mmo),
3456 /* We have to provide a valid method for getting relocs, returning zero,
3457 so we can't say BFD_JUMP_TABLE_RELOCS (_bfd_norelocs). */
3458 BFD_JUMP_TABLE_RELOCS (mmo),
3459 BFD_JUMP_TABLE_WRITE (mmo),
3460 BFD_JUMP_TABLE_LINK (mmo),
3461 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
3462
3463 NULL,
3464
3465 NULL
3466};
This page took 0.335867 seconds and 4 git commands to generate.