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