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