Back to index

cell-binutils  2.17cvs20070401
mmo.c
Go to the documentation of this file.
00001 /* BFD back-end for mmo objects (MMIX-specific object-format).
00002    Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007
00003    Free Software Foundation, Inc.
00004    Written by Hans-Peter Nilsson (hp@bitrange.com).
00005    Infrastructure and other bits originally copied from srec.c and
00006    binary.c.
00007 
00008 This file is part of BFD, the Binary File Descriptor library.
00009 
00010 This program is free software; you can redistribute it and/or modify
00011 it under the terms of the GNU General Public License as published by
00012 the Free Software Foundation; either version 2 of the License, or
00013 (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00023 
00024 /*
00025 SECTION
00026        mmo backend
00027 
00028        The mmo object format is used exclusively together with Professor
00029        Donald E.@: Knuth's educational 64-bit processor MMIX.  The simulator
00030        @command{mmix} which is available at
00031        @url{http://www-cs-faculty.stanford.edu/~knuth/programs/mmix.tar.gz}
00032        understands this format.  That package also includes a combined
00033        assembler and linker called @command{mmixal}.  The mmo format has
00034        no advantages feature-wise compared to e.g. ELF.  It is a simple
00035        non-relocatable object format with no support for archives or
00036        debugging information, except for symbol value information and
00037        line numbers (which is not yet implemented in BFD).  See
00038        @url{http://www-cs-faculty.stanford.edu/~knuth/mmix.html} for more
00039        information about MMIX.  The ELF format is used for intermediate
00040        object files in the BFD implementation.
00041 
00042 @c We want to xref the symbol table node.  A feature in "chew"
00043 @c requires that "commands" do not contain spaces in the
00044 @c arguments.  Hence the hyphen in "Symbol-table".
00045 @menu
00046 @* File layout::
00047 @* Symbol-table::
00048 @* mmo section mapping::
00049 @end menu
00050 
00051 INODE
00052 File layout, Symbol-table, mmo, mmo
00053 SUBSECTION
00054        File layout
00055 
00056        The mmo file contents is not partitioned into named sections as
00057        with e.g.@: ELF.  Memory areas is formed by specifying the
00058        location of the data that follows.  Only the memory area
00059        @samp{0x0000@dots{}00} to @samp{0x01ff@dots{}ff} is executable, so
00060        it is used for code (and constants) and the area
00061        @samp{0x2000@dots{}00} to @samp{0x20ff@dots{}ff} is used for
00062        writable data.  @xref{mmo section mapping}.
00063 
00064        There is provision for specifying ``special data'' of 65536
00065        different types.  We use type 80 (decimal), arbitrarily chosen the
00066        same as the ELF <<e_machine>> number for MMIX, filling it with
00067        section information normally found in ELF objects. @xref{mmo
00068        section mapping}.
00069 
00070        Contents is entered as 32-bit words, xor:ed over previous
00071        contents, always zero-initialized.  A word that starts with the
00072        byte @samp{0x98} forms a command called a @samp{lopcode}, where
00073        the next byte distinguished between the thirteen lopcodes.  The
00074        two remaining bytes, called the @samp{Y} and @samp{Z} fields, or
00075        the @samp{YZ} field (a 16-bit big-endian number), are used for
00076        various purposes different for each lopcode.  As documented in
00077        @url{http://www-cs-faculty.stanford.edu/~knuth/mmixal-intro.ps.gz},
00078        the lopcodes are:
00079 
00080        @table @code
00081        @item lop_quote
00082        0x98000001.  The next word is contents, regardless of whether it
00083        starts with 0x98 or not.
00084 
00085        @item lop_loc
00086        0x9801YYZZ, where @samp{Z} is 1 or 2.  This is a location
00087        directive, setting the location for the next data to the next
00088        32-bit word (for @math{Z = 1}) or 64-bit word (for @math{Z = 2}),
00089        plus @math{Y * 2^56}.  Normally @samp{Y} is 0 for the text segment
00090        and 2 for the data segment.
00091 
00092        @item lop_skip
00093        0x9802YYZZ.  Increase the current location by @samp{YZ} bytes.
00094 
00095        @item lop_fixo
00096        0x9803YYZZ, where @samp{Z} is 1 or 2.  Store the current location
00097        as 64 bits into the location pointed to by the next 32-bit
00098        (@math{Z = 1}) or 64-bit (@math{Z = 2}) word, plus @math{Y *
00099        2^56}.
00100 
00101        @item lop_fixr
00102        0x9804YYZZ.  @samp{YZ} is stored into the current location plus
00103        @math{2 - 4 * YZ}.
00104 
00105        @item lop_fixrx
00106        0x980500ZZ.  @samp{Z} is 16 or 24.  A value @samp{L} derived from
00107        the following 32-bit word are used in a manner similar to
00108        @samp{YZ} in lop_fixr: it is xor:ed into the current location
00109        minus @math{4 * L}.  The first byte of the word is 0 or 1.  If it
00110        is 1, then @math{L = (@var{lowest 24 bits of word}) - 2^Z}, if 0,
00111        then @math{L = (@var{lowest 24 bits of word})}.
00112 
00113        @item lop_file
00114        0x9806YYZZ.  @samp{Y} is the file number, @samp{Z} is count of
00115        32-bit words.  Set the file number to @samp{Y} and the line
00116        counter to 0.  The next @math{Z * 4} bytes contain the file name,
00117        padded with zeros if the count is not a multiple of four.  The
00118        same @samp{Y} may occur multiple times, but @samp{Z} must be 0 for
00119        all but the first occurrence.
00120 
00121        @item lop_line
00122        0x9807YYZZ.  @samp{YZ} is the line number.  Together with
00123        lop_file, it forms the source location for the next 32-bit word.
00124        Note that for each non-lopcode 32-bit word, line numbers are
00125        assumed incremented by one.
00126 
00127        @item lop_spec
00128        0x9808YYZZ.  @samp{YZ} is the type number.  Data until the next
00129        lopcode other than lop_quote forms special data of type @samp{YZ}.
00130        @xref{mmo section mapping}.
00131 
00132        Other types than 80, (or type 80 with a content that does not
00133        parse) is stored in sections named <<.MMIX.spec_data.@var{n}>>
00134        where @var{n} is the @samp{YZ}-type.  The flags for such a
00135        sections say not to allocate or load the data.  The vma is 0.
00136        Contents of multiple occurrences of special data @var{n} is
00137        concatenated to the data of the previous lop_spec @var{n}s.  The
00138        location in data or code at which the lop_spec occurred is lost.
00139 
00140        @item lop_pre
00141        0x980901ZZ.  The first lopcode in a file.  The @samp{Z} field forms the
00142        length of header information in 32-bit words, where the first word
00143        tells the time in seconds since @samp{00:00:00 GMT Jan 1 1970}.
00144 
00145        @item lop_post
00146        0x980a00ZZ.  @math{Z > 32}.  This lopcode follows after all
00147        content-generating lopcodes in a program.  The @samp{Z} field
00148        denotes the value of @samp{rG} at the beginning of the program.
00149        The following @math{256 - Z} big-endian 64-bit words are loaded
00150        into global registers @samp{$G} @dots{} @samp{$255}.
00151 
00152        @item lop_stab
00153        0x980b0000.  The next-to-last lopcode in a program.  Must follow
00154        immediately after the lop_post lopcode and its data.  After this
00155        lopcode follows all symbols in a compressed format
00156        (@pxref{Symbol-table}).
00157 
00158        @item lop_end
00159        0x980cYYZZ.  The last lopcode in a program.  It must follow the
00160        lop_stab lopcode and its data.  The @samp{YZ} field contains the
00161        number of 32-bit words of symbol table information after the
00162        preceding lop_stab lopcode.
00163        @end table
00164 
00165        Note that the lopcode "fixups"; <<lop_fixr>>, <<lop_fixrx>> and
00166        <<lop_fixo>> are not generated by BFD, but are handled.  They are
00167        generated by <<mmixal>>.
00168 
00169 EXAMPLE
00170        This trivial one-label, one-instruction file:
00171 
00172 | :Main TRAP 1,2,3
00173 
00174        can be represented this way in mmo:
00175 
00176 | 0x98090101 - lop_pre, one 32-bit word with timestamp.
00177 | <timestamp>
00178 | 0x98010002 - lop_loc, text segment, using a 64-bit address.
00179 |              Note that mmixal does not emit this for the file above.
00180 | 0x00000000 - Address, high 32 bits.
00181 | 0x00000000 - Address, low 32 bits.
00182 | 0x98060002 - lop_file, 2 32-bit words for file-name.
00183 | 0x74657374 - "test"
00184 | 0x2e730000 - ".s\0\0"
00185 | 0x98070001 - lop_line, line 1.
00186 | 0x00010203 - TRAP 1,2,3
00187 | 0x980a00ff - lop_post, setting $255 to 0.
00188 | 0x00000000
00189 | 0x00000000
00190 | 0x980b0000 - lop_stab for ":Main" = 0, serial 1.
00191 | 0x203a4040   @xref{Symbol-table}.
00192 | 0x10404020
00193 | 0x4d206120
00194 | 0x69016e00
00195 | 0x81000000
00196 | 0x980c0005 - lop_end; symbol table contained five 32-bit words.  */
00197 
00198 #include "bfd.h"
00199 #include "sysdep.h"
00200 #include "libbfd.h"
00201 #include "libiberty.h"
00202 #include "elf/mmix.h"
00203 #include "opcode/mmix.h"
00204 
00205 #define LOP 0x98
00206 #define LOP_QUOTE 0
00207 #define LOP_LOC 1
00208 #define LOP_SKIP 2
00209 #define LOP_FIXO 3
00210 #define LOP_FIXR 4
00211 #define LOP_FIXRX 5
00212 #define LOP_FILE 6
00213 #define LOP_LINE 7
00214 #define LOP_SPEC 8
00215 #define LOP_PRE 9
00216 #define LOP_POST 10
00217 #define LOP_STAB 11
00218 #define LOP_END 12
00219 
00220 #define LOP_QUOTE_NEXT ((LOP << 24) | (LOP_QUOTE << 16) | 1)
00221 #define SPEC_DATA_SECTION 80
00222 #define LOP_SPEC_SECTION \
00223  ((LOP << 24) | (LOP_SPEC << 16) | SPEC_DATA_SECTION)
00224 
00225 /* Must be a power of two.  If you change this to be >= 64k, you need a
00226    new test-case; the ld test b-loc64k.d touches chunk-size problem areas.  */
00227 #define MMO_SEC_CONTENTS_CHUNK_SIZE (1 << 15)
00228 
00229 /* An arbitrary number for the maximum length section name size.  */
00230 #define MAX_SECTION_NAME_SIZE (1024 * 1024)
00231 
00232 /* A quite arbitrary number for the maximum length section size.  */
00233 #define MAX_ARTIFICIAL_SECTION_SIZE (1024 * 1024 * 1024)
00234 
00235 #define MMO3_WCHAR 0x80
00236 #define MMO3_LEFT 0x40
00237 #define MMO3_MIDDLE 0x20
00238 #define MMO3_RIGHT 0x10
00239 #define MMO3_TYPEBITS 0xf
00240 #define MMO3_REGQUAL_BITS 0xf
00241 #define MMO3_UNDEF 2
00242 #define MMO3_DATA 8
00243 #define MMO3_SYMBITS 0x2f
00244 
00245 /* Put these everywhere in new code.  */
00246 #define FATAL_DEBUG                                     \
00247  _bfd_abort (__FILE__, __LINE__,                        \
00248             "Internal: Non-debugged code (test-case missing)")
00249 
00250 #define BAD_CASE(x)                       \
00251  _bfd_abort (__FILE__, __LINE__,          \
00252             "bad case for " #x)
00253 
00254 enum mmo_sym_type { mmo_reg_sym, mmo_undef_sym, mmo_data_sym, mmo_abs_sym};
00255 
00256 /* When scanning the mmo file, a linked list of mmo_symbol
00257    structures is built to represent the symbol table (if there is
00258    one).  */
00259 
00260 struct mmo_symbol
00261   {
00262     struct mmo_symbol *next;
00263     char *name;
00264     bfd_vma value;
00265     enum mmo_sym_type sym_type;
00266     unsigned int serno;
00267   };
00268 
00269 struct mmo_data_list_struct
00270   {
00271     struct mmo_data_list_struct *next;
00272     bfd_vma where;
00273     bfd_size_type size;
00274     bfd_size_type allocated_size;
00275     bfd_byte data[1];
00276   };
00277 
00278 typedef struct mmo_data_list_struct mmo_data_list_type;
00279 
00280 struct mmo_symbol_trie
00281   {
00282     struct mmo_symbol_trie *left;
00283     struct mmo_symbol_trie *right;
00284     struct mmo_symbol_trie *middle;
00285 
00286     bfd_byte symchar;
00287 
00288     /* A zero name means there's nothing here.  */
00289     struct mmo_symbol sym;
00290   };
00291 
00292 /* The mmo tdata information.  */
00293 
00294 struct mmo_data_struct
00295   {
00296     struct mmo_symbol *symbols;
00297     struct mmo_symbol *symtail;
00298     asymbol *csymbols;
00299 
00300     /* File representation of time (NULL) when this file was created.  */
00301     bfd_byte created[4];
00302 
00303     /* When we're reading bytes recursively, check this occasionally.
00304        Also holds write errors.  */
00305     bfd_boolean have_error;
00306 
00307     /* Max symbol length that may appear in the lop_stab table.  Note that
00308        this table might just hold a subset of symbols for not-really large
00309        programs, as it can only be 65536 * 4 bytes large.  */
00310     int max_symbol_length;
00311 
00312     /* Here's the symbol we build in lop_stab.  */
00313     char *lop_stab_symbol;
00314 
00315     /* Index into lop_stab_symbol for the next character when parsing the
00316        symbol information.  */
00317     int symbol_position;
00318 
00319     /* When creating arbitrary sections, we need to count section numbers.  */
00320     int sec_no;
00321 
00322     /* When writing or reading byte-wise, we need to count the bytes
00323        within a 32-bit word.  */
00324     int byte_no;
00325 
00326     /* We also need a buffer to hold the bytes we count reading or writing.  */
00327     bfd_byte buf[4];
00328   };
00329 
00330 typedef struct mmo_data_struct tdata_type;
00331 
00332 struct mmo_section_data_struct
00333   {
00334     mmo_data_list_type *head;
00335     mmo_data_list_type *tail;
00336   };
00337 
00338 #define mmo_section_data(sec) \
00339   ((struct mmo_section_data_struct *) (sec)->used_by_bfd)
00340 
00341 /* These structures are used in bfd_map_over_sections constructs.  */
00342 
00343 /* Used when writing out sections; all but the register contents section
00344    which is stored in reg_section.  */
00345 struct mmo_write_sec_info
00346   {
00347     asection *reg_section;
00348     bfd_boolean retval;
00349   };
00350 
00351 /* Used when trying to find a section corresponding to addr.  */
00352 struct mmo_find_sec_info
00353   {
00354     asection *sec;
00355     bfd_vma addr;
00356   };
00357 
00358 static bfd_boolean mmo_bfd_copy_private_bfd_data (bfd *, bfd *);
00359 static void mmo_write_section_unless_reg_contents (bfd *, asection *, void *);
00360 static void mmo_find_sec_w_addr (bfd *, asection *, void *);
00361 static void mmo_find_sec_w_addr_grow (bfd *, asection *, void *);
00362 static asection *mmo_make_section (bfd *, const char *);
00363 static void mmo_get_symbol_info (bfd *, asymbol *, symbol_info *);
00364 static void mmo_print_symbol (bfd *, void *, asymbol *, 
00365                            bfd_print_symbol_type);
00366 static void mmo_init (void);
00367 static bfd_boolean mmo_mkobject (bfd *);
00368 static bfd_boolean mmo_scan (bfd *);
00369 static asection *mmo_decide_section (bfd *, bfd_vma);
00370 static asection *mmo_get_generic_spec_data_section (bfd *, int);
00371 static asection *mmo_get_spec_section (bfd *, int);
00372 static INLINE bfd_byte *mmo_get_loc (asection *, bfd_vma, int);
00373 static void mmo_xore_64 (asection *, bfd_vma vma, bfd_vma value);
00374 static void mmo_xore_32 (asection *, bfd_vma vma, unsigned int);
00375 static void mmo_xore_16 (asection *, bfd_vma vma, unsigned int);
00376 static const bfd_target *mmo_object_p (bfd *);
00377 static void mmo_map_set_sizes (bfd *, asection *, void *);
00378 static bfd_boolean mmo_get_symbols (bfd *);
00379 static bfd_boolean mmo_create_symbol (bfd *, const char *, bfd_vma,
00380                                   enum mmo_sym_type, unsigned int);
00381 static bfd_boolean mmo_get_section_contents (bfd *, asection *, void *,
00382                                         file_ptr, bfd_size_type);
00383 static long mmo_get_symtab_upper_bound (bfd *);
00384 static long mmo_canonicalize_symtab (bfd *, asymbol **);
00385 static void mmo_get_symbol_info (bfd *, asymbol *, symbol_info *);
00386 static void mmo_print_symbol (bfd *, void *, asymbol *,
00387                            bfd_print_symbol_type);
00388 static bfd_boolean mmo_set_section_contents (bfd *, sec_ptr, const void *,
00389                                         file_ptr, bfd_size_type);
00390 static int mmo_sizeof_headers (bfd *, struct bfd_link_info *);
00391 static bfd_boolean mmo_internal_write_header (bfd *);
00392 static bfd_boolean mmo_internal_write_post (bfd *, int, asection *);
00393 static bfd_boolean mmo_internal_add_3_sym (bfd *, struct mmo_symbol_trie *,
00394                                       const struct mmo_symbol *);
00395 static unsigned int mmo_internal_3_length (bfd *, struct mmo_symbol_trie *);
00396 static void mmo_internal_3_dump (bfd *, struct mmo_symbol_trie *);
00397 static void mmo_beb128_out (bfd *, int, int);
00398 static bfd_boolean mmo_internal_write_section (bfd *, asection *);
00399 static void mmo_write_tetra (bfd *, unsigned int);
00400 static void mmo_write_tetra_raw (bfd *, unsigned int);
00401 static void mmo_write_octa (bfd *, bfd_vma);
00402 static void mmo_write_octa_raw (bfd *, bfd_vma);
00403 static bfd_boolean mmo_write_chunk (bfd *, const bfd_byte *, unsigned int);
00404 static bfd_boolean mmo_flush_chunk (bfd *);
00405 static bfd_boolean mmo_write_loc_chunk (bfd *, bfd_vma, const bfd_byte *,
00406                                    unsigned int, bfd_vma *);
00407 static bfd_boolean mmo_write_chunk_list (bfd *, mmo_data_list_type *);
00408 static bfd_boolean mmo_write_loc_chunk_list (bfd *, mmo_data_list_type *);
00409 static bfd_boolean mmo_write_symbols_and_terminator (bfd *);
00410 static flagword mmo_sec_flags_from_bfd_flags (flagword);
00411 static flagword bfd_sec_flags_from_mmo_flags (flagword);
00412 static bfd_byte mmo_get_byte (bfd *);
00413 static void mmo_write_byte (bfd *, bfd_byte);
00414 static bfd_boolean mmo_new_section_hook (bfd *, asection *);
00415 static int mmo_sort_mmo_symbols (const void *, const void *);
00416 static bfd_boolean mmo_write_object_contents (bfd *);
00417 static bfd_boolean mmo_write_section_description (bfd *, asection *);
00418 static bfd_boolean mmo_has_leading_or_trailing_zero_tetra_p (bfd *,
00419                                                       asection *);
00420 
00421 /* Global "const" variables initialized once.  Must not depend on
00422    particular input or caller; put such things into the bfd or elsewhere.
00423    Look ma, no static per-invocation data!  */
00424 
00425 static
00426 char valid_mmo_symbol_character_set[/* A-Z a-z (we assume consecutive
00427                                    codes; sorry EBCDIC:ers!).  */
00428                                 + 'Z' - 'A' + 1 + 'z' - 'a' + 1
00429                                 /* Digits.  */
00430                                 + 10
00431                                 /* ':' and '_'.  */
00432                                 + 1 + 1
00433                                 /* Codes higher than 126.  */
00434                                 + 256 - 126
00435                                 /* Ending zero.  */
00436                                 + 1];
00437 
00438 
00439 /* Get section SECNAME or create one if it doesn't exist.  When creating
00440    one, new memory for the name is allocated.  */
00441 
00442 static asection *
00443 mmo_make_section (bfd *abfd, const char *secname)
00444 {
00445   asection *sec = bfd_get_section_by_name (abfd, secname);
00446 
00447   if (sec == NULL)
00448     {
00449       char *newsecname = strdup (secname);
00450 
00451       if (newsecname == NULL)
00452        {
00453          (*_bfd_error_handler)
00454            (_("%s: No core to allocate section name %s\n"),
00455             bfd_get_filename (abfd), secname);
00456          bfd_set_error (bfd_error_system_call);
00457          return NULL;
00458        }
00459       sec = bfd_make_section (abfd, newsecname);
00460     }
00461 
00462   return sec;
00463 }
00464 
00465 /* Nothing to do, but keep as a placeholder if we need it.
00466    Note that state that might differ between bfd:s must not be initialized
00467    here, nor must it be static.  Add it to tdata information instead.  */
00468 
00469 static void
00470 mmo_init (void)
00471 {
00472   static bfd_boolean inited = FALSE;
00473   int i = 0;
00474   int j = 0;
00475   static const char letters[]
00476     = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789:_";
00477 
00478   if (inited)
00479     return;
00480   inited = TRUE;
00481 
00482   /* Fill in the set of valid symbol characters.  */
00483   strcpy (valid_mmo_symbol_character_set, letters);
00484   i = strlen (letters);
00485 
00486   for (j = 126; j < 256; j++)
00487     valid_mmo_symbol_character_set[i++] = j;
00488 }
00489 
00490 /* Check whether an existing file is an mmo file.  */
00491 
00492 static const bfd_target *
00493 mmo_object_p (bfd *abfd)
00494 {
00495   struct stat statbuf;
00496   bfd_byte b[4];
00497 
00498   mmo_init ();
00499 
00500   if (bfd_stat (abfd, &statbuf) < 0
00501       || bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
00502       || bfd_bread (b, 4, abfd) != 4)
00503     goto bad_final;
00504 
00505   /* All mmo files are a multiple of four bytes long.
00506      Only recognize version one.  */
00507   if ((statbuf.st_size % 4) != 0
00508       || b[0] != LOP || b[1] != LOP_PRE || b[2] != 1)
00509     goto bad_format;
00510 
00511   /* Get the last 32-bit word.  */
00512   if (bfd_seek (abfd, (file_ptr) statbuf.st_size - 4, SEEK_SET) != 0
00513       || bfd_bread (b, 4, abfd) != 4)
00514     goto bad_final;
00515 
00516   /* Check if the file ends in a lop_end lopcode. */
00517   if (b[0] != LOP || b[1] != LOP_END || ! mmo_mkobject (abfd))
00518     goto bad_format;
00519 
00520   /* Compute an upper bound on the max symbol length.  Not really
00521      important as all of the symbol information can only be 256k.  */
00522   abfd->tdata.mmo_data->max_symbol_length = (b[2] * 256 + b[3]) * 4;
00523   abfd->tdata.mmo_data->lop_stab_symbol
00524     = bfd_malloc (abfd->tdata.mmo_data->max_symbol_length + 1);
00525 
00526   if (abfd->tdata.mmo_data->lop_stab_symbol == NULL)
00527     {
00528       (*_bfd_error_handler)
00529        (_("%s: No core to allocate a symbol %d bytes long\n"),
00530         bfd_get_filename (abfd), abfd->tdata.mmo_data->max_symbol_length);
00531       goto bad_final;
00532     }
00533 
00534   /* Read in everything.  */
00535   if (! mmo_scan (abfd))
00536     goto bad_format_free;
00537 
00538   if (abfd->symcount > 0)
00539     abfd->flags |= HAS_SYMS;
00540 
00541   /* You'll have to tweak this if you want to use this format for other
00542      arches (not recommended due to its small-size limitations).  Look at
00543      the ELF format for how to make it target-generic.  */
00544   if (! bfd_default_set_arch_mach (abfd, bfd_arch_mmix, 0))
00545     goto bad_format_free;
00546 
00547   return abfd->xvec;
00548 
00549  bad_format_free:
00550   free (abfd->tdata.mmo_data->lop_stab_symbol);
00551  bad_format:
00552   bfd_set_error (bfd_error_wrong_format);
00553  bad_final:
00554   return NULL;
00555 }
00556 
00557 /* Set up the mmo tdata information.  */
00558 
00559 static bfd_boolean
00560 mmo_mkobject (bfd *abfd)
00561 {
00562   mmo_init ();
00563 
00564   if (abfd->tdata.mmo_data == NULL)
00565     {
00566       time_t created;
00567 
00568       /* All fields are zero-initialized, so we don't have to explicitly
00569         initialize most.  */
00570       tdata_type *tdata = (tdata_type *) bfd_zmalloc (sizeof (tdata_type));
00571       if (tdata == NULL)
00572        return FALSE;
00573 
00574       created = time (NULL);
00575       bfd_put_32 (abfd, created, tdata->created);
00576 
00577       abfd->tdata.mmo_data = tdata;
00578     }
00579 
00580   return TRUE;
00581 }
00582 
00583 static bfd_boolean
00584 mmo_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
00585 {
00586   if (bfd_get_flavour (ibfd) != bfd_target_mmo_flavour
00587       || bfd_get_flavour (obfd) != bfd_target_mmo_flavour)
00588     return TRUE;
00589 
00590   /* Copy the time the copied-from file was created.  If people want the
00591      time the file was last *modified*, they have that in the normal file
00592      information.  */
00593   memcpy (obfd->tdata.mmo_data->created, ibfd->tdata.mmo_data->created,
00594          sizeof (obfd->tdata.mmo_data->created));
00595   return TRUE;
00596 }
00597 
00598 /* Helper functions for mmo_decide_section, used through
00599    bfd_map_over_sections.  */
00600 
00601 static void
00602 mmo_find_sec_w_addr (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *p)
00603 {
00604   struct mmo_find_sec_info *infop = (struct mmo_find_sec_info *) p;
00605   bfd_vma vma = bfd_get_section_vma (abfd, sec);
00606 
00607   /* Ignore sections that aren't loaded.  */
00608   if ((bfd_get_section_flags (abfd, sec) & (SEC_LOAD | SEC_ALLOC))
00609       !=  (SEC_LOAD | SEC_ALLOC))
00610     return;
00611 
00612   if (infop->addr >= vma && infop->addr < vma + sec->size)
00613     infop->sec = sec;
00614 }
00615 
00616 static void
00617 mmo_find_sec_w_addr_grow (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *p)
00618 {
00619   struct mmo_find_sec_info *infop = (struct mmo_find_sec_info *) p;
00620   bfd_vma vma = bfd_get_section_vma (abfd, sec);
00621 
00622   /* Ignore sections that aren't loaded.  */
00623   if ((bfd_get_section_flags (abfd, sec) & (SEC_LOAD | SEC_ALLOC))
00624       !=  (SEC_LOAD | SEC_ALLOC))
00625     return;
00626 
00627   if (infop->addr >= vma && infop->addr < vma + MAX_ARTIFICIAL_SECTION_SIZE)
00628     infop->sec = sec;
00629 }
00630 
00631 /* Find a section that corresponds to a VMA.  Automatically create .text
00632    or .data and set current section to it, depending on what vma.  If we
00633    can't deduce a section, make one up as ".MMIX.sec.N", where N is an
00634    increasing number.  */
00635 
00636 static asection *
00637 mmo_decide_section (bfd *abfd, bfd_vma vma)
00638 {
00639   asection *sec = NULL;
00640   char sec_name[sizeof (".MMIX.sec.") + 20];
00641   struct mmo_find_sec_info info;
00642 
00643   info.addr = vma;
00644   info.sec = NULL;
00645 
00646   /* First see if there's a section that would match exactly.  */
00647   bfd_map_over_sections (abfd, mmo_find_sec_w_addr, &info);
00648 
00649   if (info.sec != NULL)
00650     return info.sec;
00651 
00652   /* If there's no such section, try and expand one of the existing ones,
00653      up to a limit.  Make sure we have .text and .data before we try that;
00654      create them corresponding to expected addresses and set flags to make
00655      them match the "loaded and with contents" expectation.  */
00656   if ((vma >> 56) == 0)
00657     {
00658       sec = bfd_make_section_old_way (abfd, MMO_TEXT_SECTION_NAME);
00659 
00660       if (sec == NULL)
00661        return NULL;
00662 
00663       if (! sec->user_set_vma)
00664        bfd_set_section_vma (abfd, sec, vma);
00665       if (! bfd_set_section_flags (abfd, sec,
00666                                bfd_get_section_flags (abfd, sec)
00667                                | SEC_CODE | SEC_LOAD | SEC_ALLOC))
00668        return NULL;
00669     }
00670   else if ((vma >> 56) == 0x20)
00671     {
00672       sec = bfd_make_section_old_way (abfd, MMO_DATA_SECTION_NAME);
00673 
00674       if (sec == NULL)
00675        return NULL;
00676 
00677       if (! sec->user_set_vma)
00678        bfd_set_section_vma (abfd, sec, vma);
00679       if (! bfd_set_section_flags (abfd, sec,
00680                                bfd_get_section_flags (abfd, sec)
00681                                | SEC_LOAD | SEC_ALLOC))
00682        return NULL;
00683     }
00684 
00685   bfd_map_over_sections (abfd, mmo_find_sec_w_addr_grow, &info);
00686 
00687   if (info.sec != NULL)
00688     return info.sec;
00689 
00690   /* If there's still no suitable section, make a new one.  */
00691   sprintf (sec_name, ".MMIX.sec.%d", abfd->tdata.mmo_data->sec_no++);
00692   sec = mmo_make_section (abfd, sec_name);
00693   if (! sec->user_set_vma)
00694     bfd_set_section_vma (abfd, sec, vma);
00695 
00696   if (! bfd_set_section_flags (abfd, sec,
00697                             bfd_get_section_flags (abfd, sec)
00698                             | SEC_LOAD | SEC_ALLOC))
00699     return NULL;
00700   return sec;
00701 }
00702 
00703 /* Xor in a 64-bit value VALUE at VMA.  */
00704 
00705 static INLINE void
00706 mmo_xore_64 (asection *sec, bfd_vma vma, bfd_vma value)
00707 {
00708   bfd_byte *loc = mmo_get_loc (sec, vma, 8);
00709   bfd_vma prev = bfd_get_64 (sec->owner, loc);
00710 
00711   value ^= prev;
00712   bfd_put_64 (sec->owner, value, loc);
00713 }
00714 
00715 /* Xor in a 32-bit value VALUE at VMA.  */
00716 
00717 static INLINE void
00718 mmo_xore_32 (asection *sec, bfd_vma vma, unsigned int value)
00719 {
00720   bfd_byte *loc = mmo_get_loc (sec, vma, 4);
00721   unsigned int prev = bfd_get_32 (sec->owner, loc);
00722 
00723   value ^= prev;
00724   bfd_put_32 (sec->owner, value, loc);
00725 }
00726 
00727 /* Xor in a 16-bit value VALUE at VMA.  */
00728 
00729 static INLINE void
00730 mmo_xore_16 (asection *sec, bfd_vma vma, unsigned int value)
00731 {
00732   bfd_byte *loc = mmo_get_loc (sec, vma, 2);
00733   unsigned int prev = bfd_get_16 (sec->owner, loc);
00734 
00735   value ^= prev;
00736   bfd_put_16 (sec->owner, value, loc);
00737 }
00738 
00739 /* Write a 32-bit word to output file, no lop_quote generated.  */
00740 
00741 static INLINE void
00742 mmo_write_tetra_raw (bfd *abfd, unsigned int value)
00743 {
00744   bfd_byte buf[4];
00745 
00746   bfd_put_32 (abfd, value, buf);
00747 
00748   if (bfd_bwrite (buf, 4, abfd) != 4)
00749     abfd->tdata.mmo_data->have_error = TRUE;
00750 }
00751 
00752 /* Write a 32-bit word to output file; lop_quote if necessary.  */
00753 
00754 static INLINE void
00755 mmo_write_tetra (bfd *abfd, unsigned int value)
00756 {
00757   if (((value >> 24) & 0xff) == LOP)
00758     mmo_write_tetra_raw (abfd, LOP_QUOTE_NEXT);
00759 
00760   mmo_write_tetra_raw (abfd, value);
00761 }
00762 
00763 /* Write a 64-bit word to output file, perhaps with lop_quoting.  */
00764 
00765 static INLINE void
00766 mmo_write_octa (bfd *abfd, bfd_vma value)
00767 {
00768   mmo_write_tetra (abfd, (unsigned int) (value >> 32));
00769   mmo_write_tetra (abfd, (unsigned int) value);
00770 }
00771 
00772 /* Write a 64-bit word to output file, without lop_quoting.  */
00773 
00774 static INLINE void
00775 mmo_write_octa_raw (bfd *abfd, bfd_vma value)
00776 {
00777   mmo_write_tetra_raw (abfd, (unsigned int) (value >> 32));
00778   mmo_write_tetra_raw (abfd, (unsigned int) value);
00779 }
00780 
00781 /* Write quoted contents.  Intended to be called multiple times in
00782    sequence, followed by a call to mmo_flush_chunk.  */
00783 
00784 static INLINE bfd_boolean
00785 mmo_write_chunk (bfd *abfd, const bfd_byte *loc, unsigned int len)
00786 {
00787   bfd_boolean retval = TRUE;
00788 
00789   /* Fill up a tetra from bytes remaining from a previous chunk.  */
00790   if (abfd->tdata.mmo_data->byte_no != 0)
00791     {
00792       while (abfd->tdata.mmo_data->byte_no < 4 && len != 0)
00793        {
00794          abfd->tdata.mmo_data->buf[abfd->tdata.mmo_data->byte_no++] = *loc++;
00795          len--;
00796        }
00797 
00798       if (abfd->tdata.mmo_data->byte_no == 4)
00799        {
00800          mmo_write_tetra (abfd,
00801                         bfd_get_32 (abfd, abfd->tdata.mmo_data->buf));
00802          abfd->tdata.mmo_data->byte_no = 0;
00803        }
00804     }
00805 
00806   while (len >= 4)
00807     {
00808       if (loc[0] == LOP)
00809        mmo_write_tetra_raw (abfd, LOP_QUOTE_NEXT);
00810 
00811       retval = (retval
00812               && ! abfd->tdata.mmo_data->have_error
00813               && 4 == bfd_bwrite (loc, 4, abfd));
00814 
00815       loc += 4;
00816       len -= 4;
00817     }
00818 
00819   if (len)
00820     {
00821       memcpy (abfd->tdata.mmo_data->buf, loc, len);
00822       abfd->tdata.mmo_data->byte_no = len;
00823     }
00824 
00825   if (! retval)
00826     abfd->tdata.mmo_data->have_error = TRUE;
00827   return retval;
00828 }
00829 
00830 /* Flush remaining bytes, from a previous mmo_write_chunk, zero-padded to
00831    4 bytes.  */
00832 
00833 static INLINE bfd_boolean
00834 mmo_flush_chunk (bfd *abfd)
00835 {
00836   if (abfd->tdata.mmo_data->byte_no != 0)
00837     {
00838       memset (abfd->tdata.mmo_data->buf + abfd->tdata.mmo_data->byte_no,
00839              0, 4 - abfd->tdata.mmo_data->byte_no);
00840       mmo_write_tetra (abfd,
00841                      bfd_get_32 (abfd, abfd->tdata.mmo_data->buf));
00842       abfd->tdata.mmo_data->byte_no = 0;
00843     }
00844 
00845   return ! abfd->tdata.mmo_data->have_error;
00846 }
00847 
00848 /* Same, but from a list.  */
00849 
00850 static INLINE bfd_boolean
00851 mmo_write_chunk_list (bfd *abfd, mmo_data_list_type *datap)
00852 {
00853   for (; datap != NULL; datap = datap->next)
00854     if (! mmo_write_chunk (abfd, datap->data, datap->size))
00855       return FALSE;
00856 
00857   return mmo_flush_chunk (abfd);
00858 }
00859 
00860 /* Write a lop_loc and some contents.  A caller needs to call
00861    mmo_flush_chunk after calling this function.  The location is only
00862    output if different than *LAST_VMAP, which is updated after this call.  */
00863 
00864 static bfd_boolean
00865 mmo_write_loc_chunk (bfd *abfd, bfd_vma vma, const bfd_byte *loc,
00866                    unsigned int len, bfd_vma *last_vmap)
00867 {
00868   /* Find an initial and trailing section of zero tetras; we don't need to
00869      write out zeros.  FIXME: When we do this, we should emit section size
00870      and address specifiers, else objcopy can't always perform an identity
00871      translation.  Only do this if we *don't* have left-over data from a
00872      previous write or the vma of this chunk is *not* the next address,
00873      because then data isn't tetrabyte-aligned and we're concatenating to
00874      that left-over data.  */
00875 
00876   if (abfd->tdata.mmo_data->byte_no == 0 || vma != *last_vmap)
00877     {
00878       while (len >= 4 && bfd_get_32 (abfd, loc) == 0)
00879        {
00880          vma += 4;
00881          len -= 4;
00882          loc += 4;
00883        }
00884 
00885       while (len >= 4 && bfd_get_32 (abfd, loc + len - 4) == 0)
00886        len -= 4;
00887     }
00888 
00889   /* Only write out the location if it's different than the one the caller
00890      (supposedly) previously handled, accounting for omitted leading zeros.  */
00891   if (vma != *last_vmap)
00892     {
00893       /* We might be in the middle of a sequence.  */
00894       mmo_flush_chunk (abfd);
00895 
00896       /* We always write the location as 64 bits; no use saving bytes
00897          here.  */
00898       mmo_write_tetra_raw (abfd, (LOP << 24) | (LOP_LOC << 16) | 2);
00899       mmo_write_octa_raw (abfd, vma);
00900     }
00901 
00902   /* Update to reflect end of this chunk, with trailing zeros omitted.  */
00903   *last_vmap = vma + len;
00904 
00905   return (! abfd->tdata.mmo_data->have_error
00906          && mmo_write_chunk (abfd, loc, len));
00907 }
00908 
00909 /* Same, but from a list.  */
00910 
00911 static INLINE bfd_boolean
00912 mmo_write_loc_chunk_list (bfd *abfd, mmo_data_list_type *datap)
00913 {
00914   /* Get an address different than the address of the first chunk.  */
00915   bfd_vma last_vma = datap ? datap->where - 1 : 0;
00916 
00917   for (; datap != NULL; datap = datap->next)
00918     if (! mmo_write_loc_chunk (abfd, datap->where, datap->data, datap->size,
00919                             &last_vma))
00920       return FALSE;
00921 
00922   return mmo_flush_chunk (abfd);
00923 }
00924 
00925 /* Make a .MMIX.spec_data.N section.  */
00926 
00927 static asection *
00928 mmo_get_generic_spec_data_section (bfd *abfd, int spec_data_number)
00929 {
00930   asection *sec;
00931   char secname[sizeof (MMIX_OTHER_SPEC_SECTION_PREFIX) + 20]
00932     = MMIX_OTHER_SPEC_SECTION_PREFIX;
00933 
00934   sprintf (secname + strlen (MMIX_OTHER_SPEC_SECTION_PREFIX),
00935           "%d", spec_data_number);
00936 
00937   sec = mmo_make_section (abfd, secname);
00938 
00939   return sec;
00940 }
00941 
00942 /* Make a special section for SPEC_DATA_NUMBER.  If it is the one we use
00943    ourselves, parse some of its data to get at the section name.  */
00944 
00945 static asection *
00946 mmo_get_spec_section (bfd *abfd, int spec_data_number)
00947 {
00948   char *secname;
00949   asection *sec;
00950   bfd_byte buf[4];
00951   unsigned int secname_length;
00952   unsigned int i;
00953   bfd_vma section_length;
00954   bfd_vma section_vma;
00955   mmo_data_list_type *loc;
00956   flagword flags;
00957   long orig_pos;
00958 
00959   /* If this isn't the "special" special data, then make a placeholder
00960      section.  */
00961   if (spec_data_number != SPEC_DATA_SECTION)
00962     return mmo_get_generic_spec_data_section (abfd, spec_data_number);
00963 
00964   /* Seek back to this position if there was a format error.  */
00965   orig_pos = bfd_tell (abfd);
00966 
00967   /* Read the length (in 32-bit words).  */
00968   if (bfd_bread (buf, 4, abfd) != 4)
00969     goto format_error;
00970 
00971   if (buf[0] == LOP)
00972     {
00973       if (buf[1] != LOP_QUOTE)
00974        goto format_error;
00975 
00976       if (bfd_bread (buf, 4, abfd) != 4)
00977        goto format_error;
00978     }
00979 
00980   /* We don't care to keep the name length accurate.  It's
00981      zero-terminated.  */
00982   secname_length = bfd_get_32 (abfd, buf) * 4;
00983 
00984   /* Check section name length for sanity.  */
00985   if (secname_length > MAX_SECTION_NAME_SIZE)
00986     goto format_error;
00987 
00988   /* This should be free'd regardless if a section is created.  */
00989   secname = bfd_malloc (secname_length + 1);
00990   secname[secname_length] = 0;
00991 
00992   for (i = 0; i < secname_length / 4; i++)
00993     {
00994       if (bfd_bread (secname + i * 4, 4, abfd) != 4)
00995        goto format_error_free;
00996 
00997       if (secname[i * 4] == (char) LOP)
00998        {
00999          /* A bit of overkill, but we handle char 0x98 in a section name,
01000             and recognize misparsing.  */
01001          if (secname[i * 4 + 1] != LOP_QUOTE
01002              || bfd_bread (secname + i * 4, 4, abfd) != 4)
01003            /* Whoops.  We thought this was a name, and now we found a
01004               non-lop_quote lopcode before we parsed the whole length of
01005               the name.  Signal end-of-file in the same manner.  */
01006              goto format_error_free;
01007        }
01008     }
01009 
01010   /* Get the section flags.  */
01011   if (bfd_bread (buf, 4, abfd) != 4
01012       || (buf[0] == LOP
01013          && (buf[1] != LOP_QUOTE || bfd_bread (buf, 4, abfd) != 4)))
01014     goto format_error_free;
01015 
01016   flags = bfd_get_32 (abfd, buf);
01017 
01018   /* Get the section length.  */
01019   if (bfd_bread (buf, 4, abfd) != 4
01020       || (buf[0] == LOP
01021          && (buf[1] != LOP_QUOTE || bfd_bread (buf, 4, abfd) != 4)))
01022     goto format_error_free;
01023 
01024   section_length = (bfd_vma) bfd_get_32 (abfd, buf) << 32;
01025 
01026   /* That's the first, high-part.  Now get the low part.  */
01027 
01028   if (bfd_bread (buf, 4, abfd) != 4
01029       || (buf[0] == LOP
01030          && (buf[1] != LOP_QUOTE || bfd_bread (buf, 4, abfd) != 4)))
01031     goto format_error_free;
01032 
01033   section_length |= (bfd_vma) bfd_get_32 (abfd, buf);
01034 
01035   /* Check the section length for sanity.  */
01036   if (section_length > MAX_ARTIFICIAL_SECTION_SIZE)
01037     goto format_error_free;
01038 
01039   /* Get the section VMA.  */
01040   if (bfd_bread (buf, 4, abfd) != 4
01041       || (buf[0] == LOP
01042          && (buf[1] != LOP_QUOTE || bfd_bread (buf, 4, abfd) != 4)))
01043     goto format_error_free;
01044 
01045   section_vma = (bfd_vma) bfd_get_32 (abfd, buf) << 32;
01046 
01047   /* That's the first, high-part.  Now get the low part.  */
01048   if (bfd_bread (buf, 4, abfd) != 4
01049       || (buf[0] == LOP
01050          && (buf[1] != LOP_QUOTE || bfd_bread (buf, 4, abfd) != 4)))
01051     goto format_error_free;
01052 
01053   section_vma |= (bfd_vma) bfd_get_32 (abfd, buf);
01054 
01055   sec = mmo_make_section (abfd, secname);
01056   free (secname);
01057   if (sec == NULL)
01058     goto format_error;
01059 
01060   /* We allocate a buffer here for the advertised size, with head room for
01061      tetrabyte alignment.  */
01062   loc = bfd_zmalloc (section_length + 3
01063                    + sizeof (struct mmo_data_list_struct));
01064   if (loc == NULL)
01065     goto format_error;
01066 
01067   /* Use a TETRA-rounded size for the allocated buffer; we set the
01068      "visible" section size below.  */
01069   loc->size = (section_length + 3) & ~3;
01070 
01071   /* Add in the section flags we found to those bfd entered during this
01072      process and set the contents.  */
01073   if (! bfd_set_section_flags (abfd, sec,
01074                             bfd_sec_flags_from_mmo_flags (flags)
01075                             | bfd_get_section_flags (abfd, sec)
01076                             | (section_length != 0 ? SEC_HAS_CONTENTS : 0))
01077       || ! bfd_set_section_size (abfd, sec, sec->size + section_length)
01078       /* Set VMA only for the first occurrence.  */
01079       || (! sec->user_set_vma
01080          && ! bfd_set_section_vma  (abfd, sec, section_vma)))
01081     {
01082       /* If we get an error for any of the calls above, signal more than
01083         just a format error for the spec section.  */
01084       return NULL;
01085     }
01086 
01087   loc->next = NULL;
01088   if (mmo_section_data (sec)->tail != NULL)
01089     mmo_section_data (sec)->tail->next = loc;
01090   else
01091     mmo_section_data (sec)->head = loc;
01092   mmo_section_data (sec)->tail = loc;
01093   loc->where = section_vma;
01094 
01095   return sec;
01096 
01097  format_error_free:
01098   free (secname);
01099  format_error:
01100   if (bfd_seek (abfd, orig_pos, SEEK_SET) != 0)
01101     return NULL;
01102 
01103   return mmo_get_generic_spec_data_section (abfd, spec_data_number);
01104 }
01105 
01106 /* Read a byte, but read from file in multiples of 32-bit words.  */
01107 
01108 static bfd_byte
01109 mmo_get_byte (bfd *abfd)
01110 {
01111   bfd_byte retval;
01112 
01113   if (abfd->tdata.mmo_data->byte_no == 0)
01114     {
01115       if (! abfd->tdata.mmo_data->have_error
01116          && bfd_bread (abfd->tdata.mmo_data->buf, 4, abfd) != 4)
01117        {
01118          abfd->tdata.mmo_data->have_error = TRUE;
01119 
01120          /* A value somewhat safe against tripping on some inconsistency
01121             when mopping up after this error.  */
01122          return 128;
01123        }
01124     }
01125 
01126   retval = abfd->tdata.mmo_data->buf[abfd->tdata.mmo_data->byte_no];
01127   abfd->tdata.mmo_data->byte_no = (abfd->tdata.mmo_data->byte_no + 1) % 4;
01128 
01129   return retval;
01130 }
01131 
01132 /* Write a byte, in multiples of 32-bit words.  */
01133 
01134 static void
01135 mmo_write_byte (bfd *abfd, bfd_byte value)
01136 {
01137   abfd->tdata.mmo_data->buf[(abfd->tdata.mmo_data->byte_no++ % 4)] = value;
01138   if ((abfd->tdata.mmo_data->byte_no % 4) == 0)
01139     {
01140       if (! abfd->tdata.mmo_data->have_error
01141          && bfd_bwrite (abfd->tdata.mmo_data->buf, 4, abfd) != 4)
01142        abfd->tdata.mmo_data->have_error = TRUE;
01143     }
01144 }
01145 
01146 /* Create a symbol.  */
01147 
01148 static bfd_boolean
01149 mmo_create_symbol (bfd *abfd, const char *symname, bfd_vma addr, enum
01150                  mmo_sym_type sym_type, unsigned int serno)
01151 {
01152   struct mmo_symbol *n;
01153 
01154   n = (struct mmo_symbol *) bfd_alloc (abfd, sizeof (struct mmo_symbol));
01155   if (n == NULL)
01156     return FALSE;
01157 
01158   n->name = bfd_alloc (abfd, strlen (symname) + 1);
01159   if (n->name == NULL)
01160     return FALSE;
01161 
01162   strcpy (n->name, symname);
01163 
01164   n->value = addr;
01165   n->sym_type = sym_type;
01166   n->serno = serno;
01167 
01168   if (abfd->tdata.mmo_data->symbols == NULL)
01169     abfd->tdata.mmo_data->symbols = n;
01170   else
01171     abfd->tdata.mmo_data->symtail->next = n;
01172   abfd->tdata.mmo_data->symtail = n;
01173   n->next = NULL;
01174 
01175   ++abfd->symcount;
01176 
01177   /* Check that :Main equals the last octa of the .MMIX.reg_contents
01178      section, as it's the one place we're sure to pass when reading a mmo
01179      object.  For written objects, we do it while setting the symbol
01180      table.  */
01181   if (strcmp (symname, MMIX_START_SYMBOL_NAME) == 0
01182       && bfd_get_start_address (abfd) != addr)
01183     {
01184       (*_bfd_error_handler)
01185        (_("%s: invalid mmo file: initialization value for $255 is not `Main'\n"),
01186         bfd_get_filename (abfd));
01187       bfd_set_error (bfd_error_bad_value);
01188       return FALSE;
01189     }
01190 
01191   return TRUE;
01192 }
01193 
01194 /* Read in symbols.  */
01195 
01196 static bfd_boolean
01197 mmo_get_symbols (bfd *abfd)
01198 {
01199 /*
01200 INODE
01201 Symbol-table, mmo section mapping, File layout, mmo
01202 SUBSECTION
01203        Symbol table format
01204 
01205        From mmixal.w (or really, the generated mmixal.tex) in
01206        @url{http://www-cs-faculty.stanford.edu/~knuth/programs/mmix.tar.gz}):
01207        ``Symbols are stored and retrieved by means of a @samp{ternary
01208        search trie}, following ideas of Bentley and Sedgewick. (See
01209        ACM--SIAM Symp.@: on Discrete Algorithms @samp{8} (1997), 360--369;
01210        R.@:Sedgewick, @samp{Algorithms in C} (Reading, Mass.@:
01211        Addison--Wesley, 1998), @samp{15.4}.)  Each trie node stores a
01212        character, and there are branches to subtries for the cases where
01213        a given character is less than, equal to, or greater than the
01214        character in the trie.  There also is a pointer to a symbol table
01215        entry if a symbol ends at the current node.''
01216 
01217        So it's a tree encoded as a stream of bytes.  The stream of bytes
01218        acts on a single virtual global symbol, adding and removing
01219        characters and signalling complete symbol points.  Here, we read
01220        the stream and create symbols at the completion points.
01221 
01222        First, there's a control byte <<m>>.  If any of the listed bits
01223        in <<m>> is nonzero, we execute what stands at the right, in
01224        the listed order:
01225 
01226 | (MMO3_LEFT)
01227 | 0x40 - Traverse left trie.
01228 |        (Read a new command byte and recurse.)
01229 |
01230 | (MMO3_SYMBITS)
01231 | 0x2f - Read the next byte as a character and store it in the
01232 |        current character position; increment character position.
01233 |        Test the bits of <<m>>:
01234 |
01235 |        (MMO3_WCHAR)
01236 |        0x80 - The character is 16-bit (so read another byte,
01237 |               merge into current character.
01238 |
01239 |        (MMO3_TYPEBITS)
01240 |        0xf  - We have a complete symbol; parse the type, value
01241 |               and serial number and do what should be done
01242 |               with a symbol.  The type and length information
01243 |               is in j = (m & 0xf).
01244 |
01245 |               (MMO3_REGQUAL_BITS)
01246 |              j == 0xf: A register variable.  The following
01247 |                         byte tells which register.
01248 |               j <= 8:   An absolute symbol.  Read j bytes as the
01249 |                         big-endian number the symbol equals.
01250 |                         A j = 2 with two zero bytes denotes an
01251 |                         unknown symbol.
01252 |               j > 8:    As with j <= 8, but add (0x20 << 56)
01253 |                         to the value in the following j - 8
01254 |                         bytes.
01255 |
01256 |               Then comes the serial number, as a variant of
01257 |               uleb128, but better named ubeb128:
01258 |               Read bytes and shift the previous value left 7
01259 |               (multiply by 128).  Add in the new byte, repeat
01260 |               until a byte has bit 7 set.  The serial number
01261 |               is the computed value minus 128.
01262 |
01263 |        (MMO3_MIDDLE)
01264 |        0x20 - Traverse middle trie.  (Read a new command byte
01265 |               and recurse.)  Decrement character position.
01266 |
01267 | (MMO3_RIGHT)
01268 | 0x10 - Traverse right trie.  (Read a new command byte and
01269 |        recurse.)
01270 
01271        Let's look again at the <<lop_stab>> for the trivial file
01272        (@pxref{File layout}).
01273 
01274 | 0x980b0000 - lop_stab for ":Main" = 0, serial 1.
01275 | 0x203a4040
01276 | 0x10404020
01277 | 0x4d206120
01278 | 0x69016e00
01279 | 0x81000000
01280 
01281        This forms the trivial trie (note that the path between ``:'' and
01282        ``M'' is redundant):
01283 
01284 | 203a    ":"
01285 | 40       /
01286 | 40      /
01287 | 10      \
01288 | 40      /
01289 | 40     /
01290 | 204d  "M"
01291 | 2061  "a"
01292 | 2069  "i"
01293 | 016e  "n" is the last character in a full symbol, and
01294 |       with a value represented in one byte.
01295 | 00    The value is 0.
01296 | 81    The serial number is 1.  */
01297 
01298   bfd_byte m = mmo_get_byte (abfd);
01299 
01300   /* Check first if we have a bad hair day.  */
01301   if (abfd->tdata.mmo_data->have_error)
01302     return FALSE;
01303 
01304   if (m & MMO3_LEFT)
01305     /* Traverse left trie. */
01306     mmo_get_symbols (abfd);
01307 
01308   if (m & MMO3_SYMBITS)
01309     {
01310       bfd_byte c = mmo_get_byte (abfd);
01311       bfd_byte j = m & MMO3_TYPEBITS;
01312       bfd_vma addr = 0;
01313       enum mmo_sym_type sym_type;
01314       unsigned int serno = 0;
01315       bfd_byte k;
01316 
01317       if (m & MMO3_WCHAR)
01318        {
01319          bfd_byte c2 = mmo_get_byte (abfd);
01320 
01321          /* A two-byte character.  We can't grok this, but neither can
01322             mmotype, for other cases than the second byte being zero.  */
01323 
01324          if (c != 0)
01325            {
01326              abfd->tdata.mmo_data->lop_stab_symbol
01327               [abfd->tdata.mmo_data->symbol_position] = 0;
01328 
01329              (*_bfd_error_handler)
01330               (_("%s: unsupported wide character sequence"
01331                  " 0x%02X 0x%02X after symbol name starting with `%s'\n"),
01332                bfd_get_filename (abfd), c, c2,
01333                abfd->tdata.mmo_data->lop_stab_symbol);
01334              bfd_set_error (bfd_error_bad_value);
01335              abfd->tdata.mmo_data->have_error = TRUE;
01336              return FALSE;
01337            }
01338          else
01339            c = c2;
01340        }
01341 
01342       abfd->tdata.mmo_data->lop_stab_symbol[abfd->tdata.mmo_data->symbol_position++] = c;
01343       abfd->tdata.mmo_data->lop_stab_symbol[abfd->tdata.mmo_data->symbol_position] = 0;
01344 
01345       if (j & MMO3_REGQUAL_BITS)
01346        {
01347          if (j == MMO3_REGQUAL_BITS)
01348            {
01349              sym_type = mmo_reg_sym;
01350              addr = mmo_get_byte (abfd);
01351            }
01352          else if (j <= 8)
01353            {
01354              unsigned int i;
01355 
01356              for (i = 0; i < j; i++)
01357               addr = (addr << 8) + mmo_get_byte (abfd);
01358 
01359              if (addr == 0 && j == MMO3_UNDEF)
01360               sym_type = mmo_undef_sym;
01361              else
01362               sym_type = mmo_abs_sym;
01363            }
01364          else
01365            {
01366              unsigned int i;
01367 
01368              for (i = MMO3_DATA; i < j; i++)
01369               addr = (addr << 8) + mmo_get_byte (abfd);
01370 
01371              addr += (bfd_vma) 0x20 << 56;
01372              sym_type = mmo_data_sym;
01373            }
01374 
01375          /* Get the serial number.  */
01376          do
01377            {
01378              k = mmo_get_byte (abfd);
01379              serno = (serno << 7) + k;
01380            }
01381          while (k < 128);
01382          serno -= 128;
01383 
01384          /* Got it.  Now enter it.  Skip a leading ":".  */
01385          if (! abfd->tdata.mmo_data->have_error
01386              && ! mmo_create_symbol (abfd,
01387                                   abfd->tdata.mmo_data->lop_stab_symbol
01388                                   + 1,
01389                                   addr, sym_type, serno))
01390            abfd->tdata.mmo_data->have_error = TRUE;
01391        }
01392 
01393       if (m & MMO3_MIDDLE)
01394        /* Traverse middle trie. */
01395        mmo_get_symbols (abfd);
01396 
01397       abfd->tdata.mmo_data->symbol_position--;
01398     }
01399 
01400   if (m & MMO3_RIGHT)
01401     /* Traverse right trie.  */
01402     mmo_get_symbols (abfd);
01403 
01404   return ! abfd->tdata.mmo_data->have_error;
01405 }
01406 
01407 /* Get the location of memory area [VMA..VMA + SIZE - 1], which we think
01408    is in section SEC.  Adjust and reallocate zero-initialized contents.
01409    If there's new contents, allocate to the next multiple of
01410    MMO_SEC_CONTENTS_CHUNK_SIZE.  */
01411 
01412 static INLINE bfd_byte *
01413 mmo_get_loc (asection *sec, bfd_vma vma, int size)
01414 {
01415   bfd_size_type allocated_size;
01416   struct mmo_section_data_struct *sdatap = mmo_section_data (sec);
01417   struct mmo_data_list_struct *datap = sdatap->head;
01418   struct mmo_data_list_struct *entry;
01419 
01420   /* First search the list to see if we have the requested chunk in one
01421      piece, or perhaps if we have a suitable chunk with room to fit.  */
01422   for (; datap != NULL; datap = datap->next)
01423     {
01424       if (datap->where <= vma
01425          && datap->where + datap->size >= vma + size)
01426        return datap->data + vma - datap->where;
01427       else if (datap->where <= vma
01428               && datap->where + datap->allocated_size >= vma + size
01429               /* Only munch on the "allocated size" if it does not
01430                 overlap the next chunk.  */
01431               && (datap->next == NULL || datap->next->where >= vma + size))
01432        {
01433          /* There was room allocated, but the size wasn't set to include
01434             it.  Do that now.  */
01435          datap->size += (vma + size) - (datap->where + datap->size);
01436 
01437          /* Update the section size.  This happens only if we update the
01438             32-bit-aligned chunk size.  Callers that have
01439             non-32-bit-aligned sections should do all allocation and
01440             size-setting by themselves or at least set the section size
01441             after the last allocating call to this function.  */
01442          if (vma + size > sec->vma + sec->size)
01443            sec->size += (vma + size) - (sec->vma + sec->size);
01444 
01445          return datap->data + vma - datap->where;
01446        }
01447     }
01448 
01449   /* Not found; allocate a new block.  First check in case we get a
01450      request for a size split up over several blocks; we'll have to return
01451      NULL for those cases, requesting the caller to split up the request.
01452      Requests with an address aligned on MMO_SEC_CONTENTS_CHUNK_SIZE bytes and
01453      for no more than MMO_SEC_CONTENTS_CHUNK_SIZE will always get resolved.  */
01454 
01455   for (datap = sdatap->head; datap != NULL; datap = datap->next)
01456     if ((datap->where <= vma && datap->where + datap->size > vma)
01457        || (datap->where < vma + size
01458            && datap->where + datap->size >= vma + size))
01459       return NULL;
01460 
01461   allocated_size
01462     = (size + MMO_SEC_CONTENTS_CHUNK_SIZE - 1) & ~(MMO_SEC_CONTENTS_CHUNK_SIZE - 1);
01463   entry = (mmo_data_list_type *)
01464     bfd_zalloc (sec->owner, sizeof (mmo_data_list_type) + allocated_size);
01465   if (entry == NULL)
01466     return NULL;
01467   entry->where = vma;
01468   entry->size = size;
01469   entry->allocated_size = allocated_size;
01470 
01471   datap = sdatap->head;
01472 
01473   /* Sort the records by address.  Optimize for the common case of adding
01474      a record to the end of the list.  */
01475   if (sdatap->tail != NULL && entry->where >= sdatap->tail->where)
01476     {
01477       sdatap->tail->next = entry;
01478       entry->next = NULL;
01479       sdatap->tail = entry;
01480     }
01481   else
01482     {
01483       mmo_data_list_type **look;
01484       for (look = &sdatap->head;
01485           *look != NULL && (*look)->where < entry->where;
01486           look = &(*look)->next)
01487        ;
01488       entry->next = *look;
01489       *look = entry;
01490       if (entry->next == NULL)
01491        {
01492          sdatap->tail = entry;
01493 
01494          /* We get here for the first time (at other times too) for this
01495             section.  Say we have contents.  */
01496          if (! bfd_set_section_flags (sec->owner, sec,
01497                                    bfd_get_section_flags (sec->owner, sec)
01498                                    | SEC_HAS_CONTENTS))
01499            return NULL;
01500        }
01501     }
01502 
01503   /* Update the section size.  This happens only when we add contents and
01504      re-size as we go.  The section size will then be aligned to 32 bits.  */
01505   if (vma + size > sec->vma + sec->size)
01506     sec->size += (vma + size) - (sec->vma + sec->size);
01507   return entry->data;
01508 }
01509 
01510 /* Set sizes once we've read in all sections.  */
01511 
01512 static void
01513 mmo_map_set_sizes (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
01514                  void *ignored ATTRIBUTE_UNUSED)
01515 {
01516   sec->lma = sec->vma;
01517 }
01518 
01519 /* Read the mmo file and turn it into sections.  */
01520 
01521 static bfd_boolean
01522 mmo_scan (bfd *abfd)
01523 {
01524   unsigned int i;
01525   unsigned int lineno = 1;
01526   bfd_boolean error = FALSE;
01527   bfd_vma vma = 0;
01528   asection *sec = bfd_make_section_old_way (abfd, MMO_TEXT_SECTION_NAME);
01529   asection *non_spec_sec = NULL;
01530   bfd_vma non_spec_vma = 0;
01531   char *current_filename = NULL;
01532   bfd_size_type nbytes_read = 0;
01533   /* Buffer with room to read a 64-bit value.  */
01534   bfd_byte buf[8];
01535   long stab_loc = -1;
01536   char *file_names[256];
01537 
01538   memset (file_names, 0, sizeof (file_names));
01539 
01540   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
01541     goto error_return;
01542 
01543   while ((nbytes_read = bfd_bread (buf, 4, abfd)) == 4)
01544     {
01545       if (buf[0] == LOP)
01546        {
01547          unsigned int y = bfd_get_8 (abfd, buf + 2);
01548          unsigned int z = bfd_get_8 (abfd, buf + 3);
01549 
01550          /* Change back to the original section for lopcodes other
01551             than LOP_QUOTE that comes after a LOP_SPEC.  */
01552          if ((buf[1] != LOP_QUOTE || y != 0 || z != 1)
01553              && non_spec_sec != NULL)
01554            {
01555              sec = non_spec_sec;
01556              vma = non_spec_vma;
01557              non_spec_sec = NULL;
01558            }
01559 
01560          switch (buf[1])
01561            {
01562            default:
01563              (*_bfd_error_handler)
01564               (_("%s: invalid mmo file: unsupported lopcode `%d'\n"),
01565                bfd_get_filename (abfd), buf[1]);
01566              bfd_set_error (bfd_error_bad_value);
01567              goto error_return;
01568 
01569            case LOP_QUOTE:
01570              /* Quote the next 32-bit word.  */
01571              if (y != 0 || z != 1)
01572               {
01573                 (*_bfd_error_handler)
01574                   (_("%s: invalid mmo file: expected YZ = 1 got YZ = %d for lop_quote\n"),
01575                    bfd_get_filename (abfd), y*256+z);
01576                 bfd_set_error (bfd_error_bad_value);
01577                 goto error_return;
01578               }
01579              if (bfd_bread (buf, 4, abfd) != 4)
01580               goto error_return;
01581 
01582              mmo_xore_32 (sec, vma, bfd_get_32 (abfd, buf));
01583              vma += 4;
01584              vma &= ~3;
01585              lineno++;
01586              break;
01587 
01588            case LOP_LOC:
01589              /* Set vma (and section).  */
01590              vma = (bfd_vma) y << 56;
01591              if (z == 1)
01592               {
01593                 /* Get a 32-bit value.  */
01594                 if (bfd_bread (buf, 4, abfd) != 4)
01595                   goto error_return;
01596 
01597                 vma += bfd_get_32 (abfd, buf);
01598               }
01599              else if (z == 2)
01600               {
01601                 /* Get a 64-bit value.  */
01602                 if (bfd_bread (buf, 8, abfd) != 8)
01603                   goto error_return;
01604 
01605                 vma += bfd_get_64 (abfd, buf);
01606               }
01607              else
01608               {
01609                 (*_bfd_error_handler)
01610                   (_("%s: invalid mmo file: expected z = 1 or z = 2, got z = %d for lop_loc\n"),
01611                    bfd_get_filename (abfd), z);
01612                 bfd_set_error (bfd_error_bad_value);
01613                 goto error_return;
01614               }
01615 
01616              sec = mmo_decide_section (abfd, vma);
01617              if (sec == NULL)
01618               goto error_return;
01619              break;
01620 
01621            case LOP_SKIP:
01622              /* Move forward within the same section.  */
01623              vma += y * 256 + z;
01624 
01625              sec = mmo_decide_section (abfd, vma);
01626              if (sec == NULL)
01627               goto error_return;
01628              break;
01629 
01630            case LOP_FIXO:
01631              /* A fixup: Store the current vma somewhere.  Position using
01632                same format as LOP_LOC.  */
01633              {
01634               bfd_vma p = (bfd_vma) y << 56;
01635               asection *fixosec;
01636 
01637               if (z == 1)
01638                 {
01639                   /* Get a 32-bit value.  */
01640                   if (bfd_bread (buf, 4, abfd) != 4)
01641                     goto error_return;
01642 
01643                   p += bfd_get_32 (abfd, buf);
01644                 }
01645               else if (z == 2)
01646                 {
01647                   /* Get a 64-bit value.  */
01648                   if (bfd_bread (buf, 8, abfd) != 8)
01649                     goto error_return;
01650 
01651                   p += bfd_get_64 (abfd, buf);
01652                 }
01653               else
01654                 {
01655                   (*_bfd_error_handler)
01656                     (_("%s: invalid mmo file: expected z = 1 or z = 2, got z = %d for lop_fixo\n"),
01657                      bfd_get_filename (abfd), z);
01658                   bfd_set_error (bfd_error_bad_value);
01659                   goto error_return;
01660                 }
01661 
01662               /* The section where we store this address might be a
01663                  different one than the current section.  */
01664               fixosec = mmo_decide_section (abfd, p);
01665               if (fixosec == NULL)
01666                 goto error_return;
01667               mmo_xore_64 (fixosec, p, vma);
01668              }
01669            break;
01670 
01671            case LOP_FIXR:
01672              /* A fixup: Store YZ of this lopcode into YZ at vma - 4 * yz.  */
01673              {
01674               unsigned int yz = (y * 256 + z);
01675               bfd_vma p = vma + 2 - 4 * yz;
01676               asection *fixrsec = mmo_decide_section (abfd, p);
01677               if (fixrsec == NULL)
01678                 goto error_return;
01679               mmo_xore_16 (fixrsec, p, yz);
01680              }
01681            break;
01682 
01683            case LOP_FIXRX:
01684              /* A fixup, similar to lop_fixr, but taking larger numbers
01685                and can change branches into the opposite direction
01686                (gasp!).  */
01687              {
01688               bfd_vma delta;
01689               bfd_vma p;
01690               asection *fixrsec;
01691 
01692               if (y != 0)
01693                 {
01694                   (*_bfd_error_handler)
01695                     (_("%s: invalid mmo file: expected y = 0, got y = %d for lop_fixrx\n"),
01696                      bfd_get_filename (abfd), y);
01697                   bfd_set_error (bfd_error_bad_value);
01698                   goto error_return;
01699                 }
01700 
01701               if (z != 16 && z != 24)
01702                 {
01703                   (*_bfd_error_handler)
01704                     (_("%s: invalid mmo file: expected z = 16 or z = 24, got z = %d for lop_fixrx\n"),
01705                      bfd_get_filename (abfd), z);
01706                   bfd_set_error (bfd_error_bad_value);
01707                   goto error_return;
01708                 }
01709 
01710               /* Get the next 32-bit value.  */
01711               if (bfd_bread (buf, 4, abfd) != 4)
01712                 goto error_return;
01713 
01714               delta = bfd_get_32 (abfd, buf);
01715 
01716               /* Do an, ehm, involved calculation for the location of
01717                  the fixup.  See mmixal documentation for a verbose
01718                  explanation.  We follow it verbosely here for the
01719                  readers delight.  */
01720               if (buf[0] == 0)
01721                 p = vma - 4 * delta;
01722               else if (buf[0] == 1)
01723                 p = vma - 4 * ((delta & 0xffffff) - (1 << z));
01724               else
01725                 {
01726                   (*_bfd_error_handler)
01727                     (_("%s: invalid mmo file: leading byte of operand word must be 0 or 1, got %d for lop_fixrx\n"),
01728                      bfd_get_filename (abfd), buf[0]);
01729                   bfd_set_error (bfd_error_bad_value);
01730                   goto error_return;
01731                 }
01732 
01733               fixrsec = mmo_decide_section (abfd, vma);
01734               if (fixrsec == NULL)
01735                 goto error_return;
01736               mmo_xore_32 (fixrsec, p, delta);
01737              }
01738            break;
01739 
01740            case LOP_FILE:
01741              /* Set current file and perhaps the file name.  Reset line
01742                number.  */
01743              if (z != 0)
01744               {
01745                 char *fname = bfd_malloc (z * 4 + 1);
01746 
01747                 if (fname == NULL)
01748                   {
01749                     (*_bfd_error_handler)
01750                      (_("%s: cannot allocate file name for file number %d, %d bytes\n"),
01751                       bfd_get_filename (abfd), y, z * 4 + 1);
01752                     bfd_set_error (bfd_error_system_call);
01753                     goto error_return;
01754                   }
01755 
01756                 fname[z * 4] = 0;
01757 
01758                 for (i = 0; i < z; i++)
01759                   {
01760                     if (bfd_bread (fname + i * 4, 4, abfd) != 4)
01761                      {
01762                        free (fname);
01763                        goto error_return;
01764                      }
01765                   }
01766 
01767                 if (file_names[y] != NULL)
01768                   {
01769                     (*_bfd_error_handler)
01770                      (_("%s: invalid mmo file: file number %d `%s',"
01771                         " was already entered as `%s'\n"),
01772                       bfd_get_filename (abfd), y, fname, file_names[y]);
01773                     bfd_set_error (bfd_error_bad_value);
01774                     goto error_return;
01775                   }
01776 
01777                 file_names[y] = fname;
01778               }
01779 
01780              if (file_names[y] == NULL)
01781               {
01782                 (*_bfd_error_handler)
01783                   (_("%s: invalid mmo file: file name for number %d"
01784                      " was not specified before use\n"),
01785                    bfd_get_filename (abfd), y);
01786                 bfd_set_error (bfd_error_bad_value);
01787                 goto error_return;
01788               }
01789 
01790              current_filename = file_names[y];
01791              lineno = 0;
01792              break;
01793 
01794            case LOP_LINE:
01795              /* Set line number.  */
01796              lineno = y * 256 + z;
01797              /* FIXME: Create a sequence of mmo-specific line number
01798                entries for each section, then translate into canonical
01799                format.  */
01800              break;
01801 
01802            case LOP_SPEC:
01803              /* Special data follows until the next non-lop_quote
01804                lopcode.  */
01805              non_spec_sec = sec;
01806              non_spec_vma = vma;
01807              sec = mmo_get_spec_section (abfd, y * 256 + z);
01808              if (sec == NULL)
01809               goto error_return;
01810 
01811              vma = sec->vma;
01812              break;
01813 
01814            case LOP_PRE:
01815              {
01816               /* We ignore header information, except we read in the
01817                  creation time from the first 32-bit word with the time
01818                  in seconds since era.  */
01819               if (z >= 1
01820                   && bfd_bread (abfd->tdata.mmo_data->created, 4,
01821                              abfd) != 4)
01822                 goto error_return;
01823 
01824               for (i = 1; i < z; i++)
01825                 if (bfd_bread (buf, 4, abfd) != 4)
01826                   goto error_return;
01827              }
01828              break;
01829 
01830            case LOP_POST:
01831              /* This tells of the contents of registers $Z..$255 at
01832                startup.  We make a section out of it, with VMA = Z * 8,
01833                but only if Z != 255 or the contents is non-zero.  */
01834              {
01835               asection *rsec;
01836               bfd_byte *loc;
01837               bfd_vma first_octa;
01838               bfd_vma startaddr_octa;
01839 
01840               /* Read first octaword outside loop to simplify logic when
01841                  excluding the Z == 255, octa == 0 case.  */
01842               if (bfd_bread (buf, 8, abfd) != 8)
01843                 goto error_return;
01844 
01845               first_octa = bfd_get_64 (abfd, buf);
01846 
01847               /* Don't emit contents for the trivial case which is
01848                  always present; $255 pointing to Main.  */
01849               if (z != 255)
01850                 {
01851                   rsec
01852                     = bfd_make_section_old_way (abfd,
01853                                             MMIX_REG_CONTENTS_SECTION_NAME);
01854                   rsec->flags |= SEC_LINKER_CREATED;
01855                   rsec->vma = z * 8;
01856                   loc = mmo_get_loc (rsec, z * 8, (255 - z) * 8);
01857                   bfd_put_64 (abfd, first_octa, loc);
01858 
01859                   for (i = z + 1; i < 255; i++)
01860                     {
01861                      if (bfd_bread (loc + (i - z) * 8, 8, abfd) != 8)
01862                        goto error_return;
01863                     }
01864 
01865                   /* Read out the last octabyte, and use it to set the
01866                      start address.  */
01867                   if (bfd_bread (buf, 8, abfd) != 8)
01868                     goto error_return;
01869 
01870                   startaddr_octa = bfd_get_64 (abfd, buf);
01871                 }
01872               else
01873                 startaddr_octa = first_octa;
01874 
01875               if (! bfd_set_start_address (abfd, startaddr_octa))
01876                 {
01877                   /* Currently this can't fail, but this should handle
01878                      future failures.  */
01879                   bfd_set_error (bfd_error_bad_value);
01880                   goto error_return;
01881                 }
01882              }
01883              break;
01884 
01885            case LOP_STAB:
01886              /* We read in the symbols now, not later.  */
01887              if (y != 0 || z != 0)
01888               {
01889                 (*_bfd_error_handler)
01890                   (_("%s: invalid mmo file: fields y and z of lop_stab"
01891                      " non-zero, y: %d, z: %d\n"),
01892                    bfd_get_filename (abfd), y, z);
01893                 bfd_set_error (bfd_error_bad_value);
01894                 goto error_return;
01895               }
01896 
01897              /* Save the location, so we can check that YZ in the LOP_END
01898                is correct.  */
01899              stab_loc = bfd_tell (abfd);
01900 
01901              /* It's not said that an MMO can be without symbols (though
01902                mmixal will refuse to assemble files without Main), but
01903                it seems it would still be a valid mmo-file, so allow it.
01904                We detect the absence of a symbol area in that the upper
01905                limit is computed (from the lop_end YZ field) as 0.
01906                Don't call mmo_get_symbols; it can only detect the end of
01907                a valid symbol trie, not the absence of one.  */
01908              if (abfd->tdata.mmo_data->max_symbol_length != 0
01909                 && ! mmo_get_symbols (abfd))
01910               goto error_return;
01911              break;
01912 
01913            case LOP_END:
01914              {
01915               /* This must be the last 32-bit word in an mmo file.
01916                  Let's find out.  */
01917               struct stat statbuf;
01918               file_ptr curpos = bfd_tell (abfd);
01919 
01920               if (bfd_stat (abfd, &statbuf) < 0)
01921                 goto error_return;
01922 
01923               if (statbuf.st_size != curpos)
01924                 {
01925                   (*_bfd_error_handler)
01926                     (_("%s: invalid mmo file: lop_end not last item in"
01927                       " file\n"),
01928                      bfd_get_filename (abfd));
01929                   bfd_set_error (bfd_error_bad_value);
01930                   goto error_return;
01931                 }
01932 
01933               /* Check that the YZ field is right.  Subtract the size of
01934                  this LOP_END in the calculation; YZ does not include
01935                  it.  */
01936               if ((long) (y * 256 + z) * 4 != (curpos - stab_loc) - 4)
01937                 {
01938                   (*_bfd_error_handler)
01939                     (_("%s: invalid mmo file: YZ of lop_end (%ld)"
01940                       " not equal to the number of tetras to the preceding"
01941                       " lop_stab (%ld)\n"),
01942                      bfd_get_filename (abfd), (long) (y * 256 + z),
01943                      (curpos - stab_loc - 4)/4);
01944                   bfd_set_error (bfd_error_bad_value);
01945                   goto error_return;
01946                 }
01947 
01948               bfd_map_over_sections (abfd, mmo_map_set_sizes, NULL);
01949               goto done;
01950              }
01951            }
01952        }
01953       else
01954        {
01955          /* This wasn't a lopcode, so store it in the current section.  */
01956          mmo_xore_32 (sec, vma & ~3, bfd_get_32 (abfd, buf));
01957          vma += 4;
01958          vma &= ~3;
01959          lineno++;
01960        }
01961     }
01962 
01963   /* We know this file is a multiple of four bytes (checked in
01964      mmo_object_p), so if we got something other than 0, this was a bad
01965      file (although it's more likely we'll get 0 in that case too).
01966      If we got end-of-file, then there was no lop_stab, so the file has
01967      invalid format.  */
01968 
01969   if (nbytes_read != 0)
01970     bfd_set_error (bfd_error_system_call);
01971   else
01972     bfd_set_error (bfd_error_bad_value);
01973 
01974  error_return:
01975   error = TRUE;
01976  done:
01977   /* Mark the .text and .data section with their normal attribute if they
01978      contain anything.  This is not redundant wrt. mmo_decide_section,
01979      since that code might never execute, and conversely the alloc+code
01980      section flags must be set then.  */
01981   sec = bfd_get_section_by_name (abfd, MMO_TEXT_SECTION_NAME);
01982   if (sec != NULL
01983       && (bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS)
01984       && ! bfd_set_section_flags (abfd, sec,
01985                               bfd_get_section_flags (abfd, sec)
01986                               | SEC_ALLOC | SEC_LOAD | SEC_CODE))
01987     error = TRUE;
01988 
01989   sec = bfd_get_section_by_name (abfd, MMO_DATA_SECTION_NAME);
01990   if (sec != NULL
01991       && (bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS)
01992       && ! bfd_set_section_flags (abfd, sec,
01993                               bfd_get_section_flags (abfd, sec)
01994                               | SEC_ALLOC | SEC_LOAD))
01995     error = TRUE;
01996 
01997   /* Free whatever resources we took.  */
01998   for (i = 0; i < sizeof (file_names) / sizeof (file_names[0]); i++)
01999     if (file_names[i])
02000       free (file_names[i]);
02001   return ! error;
02002 }
02003 
02004 /* A hook to set up object file dependent section information.  For mmo,
02005    we point out the shape of allocated section contents.  */
02006 
02007 static bfd_boolean
02008 mmo_new_section_hook (bfd *abfd, asection *newsect)
02009 {
02010   if (!newsect->used_by_bfd)
02011     {
02012       /* We zero-fill all fields and assume NULL is represented by an all
02013         zero-bit pattern.  */
02014       newsect->used_by_bfd
02015        = bfd_zalloc (abfd, sizeof (struct mmo_section_data_struct));
02016       if (!newsect->used_by_bfd)
02017        return FALSE;
02018     }
02019 
02020   /* Always align to at least 32-bit words.  */
02021   newsect->alignment_power = 2;
02022   return _bfd_generic_new_section_hook (abfd, newsect);
02023 }
02024 
02025 /* We already have section contents loaded for sections that have
02026    contents.  */
02027 
02028 static bfd_boolean
02029 mmo_get_section_contents (bfd *abfd ATTRIBUTE_UNUSED,
02030                        asection *sec,
02031                        void * location,
02032                        file_ptr offset,
02033                        bfd_size_type bytes_to_do)
02034 {
02035   /* Iterate over diminishing chunk sizes, copying contents, like
02036      mmo_set_section_contents.  */
02037   while (bytes_to_do)
02038     {
02039       /* A minor song-and-dance to make sure we're not bitten by the
02040         distant possibility of the cast from bfd_vma to int making the
02041         chunk zero-sized.  */
02042       int chunk_size
02043        = (int) bytes_to_do != 0 ? bytes_to_do : MMO_SEC_CONTENTS_CHUNK_SIZE;
02044       bfd_byte *loc;
02045 
02046       do
02047        loc = mmo_get_loc (sec, sec->vma + offset, chunk_size);
02048       while (loc == NULL && (chunk_size /= 2) != 0);
02049 
02050       if (chunk_size == 0)
02051        return FALSE;
02052 
02053       memcpy (location, loc, chunk_size);
02054 
02055       location += chunk_size;
02056       bytes_to_do -= chunk_size;
02057       offset += chunk_size;
02058     }
02059   return TRUE;
02060 }
02061 
02062 /* Return the amount of memory needed to read the symbol table.  */
02063 
02064 static long
02065 mmo_get_symtab_upper_bound (bfd *abfd)
02066 {
02067   return (abfd->symcount + 1) * sizeof (asymbol *);
02068 }
02069 
02070 /* Sort mmo symbols by serial number.  */
02071 
02072 static int
02073 mmo_sort_mmo_symbols (const void *arg1, const void *arg2)
02074 {
02075   const struct mmo_symbol *sym1 = *(const struct mmo_symbol **) arg1;
02076   const struct mmo_symbol *sym2 = *(const struct mmo_symbol **) arg2;
02077 
02078   /* Sort by serial number first.  */
02079   if (sym1->serno < sym2->serno)
02080     return -1;
02081   else if (sym1->serno > sym2->serno)
02082     return 1;
02083 
02084   /* Then sort by address of the table entries.  */
02085   return ((const char *) arg1 - (const char *) arg2);
02086 }
02087 
02088 /* Translate the symbol table.  */
02089 
02090 static long
02091 mmo_canonicalize_symtab (bfd *abfd, asymbol **alocation)
02092 {
02093   unsigned int symcount = bfd_get_symcount (abfd);
02094   asymbol *csymbols;
02095   unsigned int i;
02096 
02097   csymbols = abfd->tdata.mmo_data->csymbols;
02098   if (csymbols == NULL)
02099     {
02100       asymbol *c;
02101       struct mmo_symbol *s;
02102       struct mmo_symbol **msp;
02103 
02104       /* First we store the symbols into the table we'll return, then we
02105         qsort it on the serial number, with secondary on the address of
02106         the symbol, to preserve order if there would be non-unique serial
02107         numbers.  */
02108       for (s = abfd->tdata.mmo_data->symbols,
02109             msp = (struct mmo_symbol **) alocation;
02110           s != NULL;
02111           s = s->next, ++msp)
02112        *msp = s;
02113 
02114       *msp = NULL;
02115 
02116       qsort (alocation, symcount, sizeof (struct mmo_symbol *),
02117             mmo_sort_mmo_symbols);
02118 
02119       csymbols = (asymbol *) bfd_alloc (abfd, symcount * sizeof (asymbol));
02120       if (csymbols == NULL && symcount != 0)
02121        return FALSE;
02122       abfd->tdata.mmo_data->csymbols = csymbols;
02123 
02124       for (msp = (struct mmo_symbol **) alocation, c = csymbols;
02125           *msp != NULL;
02126           msp++, ++c)
02127        {
02128          s = *msp;
02129          c->the_bfd = abfd;
02130          c->name = s->name;
02131          c->value = s->value;
02132          c->flags = BSF_GLOBAL;
02133 
02134          if (s->sym_type == mmo_data_sym)
02135            {
02136              c->section
02137               = bfd_get_section_by_name (abfd, MMO_DATA_SECTION_NAME);
02138 
02139              if (c->section == NULL)
02140               c->section = bfd_abs_section_ptr;
02141              else
02142               c->value -= c->section->vma;
02143            }
02144          else if (s->sym_type == mmo_undef_sym)
02145            c->section = bfd_und_section_ptr;
02146          else if (s->sym_type == mmo_reg_sym)
02147            {
02148              c->section
02149               = bfd_make_section_old_way (abfd, MMIX_REG_SECTION_NAME);
02150              c->section->flags |= SEC_LINKER_CREATED;
02151            }
02152          else
02153            {
02154              asection *textsec
02155               = bfd_get_section_by_name (abfd, MMO_TEXT_SECTION_NAME);
02156              asection *datasec;
02157 
02158              if (textsec != NULL
02159                 && c->value >= textsec->vma
02160                 && c->value <= textsec->vma + textsec->size)
02161               {
02162                 c->section = textsec;
02163                 c->value -= c->section->vma;
02164               }
02165              /* In mmo, symbol types depend on the VMA.  Therefore, if
02166                the data section isn't within the usual bounds, its
02167                symbols are marked as absolute.  Correct that.  This
02168                means we can't have absolute symbols with values matching
02169                data section addresses, but we also can't have with
02170                absolute symbols with values matching text section
02171                addresses.  For such needs, use the ELF format.  */
02172              else if ((datasec
02173                      = bfd_get_section_by_name (abfd,
02174                                              MMO_DATA_SECTION_NAME))
02175                      != NULL
02176                      && c->value >= datasec->vma
02177                      && c->value <= datasec->vma + datasec->size)
02178               {
02179                 c->section = datasec;
02180                 c->value -= c->section->vma;
02181               }
02182              else
02183               c->section = bfd_abs_section_ptr;
02184            }
02185 
02186          c->udata.p = NULL;
02187        }
02188     }
02189 
02190   /* Last, overwrite the incoming table with the right-type entries.  */
02191   for (i = 0; i < symcount; i++)
02192     *alocation++ = csymbols++;
02193   *alocation = NULL;
02194 
02195   return symcount;
02196 }
02197 
02198 /* Get information about a symbol.  */
02199 
02200 static void
02201 mmo_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
02202                    asymbol *symbol, symbol_info *ret)
02203 {
02204   bfd_symbol_info (symbol, ret);
02205 }
02206 
02207 static void
02208 mmo_print_symbol (bfd *abfd, void *afile, asymbol *symbol,
02209                 bfd_print_symbol_type how)
02210 {
02211   FILE *file = (FILE *) afile;
02212 
02213   switch (how)
02214     {
02215     case bfd_print_symbol_name:
02216       fprintf (file, "%s", symbol->name);
02217       break;
02218     default:
02219       bfd_print_symbol_vandf (abfd, file, symbol);
02220 
02221       fprintf (file, " %-5s %s",
02222               symbol->section->name,
02223               symbol->name);
02224     }
02225 }
02226 
02227 /* We can't map a file directly into executable code, so the
02228    size of header information is irrelevant.  */
02229 
02230 static int
02231 mmo_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
02232                   struct bfd_link_info *info ATTRIBUTE_UNUSED)
02233 {
02234   return 0;
02235 }
02236 
02237 /* Write the (section-neutral) file preamble.  */
02238 
02239 static bfd_boolean
02240 mmo_internal_write_header (bfd *abfd)
02241 {
02242   const char lop_pre_bfd[] = { LOP, LOP_PRE, 1, 1};
02243 
02244   if (bfd_bwrite (lop_pre_bfd, 4, abfd) != 4)
02245     return FALSE;
02246 
02247   /* Copy creation time of original file.  */
02248   if (bfd_bwrite (abfd->tdata.mmo_data->created, 4, abfd) != 4)
02249     return FALSE;
02250 
02251   return TRUE;
02252 }
02253 
02254 /* Write the LOP_POST record, with global register initializations.
02255    Z is the Z field of the LOP_POST, corresponding to 255 - number of
02256    registers at DATA.  The Z = 255 field is filled in with the
02257    start-address.  */
02258 
02259 static bfd_boolean
02260 mmo_internal_write_post (bfd *abfd, int z, asection *sec)
02261 {
02262   int i;
02263   bfd_byte buf[8];
02264   mmo_write_tetra_raw (abfd, (LOP << 24) | (LOP_POST << 16) | z);
02265 
02266   for (i = z; i < 255; i++)
02267     {
02268       bfd_byte *data = mmo_get_loc (sec, i * 8, 8);
02269 
02270       if (bfd_bwrite (data, 8, abfd) != 8)
02271        return FALSE;
02272     }
02273 
02274   /* For Z == $255, we always emit the start location; supposedly Main,
02275      but we have it handy at bfd_get_start_address.  If we're called with
02276      Z == 255, don't assume DATA is valid.  */
02277   bfd_put_64 (abfd, bfd_get_start_address (abfd), buf);
02278 
02279   return ! abfd->tdata.mmo_data->have_error && bfd_bwrite (buf, 8, abfd) == 8;
02280 }
02281 
02282 /* Translate to and from BFD flags.  This is to make sure that we don't
02283    get bitten by BFD flag number changes.  */
02284 
02285 static flagword
02286 mmo_sec_flags_from_bfd_flags (flagword flags)
02287 {
02288   flagword oflags = 0;
02289 
02290   if (flags & SEC_ALLOC)
02291     oflags |= MMO_SEC_ALLOC;
02292   if (flags & SEC_LOAD)
02293     oflags |= MMO_SEC_LOAD;
02294   if (flags & SEC_RELOC)
02295     oflags |= MMO_SEC_RELOC;
02296   if (flags & SEC_READONLY)
02297     oflags |= MMO_SEC_READONLY;
02298   if (flags & SEC_CODE)
02299     oflags |= MMO_SEC_CODE;
02300   if (flags & SEC_DATA)
02301     oflags |= MMO_SEC_DATA;
02302   if (flags & SEC_NEVER_LOAD)
02303     oflags |= MMO_SEC_NEVER_LOAD;
02304   if (flags & SEC_IS_COMMON)
02305     oflags |= MMO_SEC_IS_COMMON;
02306   if (flags & SEC_DEBUGGING)
02307     oflags |= MMO_SEC_DEBUGGING;
02308 
02309   return oflags;
02310 }
02311 
02312 static flagword
02313 bfd_sec_flags_from_mmo_flags (flagword flags)
02314 {
02315   flagword oflags = 0;
02316 
02317   if (flags & MMO_SEC_ALLOC)
02318     oflags |= SEC_ALLOC;
02319   if (flags & MMO_SEC_LOAD)
02320     oflags |= SEC_LOAD;
02321   if (flags & MMO_SEC_RELOC)
02322     oflags |= SEC_RELOC;
02323   if (flags & MMO_SEC_READONLY)
02324     oflags |= SEC_READONLY;
02325   if (flags & MMO_SEC_CODE)
02326     oflags |= SEC_CODE;
02327   if (flags & MMO_SEC_DATA)
02328     oflags |= SEC_DATA;
02329   if (flags & MMO_SEC_NEVER_LOAD)
02330     oflags |= SEC_NEVER_LOAD;
02331   if (flags & MMO_SEC_IS_COMMON)
02332     oflags |= SEC_IS_COMMON;
02333   if (flags & MMO_SEC_DEBUGGING)
02334     oflags |= SEC_DEBUGGING;
02335 
02336   return oflags;
02337 }
02338 
02339 /* Return TRUE iff the leading or trailing tetrabyte in SEC is defined and
02340    is 0.  */
02341 
02342 static bfd_boolean
02343 mmo_has_leading_or_trailing_zero_tetra_p (bfd *abfd, asection *sec)
02344 {
02345   bfd_vma secaddr = bfd_get_section_vma (abfd, sec);
02346 
02347   if (sec->size < 4)
02348     return FALSE;
02349 
02350   if (bfd_get_32 (abfd, mmo_get_loc (sec, secaddr, 4)) == 0
02351       && bfd_get_32 (abfd,
02352                    mmo_get_loc (sec, secaddr + sec->size - 4, 4)) == 0)
02353     return TRUE;
02354 
02355   return FALSE;
02356 }
02357 
02358 /* Write a section.  */
02359 
02360 static bfd_boolean
02361 mmo_internal_write_section (bfd *abfd, asection *sec)
02362 {
02363   /* We do it differently depending on what section this is:
02364 
02365    ".text": Output, prepended by information about the first source file
02366    (not yet implemented.)
02367 
02368    ".data": Output.
02369 
02370    (".MMIX.reg_contents": Not handled here.)
02371 
02372    Anything else: Output inside a lop_spec 80, in the format described
02373    above.  */
02374 
02375   if (strcmp (sec->name, MMO_TEXT_SECTION_NAME) == 0)
02376     {
02377       bfd_vma secaddr = bfd_get_section_vma (abfd, sec);
02378 
02379       /* Because leading and trailing zeros are omitted in output, we need to
02380         specify the section boundaries so they're correct when the file
02381         is read in again.  That's also the case if this section is
02382         specified as not within its usual boundaries or alignments.  */
02383       if (sec->size != 0
02384          && (secaddr + sec->size >= (bfd_vma) 1 << 56
02385              || (secaddr & 3) != 0
02386              || (sec->size & 3) != 0
02387              || mmo_has_leading_or_trailing_zero_tetra_p (abfd, sec)))
02388        {
02389          if (!mmo_write_section_description (abfd, sec))
02390            return FALSE;
02391        }
02392 
02393       /* FIXME: Output source file name and line number.  */
02394       return mmo_write_loc_chunk_list (abfd, mmo_section_data (sec)->head);
02395     }
02396   else if (strcmp (sec->name, MMO_DATA_SECTION_NAME) == 0)
02397     {
02398       bfd_vma secaddr = bfd_get_section_vma (abfd, sec);
02399 
02400       /* Same goes as for MMO_TEXT_SECTION_NAME above.  */
02401       if (sec->size != 0
02402          && (secaddr < (bfd_vma) 0x20 << 56
02403              || secaddr + sec->size >= (bfd_vma) 0x21 << 56
02404              || (secaddr & 3) != 0
02405              || (sec->size & 3) != 0
02406              || mmo_has_leading_or_trailing_zero_tetra_p (abfd, sec)))
02407        {
02408          if (!mmo_write_section_description (abfd, sec))
02409            return FALSE;
02410        }
02411 
02412       return mmo_write_loc_chunk_list (abfd, mmo_section_data (sec)->head);
02413     }
02414   else if (strcmp (sec->name, MMIX_REG_CONTENTS_SECTION_NAME) == 0)
02415     /* Not handled here.  */
02416     {
02417       /* This would normally be an abort call since this can't happen, but
02418          we don't do that.  */
02419       bfd_set_error (bfd_error_bad_value);
02420       return FALSE;
02421     }
02422   else if (CONST_STRNEQ (sec->name, MMIX_OTHER_SPEC_SECTION_PREFIX))
02423     {
02424       int n = atoi (sec->name + strlen (MMIX_OTHER_SPEC_SECTION_PREFIX));
02425 
02426       mmo_write_tetra_raw (abfd, (LOP << 24) | (LOP_SPEC << 16) | n);
02427       return (! abfd->tdata.mmo_data->have_error
02428              && mmo_write_chunk_list (abfd, mmo_section_data (sec)->head));
02429     }
02430   /* Ignore sections that are just allocated or empty; we write out
02431      _contents_ here.  */
02432   else if ((bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS) != 0
02433           && sec->size != 0)
02434     {
02435       if (!mmo_write_section_description (abfd, sec))
02436        return FALSE;
02437 
02438       /* Writing a LOP_LOC ends the LOP_SPEC data, and makes data actually
02439         loaded.  */
02440       if (bfd_get_section_flags (abfd, sec) & SEC_LOAD)
02441        return (! abfd->tdata.mmo_data->have_error
02442               && mmo_write_loc_chunk_list (abfd,
02443                                     mmo_section_data (sec)->head));
02444       return (! abfd->tdata.mmo_data->have_error
02445              && mmo_write_chunk_list (abfd, mmo_section_data (sec)->head));
02446     }
02447 
02448   /* Some section without contents.  */
02449   return TRUE;
02450 }
02451 
02452 /* Write the description of a section, extended-mmo-style.  */
02453 
02454 static bfd_boolean
02455 mmo_write_section_description (bfd *abfd, asection *sec)
02456 {
02457   /* Keep the following document-comment formatted the way it is.  */
02458 /*
02459 INODE
02460 mmo section mapping, , Symbol-table, mmo
02461 SUBSECTION
02462        mmo section mapping
02463 
02464        The implementation in BFD uses special data type 80 (decimal) to
02465        encapsulate and describe named sections, containing e.g.@: debug
02466        information.  If needed, any datum in the encapsulation will be
02467        quoted using lop_quote.  First comes a 32-bit word holding the
02468        number of 32-bit words containing the zero-terminated zero-padded
02469        segment name.  After the name there's a 32-bit word holding flags
02470        describing the section type.  Then comes a 64-bit big-endian word
02471        with the section length (in bytes), then another with the section
02472        start address.  Depending on the type of section, the contents
02473        might follow, zero-padded to 32-bit boundary.  For a loadable
02474        section (such as data or code), the contents might follow at some
02475        later point, not necessarily immediately, as a lop_loc with the
02476        same start address as in the section description, followed by the
02477        contents.  This in effect forms a descriptor that must be emitted
02478        before the actual contents.  Sections described this way must not
02479        overlap.
02480 
02481        For areas that don't have such descriptors, synthetic sections are
02482        formed by BFD.  Consecutive contents in the two memory areas
02483        @samp{0x0000@dots{}00} to @samp{0x01ff@dots{}ff} and
02484        @samp{0x2000@dots{}00} to @samp{0x20ff@dots{}ff} are entered in
02485        sections named <<.text>> and <<.data>> respectively.  If an area
02486        is not otherwise described, but would together with a neighboring
02487        lower area be less than @samp{0x40000000} bytes long, it is joined
02488        with the lower area and the gap is zero-filled.  For other cases,
02489        a new section is formed, named <<.MMIX.sec.@var{n}>>.  Here,
02490        @var{n} is a number, a running count through the mmo file,
02491        starting at 0.
02492 
02493 EXAMPLE
02494        A loadable section specified as:
02495 
02496 | .section secname,"ax"
02497 | TETRA 1,2,3,4,-1,-2009
02498 | BYTE 80
02499 
02500        and linked to address @samp{0x4}, is represented by the sequence:
02501 
02502 | 0x98080050 - lop_spec 80
02503 | 0x00000002 - two 32-bit words for the section name
02504 | 0x7365636e - "secn"
02505 | 0x616d6500 - "ame\0"
02506 | 0x00000033 - flags CODE, READONLY, LOAD, ALLOC
02507 | 0x00000000 - high 32 bits of section length
02508 | 0x0000001c - section length is 28 bytes; 6 * 4 + 1 + alignment to 32 bits
02509 | 0x00000000 - high 32 bits of section address
02510 | 0x00000004 - section address is 4
02511 | 0x98010002 - 64 bits with address of following data
02512 | 0x00000000 - high 32 bits of address
02513 | 0x00000004 - low 32 bits: data starts at address 4
02514 | 0x00000001 - 1
02515 | 0x00000002 - 2
02516 | 0x00000003 - 3
02517 | 0x00000004 - 4
02518 | 0xffffffff - -1
02519 | 0xfffff827 - -2009
02520 | 0x50000000 - 80 as a byte, padded with zeros.
02521 
02522        Note that the lop_spec wrapping does not include the section
02523        contents.  Compare this to a non-loaded section specified as:
02524 
02525 | .section thirdsec
02526 | TETRA 200001,100002
02527 | BYTE 38,40
02528 
02529        This, when linked to address @samp{0x200000000000001c}, is
02530        represented by:
02531 
02532 | 0x98080050 - lop_spec 80
02533 | 0x00000002 - two 32-bit words for the section name
02534 | 0x7365636e - "thir"
02535 | 0x616d6500 - "dsec"
02536 | 0x00000010 - flag READONLY
02537 | 0x00000000 - high 32 bits of section length
02538 | 0x0000000c - section length is 12 bytes; 2 * 4 + 2 + alignment to 32 bits
02539 | 0x20000000 - high 32 bits of address
02540 | 0x0000001c - low 32 bits of address 0x200000000000001c
02541 | 0x00030d41 - 200001
02542 | 0x000186a2 - 100002
02543 | 0x26280000 - 38, 40 as bytes, padded with zeros
02544 
02545        For the latter example, the section contents must not be
02546        loaded in memory, and is therefore specified as part of the
02547        special data.  The address is usually unimportant but might
02548        provide information for e.g.@: the DWARF 2 debugging format.  */
02549 
02550   mmo_write_tetra_raw (abfd, LOP_SPEC_SECTION);
02551   mmo_write_tetra (abfd, (strlen (sec->name) + 3) / 4);
02552   mmo_write_chunk (abfd, (bfd_byte *) sec->name, strlen (sec->name));
02553   mmo_flush_chunk (abfd);
02554   /* FIXME: We can get debug sections (.debug_line & Co.) with a section
02555      flag still having SEC_RELOC set.  Investigate.  This might be true
02556      for all alien sections; perhaps mmo.em should clear that flag.  Might
02557      be related to weak references.  */
02558   mmo_write_tetra (abfd,
02559                  mmo_sec_flags_from_bfd_flags
02560                  (bfd_get_section_flags (abfd, sec)));
02561   mmo_write_octa (abfd, sec->size);
02562   mmo_write_octa (abfd, bfd_get_section_vma (abfd, sec));
02563   return TRUE;
02564 }
02565 
02566 /* We save up all data before output.  */
02567 
02568 static bfd_boolean
02569 mmo_set_section_contents (bfd *abfd ATTRIBUTE_UNUSED, sec_ptr sec,
02570                        const void *location, file_ptr offset,
02571                        bfd_size_type bytes_to_do)
02572 {
02573   /* Iterate over diminishing chunk sizes, copying contents.  */
02574   while (bytes_to_do)
02575     {
02576       /* A minor song-and-dance to make sure we're not bitten by the
02577         distant possibility of the cast from bfd_vma to int making the
02578         chunk zero-sized.  */
02579       int chunk_size
02580        = (int) bytes_to_do != 0 ? bytes_to_do : MMO_SEC_CONTENTS_CHUNK_SIZE;
02581       bfd_byte *loc;
02582 
02583       do
02584        loc = mmo_get_loc (sec, sec->vma + offset, chunk_size);
02585       while (loc == NULL && (chunk_size /= 2) != 0);
02586 
02587       if (chunk_size == 0)
02588        return FALSE;
02589 
02590       memcpy (loc, location, chunk_size);
02591 
02592       location += chunk_size;
02593       bytes_to_do -= chunk_size;
02594       offset += chunk_size;
02595     }
02596   return TRUE;
02597 }
02598 
02599 /* Add a symbol to a trie-tree.  */
02600 
02601 static bfd_boolean
02602 mmo_internal_add_3_sym (bfd *abfd, struct mmo_symbol_trie *rootp,
02603                      const struct mmo_symbol *symp)
02604 {
02605   const char *name = symp->name;
02606   struct mmo_symbol_trie *trie = rootp;
02607   struct mmo_symbol_trie **triep = NULL;
02608 
02609   while (*name && trie != NULL)
02610     {
02611       if (*name < trie->symchar)
02612        {
02613          triep = &trie->left;
02614          trie = trie->left;
02615        }
02616       else if (*name > trie->symchar)
02617        {
02618          triep = &trie->right;
02619          trie = trie->right;
02620        }
02621       else if (*name == trie->symchar)
02622        {
02623          triep = &trie->middle;
02624          name++;
02625 
02626          /* Make sure "trie" points to where we should fill in the
02627             current symbol whenever we've iterated through "name".  We
02628             would lose the right position if we encounter "foobar" then
02629             "foo".  */
02630          if (*name)
02631            trie = trie->middle;
02632        }
02633     }
02634 
02635   while (*name != 0)
02636     {
02637       /* Create middle branches for the rest of the characters.  */
02638       trie = bfd_zalloc (abfd, sizeof (struct mmo_symbol_trie));
02639       *triep = trie;
02640       trie->symchar = *name++;
02641       triep = &trie->middle;
02642     }
02643 
02644   /* We discover a duplicate symbol rather late in the process, but still;
02645      we discover it and bail out.  */
02646   if (trie->sym.name != NULL)
02647     {
02648       (*_bfd_error_handler)
02649        (_("%s: invalid symbol table: duplicate symbol `%s'\n"),
02650         bfd_get_filename (abfd), trie->sym.name);
02651       bfd_set_error (bfd_error_bad_value);
02652       return FALSE;
02653     }
02654 
02655   memcpy (&trie->sym, symp, sizeof *symp);
02656   return TRUE;
02657 }
02658 
02659 /* Find out the length of the serialized version of a trie in bytes.  */
02660 
02661 static unsigned int
02662 mmo_internal_3_length (bfd *abfd, struct mmo_symbol_trie *trie)
02663 {
02664   /* First, one for the control byte.  */
02665   unsigned int length = 1;
02666 
02667   if (trie == NULL)
02668     return 0;
02669 
02670   /* Add in the recursion to the left.  */
02671   length += mmo_internal_3_length (abfd, trie->left);
02672 
02673   /* Add in the middle trie and the character.  */
02674   length += 1 + mmo_internal_3_length (abfd, trie->middle);
02675 
02676   /* Add in the recursion to the right.  */
02677   length += mmo_internal_3_length (abfd, trie->right);
02678 
02679   /* Add in bytes for the symbol (if this is an endnode). */
02680   if (trie->sym.name != NULL)
02681     {
02682       unsigned int serno = trie->sym.serno;
02683 
02684       /* First what it takes to encode the value. */
02685       if (trie->sym.sym_type == mmo_reg_sym)
02686        length++;
02687       else if (trie->sym.sym_type == mmo_undef_sym)
02688        length += 2;
02689       else
02690        {
02691          bfd_vma value = trie->sym.value;
02692 
02693          /* Coded in one to eight following bytes.  */
02694          if (trie->sym.sym_type == mmo_data_sym)
02695            value -= (bfd_vma) 0x20 << 56;
02696 
02697          do
02698            {
02699              value >>= 8;
02700              length++;
02701            }
02702          while (value != 0);
02703        }
02704 
02705       /* Find out what it takes to encode the serial number.  */
02706       do
02707        {
02708          serno >>= 7;
02709          length++;
02710        }
02711       while (serno != 0);
02712     }
02713 
02714   return length;
02715 }
02716 
02717 /* Helper function for outputting the serial number of a symbol, output as
02718    a variant of leb128 (see dwarf2 documentation) which could be called
02719    beb128.  Using a helper function and recursion simplifies debugging.  */
02720 
02721 static void
02722 mmo_beb128_out (bfd *abfd, int serno, int marker)
02723 {
02724   if (serno & ~0x7f)
02725     mmo_beb128_out (abfd, serno >> 7, 0);
02726   mmo_write_byte (abfd, marker | (serno & 0x7f));
02727 }
02728 
02729 /* Serialize a trie.  */
02730 
02731 static void
02732 mmo_internal_3_dump (bfd *abfd, struct mmo_symbol_trie *trie)
02733 {
02734   bfd_byte control = 0;
02735 
02736   if (trie == NULL)
02737     return;
02738 
02739   if (trie->left)
02740     control |= MMO3_LEFT;
02741 
02742   if (trie->middle)
02743     control |= MMO3_MIDDLE;
02744 
02745   if (trie->right)
02746     control |= MMO3_RIGHT;
02747 
02748   if (trie->sym.name != NULL)
02749     {
02750       /* Encode the symbol type and length of value bytes.  */
02751       if (trie->sym.sym_type == mmo_reg_sym)
02752        control |= MMO3_REGQUAL_BITS;
02753       else if (trie->sym.sym_type == mmo_undef_sym)
02754        control |= MMO3_UNDEF;
02755       else
02756        {
02757          bfd_vma value = trie->sym.value;
02758 
02759          /* Coded in 1..8 following bytes.  */
02760          if (trie->sym.sym_type == mmo_data_sym)
02761            {
02762              control |= MMO3_DATA;
02763              value -= (bfd_vma) 0x20 << 56;
02764            }
02765 
02766          do
02767            {
02768              value >>= 8;
02769              control++;
02770            }
02771          while (value != 0);
02772        }
02773     }
02774 
02775   /* The control byte is output before recursing.  */
02776   mmo_write_byte (abfd, control);
02777 
02778   mmo_internal_3_dump (abfd, trie->left);
02779 
02780   if (control & MMO3_SYMBITS)
02781     {
02782       mmo_write_byte (abfd, trie->symchar);
02783 
02784       if (trie->sym.name != NULL)
02785        {
02786          if (trie->sym.sym_type == mmo_reg_sym)
02787            mmo_write_byte (abfd, trie->sym.value);
02788          else if (trie->sym.sym_type == mmo_undef_sym)
02789            {
02790              mmo_write_byte (abfd, 0);
02791              mmo_write_byte (abfd, 0);
02792            }
02793          else
02794            {
02795              bfd_vma value = trie->sym.value;
02796 
02797              bfd_byte byte_n = control & 15;
02798 
02799              /* Coded in 1..8 following bytes.  Note that the value is
02800                shifted out big-endian.  */
02801              if (trie->sym.sym_type == mmo_data_sym)
02802               {
02803                 value -= (bfd_vma) 0x20 << 56;
02804                 byte_n -= 8;
02805               }
02806 
02807              do
02808               {
02809                 mmo_write_byte (abfd, (value >> ((byte_n - 1) * 8)) & 0xff);
02810                 byte_n--;
02811               }
02812              while (byte_n != 0);
02813            }
02814 
02815          mmo_beb128_out (abfd, trie->sym.serno, 128);
02816        }
02817       mmo_internal_3_dump (abfd, trie->middle);
02818     }
02819   mmo_internal_3_dump (abfd, trie->right);
02820 }
02821 
02822 /* Write symbols in mmo format.  Also write the lop_end terminator.  */
02823 
02824 static bfd_boolean
02825 mmo_write_symbols_and_terminator (bfd *abfd)
02826 {
02827   int count = bfd_get_symcount (abfd);
02828   asymbol *maintable[2];
02829   asymbol **table;
02830   asymbol **orig_table = bfd_get_outsymbols (abfd);
02831   int serno;
02832   struct mmo_symbol_trie root;
02833   int trie_len;
02834   int i;
02835   bfd_byte buf[4];
02836 
02837   /* Create a symbol for "Main".  */
02838   asymbol *fakemain = bfd_make_empty_symbol (abfd);
02839 
02840   fakemain->flags = BSF_GLOBAL;
02841   fakemain->value = bfd_get_start_address (abfd);
02842   fakemain->name = MMIX_START_SYMBOL_NAME;
02843   fakemain->section = bfd_abs_section_ptr;
02844   maintable[0] = fakemain;
02845   maintable[1] = NULL;
02846 
02847   memset (&root, 0, sizeof (root));
02848 
02849   /* Make all symbols take a left turn.  */
02850   root.symchar = 0xff;
02851 
02852   /* There must always be a ":Main", so we'll add one if there are no
02853      symbols.  Make sure we have room for it.  */
02854   table = bfd_alloc (abfd, (count + 1) * sizeof (asymbol *));
02855   if (table == NULL)
02856     return FALSE;
02857 
02858   memcpy (table, orig_table, count * sizeof (asymbol *));
02859 
02860   /* Move :Main (if there is one) to the first position.  This is
02861      necessary to get the same layout of the trie-tree when linking as
02862      when objcopying the result as in the objcopy.exp test "simple objcopy
02863      of executable".  It also automatically takes care of assigning serial
02864      number 1 to :Main (as is mandatory).  */
02865   for (i = 0; i < count; i++)
02866     if (table[i] != NULL
02867        && strcmp (table[i]->name, MMIX_START_SYMBOL_NAME) == 0
02868        && (table[i]->flags & (BSF_DEBUGGING|BSF_GLOBAL)) == BSF_GLOBAL)
02869       {
02870        asymbol *mainsym = table[i];
02871        memcpy (table + 1, orig_table, i * sizeof (asymbol *));
02872        table[0] = mainsym;
02873 
02874        /* Check that the value assigned to :Main is the same as the entry
02875           address.  The default linker script asserts this.  This is as
02876           good a place as any to check this consistency. */
02877        if ((mainsym->value
02878             + mainsym->section->output_section->vma
02879             + mainsym->section->output_offset)
02880            != bfd_get_start_address (abfd))
02881          {
02882            /* Arbitrary buffer to hold the printable representation of a
02883               vma.  */
02884            char vmas_main[40];
02885            char vmas_start[40];
02886            bfd_vma vma_start = bfd_get_start_address (abfd);
02887 
02888            sprintf_vma (vmas_main, mainsym->value);
02889            sprintf_vma (vmas_start, vma_start);
02890 
02891            (*_bfd_error_handler)
02892              (_("%s: Bad symbol definition: `Main' set to %s rather"
02893                " than the start address %s\n"),
02894               bfd_get_filename (abfd), vmas_main, vmas_start);
02895            bfd_set_error (bfd_error_bad_value);
02896            return FALSE;
02897          }
02898        break;
02899       }
02900   if (i == count && count != 0)
02901     {
02902       /* When there are symbols, there must be a :Main.  There was no
02903         :Main, so we need to add it manually.  */
02904       memcpy (table + 1, orig_table, count * sizeof (asymbol *));
02905       table[0] = fakemain;
02906       count++;
02907     }
02908 
02909   for (i = 0, serno = 1; i < count && table[i] != NULL; i++)
02910     {
02911       asymbol *s = table[i];
02912 
02913       /* It's not enough to consult bfd_is_local_label, since it does not
02914         mean "local" in the sense of linkable-and-observable-after-link.
02915         Let's just check the BSF_GLOBAL flag.
02916 
02917         Also, don't export symbols with characters not in the allowed set.  */
02918       if ((s->flags & (BSF_DEBUGGING|BSF_GLOBAL)) == BSF_GLOBAL
02919          && strspn (s->name,
02920                    valid_mmo_symbol_character_set) == strlen (s->name))
02921        {
02922          struct mmo_symbol sym;
02923          memset (&sym, 0, sizeof (sym));
02924 
02925          /* Need to strip const here; strdup:ing would leak and the
02926             existing string must be safe to reuse.  */
02927          sym.name = (char *) s->name;
02928          sym.value =
02929            s->value
02930            + s->section->output_section->vma
02931            + s->section->output_offset;
02932 
02933          if (bfd_is_und_section (s->section))
02934            sym.sym_type = mmo_undef_sym;
02935          else if (strcmp (s->section->name, MMO_DATA_SECTION_NAME) == 0
02936                  /* The encoding of data symbols require that the "rest"
02937                     of the value fits in 6 bytes, so the upper two bytes
02938                     must be 0x2000.  All other symbols get to be the
02939                     absolute type.  */
02940                  && (sym.value >> 48) == 0x2000)
02941            sym.sym_type = mmo_data_sym;
02942          else if (strcmp (s->section->name, MMIX_REG_SECTION_NAME) == 0)
02943            sym.sym_type = mmo_reg_sym;
02944          else if (strcmp (s->section->name,
02945                         MMIX_REG_CONTENTS_SECTION_NAME) == 0)
02946            {
02947              sym.sym_type = mmo_reg_sym;
02948              sym.value /= 8;
02949            }
02950          else
02951            sym.sym_type = mmo_abs_sym;
02952 
02953          /* FIXME: We assume the order of the received symbols is an
02954             ordered mapping of the serial numbers.  This is not
02955             necessarily true if we e.g. objcopy a mmo file to another and
02956             there are gaps in the numbering.  Not sure if this can
02957             happen.  Not sure what to do.  */
02958          sym.serno = serno++;
02959 
02960          if (! mmo_internal_add_3_sym (abfd, &root, &sym))
02961            return FALSE;
02962        }
02963     }
02964 
02965   /* Change the root node to be a ":"-prefix.  */
02966   root.symchar = ':';
02967   root.middle = root.left;
02968   root.right = NULL;
02969   root.left = NULL;
02970 
02971   /* We have to find out if we can fit the whole symbol table in the mmo
02972      symtab.  It would be bad to assume we can always fit it in 262144
02973      bytes.  If we can't, just leave the Main symbol.  */
02974   trie_len = (mmo_internal_3_length (abfd, &root) + 3)/4;
02975 
02976   if (trie_len > 0xffff)
02977     {
02978       /* Test this code by using a lower limit in the test above and check
02979         that the single "Main" symbol is emitted and handled properly.
02980         There's no specific test-case.  */
02981       struct mmo_symbol sym;
02982 
02983       (*_bfd_error_handler)
02984        (_("%s: warning: symbol table too large for mmo, larger than 65535"
02985           " 32-bit words: %d.  Only `Main' will be emitted.\n"),
02986         bfd_get_filename (abfd), trie_len);
02987 
02988       memset (&sym, 0, sizeof (sym));
02989       sym.sym_type = mmo_abs_sym;
02990       sym.name = MMIX_START_SYMBOL_NAME;
02991       sym.serno = 1;
02992       sym.value = bfd_get_start_address (abfd);
02993 
02994       /* Then patch up a symbol table to be just the ":Main" symbol.  */
02995       memset (&root, 0, sizeof (root));
02996       root.left = root.middle;
02997       root.symchar = 0xff;
02998       root.middle = NULL;
02999       root.right = NULL;
03000 
03001       if (! mmo_internal_add_3_sym (abfd, &root, &sym))
03002        return FALSE;
03003 
03004       root.symchar = ':';
03005       root.middle = root.left;
03006       root.right = NULL;
03007       root.left = NULL;
03008 
03009       trie_len = (mmo_internal_3_length (abfd, &root) + 3)/4;
03010     }
03011 
03012   /* Reset the written-bytes counter.  */
03013   abfd->tdata.mmo_data->byte_no = 0;
03014 
03015   /* Put out the lop_stab mark.  */
03016   bfd_put_32 (abfd, (LOP << 24) | (LOP_STAB << 16), buf);
03017   if (bfd_bwrite (buf, 4, abfd) != 4)
03018     return FALSE;
03019 
03020   /* Dump out symbols.  */
03021   mmo_internal_3_dump (abfd, &root);
03022 
03023   if (trie_len != (abfd->tdata.mmo_data->byte_no + 3)/4)
03024     {
03025       /* I haven't seen this trig.  It seems no use claiming this case
03026         isn't debugged and abort if we get here.  Instead emit a
03027         diagnostic and fail "normally".  */
03028       (*_bfd_error_handler)
03029        (_("%s: internal error, symbol table changed size from %d to %d"
03030           " words\n"),
03031         bfd_get_filename (abfd), trie_len,
03032         (abfd->tdata.mmo_data->byte_no + 3)/4);
03033       bfd_set_error (bfd_error_bad_value);
03034       return FALSE;
03035     }
03036 
03037   /* Dump out remaining bytes in the buffer and handle I/O errors by
03038      propagating errors.  */
03039   if ((abfd->tdata.mmo_data->byte_no % 4) != 0
03040       || abfd->tdata.mmo_data->have_error)
03041     {
03042       memset (abfd->tdata.mmo_data->buf + (abfd->tdata.mmo_data->byte_no % 4),
03043              0, 4 - (abfd->tdata.mmo_data->byte_no % 4));
03044 
03045       if (abfd->tdata.mmo_data->have_error
03046          || bfd_bwrite (abfd->tdata.mmo_data->buf, 4, abfd) != 4)
03047        return FALSE;
03048     }
03049 
03050   bfd_put_32 (abfd, (LOP << 24) | (LOP_END << 16) | trie_len, buf);
03051   return bfd_bwrite (buf, 4, abfd) == 4;
03052 }
03053 
03054 /* Write section unless it is the register contents section.  For that, we
03055    instead store the section in the supplied pointer.  This function is
03056    used through bfd_map_over_sections.  */
03057 
03058 static void
03059 mmo_write_section_unless_reg_contents (bfd *abfd, asection *sec, void *p)
03060 {
03061   struct mmo_write_sec_info *infop = (struct mmo_write_sec_info *) p;
03062 
03063   if (! infop->retval)
03064     return;
03065 
03066   if (strcmp (sec->name, MMIX_REG_CONTENTS_SECTION_NAME) == 0)
03067     {
03068       infop->reg_section = sec;
03069       return;
03070     }
03071 
03072   /* Exclude the convenience register section.  */
03073   if (strcmp (sec->name, MMIX_REG_SECTION_NAME) == 0)
03074     {
03075       if (bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS)
03076        {
03077          /* Make sure it hasn't got contents.  It seems impossible to
03078             make it carry contents, so we don't have a test-case for
03079             this.  */
03080          (*_bfd_error_handler)
03081            (_("%s: internal error, internal register section %s had"
03082               " contents\n"),
03083             bfd_get_filename (abfd), sec->name);
03084          bfd_set_error (bfd_error_bad_value);
03085          infop->retval = FALSE;
03086          return;
03087        }
03088 
03089       return;
03090     }
03091 
03092   infop->retval = mmo_internal_write_section (abfd, sec);
03093 }
03094 
03095 /* Do the actual output of a file.  Assumes mmo_set_section_contents is
03096    already called. */
03097 
03098 static bfd_boolean
03099 mmo_write_object_contents (bfd *abfd)
03100 {
03101   struct mmo_write_sec_info wsecinfo;
03102 
03103   /* First, there are a few words of preamble.  */
03104   if (! mmo_internal_write_header (abfd))
03105     return FALSE;
03106 
03107   wsecinfo.reg_section = NULL;
03108   wsecinfo.retval = TRUE;
03109 
03110   bfd_map_over_sections (abfd, mmo_write_section_unless_reg_contents,
03111                       &wsecinfo);
03112 
03113   if (! wsecinfo.retval)
03114     return FALSE;
03115 
03116   if (wsecinfo.reg_section != NULL)
03117     {
03118       asection *sec = wsecinfo.reg_section;
03119       unsigned int z = (unsigned int) (sec->vma / 8);
03120 
03121       /* Registers 0..31 must not be global.  Do sanity check on the "vma"
03122         of the register contents section and check that it corresponds to
03123         the length of the section.  */
03124       if (z < 32 || z >= 255 || (sec->vma & 7) != 0
03125          || sec->vma != 256 * 8 - sec->size - 8)
03126        {
03127          bfd_set_error (bfd_error_bad_value);
03128 
03129          if (sec->size == 0)
03130            /* There must always be at least one such register.  */
03131            (*_bfd_error_handler)
03132              (_("%s: no initialized registers; section length 0\n"),
03133               bfd_get_filename (abfd));
03134          else if (sec->vma > (256 - 32) * 8)
03135            /* Provide better error message for the case of too many
03136               global registers.  */
03137            (*_bfd_error_handler)
03138              (_("%s: too many initialized registers; section length %ld\n"),
03139               bfd_get_filename (abfd),
03140               (long) sec->size);
03141          else
03142            (*_bfd_error_handler)
03143              (_("%s: invalid start address for initialized registers of"
03144                " length %ld: 0x%lx%08lx\n"),
03145               bfd_get_filename (abfd),
03146               (long) sec->size,
03147               (unsigned long) (sec->vma >> 32), (unsigned long) (sec->vma));
03148 
03149          return FALSE;
03150        }
03151 
03152       if (! mmo_internal_write_post (abfd, z, sec))
03153        return FALSE;
03154     }
03155   else
03156     if (! mmo_internal_write_post (abfd, 255, NULL))
03157       return FALSE;
03158 
03159   return mmo_write_symbols_and_terminator (abfd);
03160 }
03161 
03162 /* If there's anything in particular in a mmo bfd that we want to free,
03163    make this a real function.  Only do this if you see major memory
03164    thrashing; zealous free:ing will cause unwanted behavior, especially if
03165    you "free" memory allocated with "bfd_alloc", or even "bfd_release" a
03166    block allocated with "bfd_alloc"; they're really allocated from an
03167    obstack, and we don't know what was allocated there since this
03168    particular allocation.  */
03169 
03170 #define       mmo_close_and_cleanup _bfd_generic_close_and_cleanup
03171 #define mmo_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
03172 
03173 /* Perhaps we need to adjust this one; mmo labels (originally) without a
03174    leading ':' might more appropriately be called local.  */
03175 #define mmo_bfd_is_local_label_name bfd_generic_is_local_label_name
03176 #define mmo_bfd_is_target_special_symbol  \
03177   ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
03178 
03179 /* Is this one really used or defined by anyone?  */
03180 #define mmo_get_lineno _bfd_nosymbols_get_lineno
03181 
03182 /* FIXME: We can do better on this one, if we have a dwarf2 .debug_line
03183    section or if MMO line numbers are implemented.  */
03184 #define mmo_find_nearest_line _bfd_nosymbols_find_nearest_line
03185 #define mmo_find_inliner_info _bfd_nosymbols_find_inliner_info
03186 #define mmo_make_empty_symbol _bfd_generic_make_empty_symbol
03187 #define mmo_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
03188 #define mmo_read_minisymbols _bfd_generic_read_minisymbols
03189 #define mmo_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
03190 
03191 #define mmo_get_section_contents_in_window \
03192   _bfd_generic_get_section_contents_in_window
03193 #define mmo_bfd_get_relocated_section_contents \
03194   bfd_generic_get_relocated_section_contents
03195 #define mmo_bfd_gc_sections bfd_generic_gc_sections
03196 #define mmo_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
03197 #define mmo_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
03198 #define mmo_bfd_link_add_symbols _bfd_generic_link_add_symbols
03199 #define mmo_bfd_link_just_syms _bfd_generic_link_just_syms
03200 #define mmo_bfd_final_link _bfd_generic_final_link
03201 #define mmo_bfd_link_split_section _bfd_generic_link_split_section
03202 
03203 /* Strictly speaking, only MMIX uses this restricted format, but let's not
03204    stop anybody from shooting themselves in the foot.  */
03205 #define mmo_set_arch_mach bfd_default_set_arch_mach
03206 #define mmo_bfd_relax_section bfd_generic_relax_section
03207 #define mmo_bfd_merge_sections bfd_generic_merge_sections
03208 #define mmo_bfd_is_group_section bfd_generic_is_group_section
03209 #define mmo_bfd_discard_group bfd_generic_discard_group
03210 #define mmo_section_already_linked \
03211   _bfd_generic_section_already_linked
03212 
03213 /* We want to copy time of creation, otherwise we'd use
03214    BFD_JUMP_TABLE_COPY (_bfd_generic).  */
03215 #define mmo_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
03216 #define mmo_bfd_copy_private_section_data _bfd_generic_bfd_copy_private_section_data
03217 #define mmo_bfd_copy_private_symbol_data _bfd_generic_bfd_copy_private_symbol_data
03218 #define mmo_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data
03219 #define mmo_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
03220 #define mmo_bfd_print_private_bfd_data _bfd_generic_bfd_print_private_bfd_data
03221 
03222 const bfd_target bfd_mmo_vec =
03223 {
03224   "mmo",                    /* name */
03225   bfd_target_mmo_flavour,
03226   BFD_ENDIAN_BIG,           /* target byte order */
03227   BFD_ENDIAN_BIG,           /* target headers byte order */
03228 
03229   /* FIXME: Might need adjustments.  */
03230   (HAS_RELOC | EXEC_P |            /* object flags */
03231    HAS_LINENO | HAS_DEBUG |
03232    HAS_SYMS | HAS_LOCALS | WP_TEXT),
03233 
03234   /* FIXME: Might need adjustments.  */
03235   (SEC_CODE | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
03236    | SEC_READONLY | SEC_EXCLUDE | SEC_DEBUGGING | SEC_IN_MEMORY),
03237                             /* section flags */
03238   0,                        /* leading underscore */
03239   ' ',                      /* ar_pad_char */
03240   16,                       /* ar_max_namelen */
03241   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
03242   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
03243   bfd_getb16, bfd_getb_signed_16, bfd_putb16,    /* data */
03244   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
03245   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
03246   bfd_getb16, bfd_getb_signed_16, bfd_putb16,    /* hdrs */
03247 
03248   {
03249     _bfd_dummy_target,
03250     mmo_object_p,           /* bfd_check_format */
03251     _bfd_dummy_target,
03252     _bfd_dummy_target,
03253   },
03254   {
03255     bfd_false,
03256     mmo_mkobject,
03257     bfd_false,
03258     bfd_false,
03259   },
03260   {                         /* bfd_write_contents */
03261     bfd_false,
03262     mmo_write_object_contents,
03263     bfd_false,
03264     bfd_false,
03265   },
03266 
03267   BFD_JUMP_TABLE_GENERIC (mmo),
03268   BFD_JUMP_TABLE_COPY (mmo),
03269   BFD_JUMP_TABLE_CORE (_bfd_nocore),
03270   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
03271   BFD_JUMP_TABLE_SYMBOLS (mmo),
03272   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
03273   BFD_JUMP_TABLE_WRITE (mmo),
03274   BFD_JUMP_TABLE_LINK (mmo),
03275   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
03276 
03277   NULL,
03278 
03279   NULL
03280 };