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