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