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