X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=bfd%2Fmmo.c;h=2c74c764fc0879fb3621ca9f9ed6b7b65bf5bf86;hb=cbda93a56a0af8d7787ff091caad64af1b2bd085;hp=091b341810be3d5b9d2b147ef7616c8a13ae3d87;hpb=01f0fe5e0450edf168c1f612feb93cf588e4e7ea;p=platform%2Fupstream%2Fbinutils.git diff --git a/bfd/mmo.c b/bfd/mmo.c index 091b341..2c74c76 100644 --- a/bfd/mmo.c +++ b/bfd/mmo.c @@ -1,25 +1,26 @@ /* BFD back-end for mmo objects (MMIX-specific object-format). - Copyright 2001, 2002, 2003, 2004, 2005 - Free Software Foundation, Inc. + Copyright (C) 2001-2014 Free Software Foundation, Inc. Written by Hans-Peter Nilsson (hp@bitrange.com). Infrastructure and other bits originally copied from srec.c and binary.c. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ /* SECTION @@ -28,14 +29,14 @@ SECTION The mmo object format is used exclusively together with Professor Donald E.@: Knuth's educational 64-bit processor MMIX. The simulator @command{mmix} which is available at - @url{http://www-cs-faculty.stanford.edu/~knuth/programs/mmix.tar.gz} + @url{http://mmix.cs.hm.edu/src/index.html} understands this format. That package also includes a combined assembler and linker called @command{mmixal}. The mmo format has no advantages feature-wise compared to e.g. ELF. It is a simple non-relocatable object format with no support for archives or debugging information, except for symbol value information and line numbers (which is not yet implemented in BFD). See - @url{http://www-cs-faculty.stanford.edu/~knuth/mmix.html} for more + @url{http://mmix.cs.hm.edu/} for more information about MMIX. The ELF format is used for intermediate object files in the BFD implementation. @@ -74,7 +75,7 @@ SUBSECTION two remaining bytes, called the @samp{Y} and @samp{Z} fields, or the @samp{YZ} field (a 16-bit big-endian number), are used for various purposes different for each lopcode. As documented in - @url{http://www-cs-faculty.stanford.edu/~knuth/mmixal-intro.ps.gz}, + @url{http://mmix.cs.hm.edu/doc/mmixal.pdf}, the lopcodes are: @table @code @@ -87,7 +88,11 @@ SUBSECTION directive, setting the location for the next data to the next 32-bit word (for @math{Z = 1}) or 64-bit word (for @math{Z = 2}), plus @math{Y * 2^56}. Normally @samp{Y} is 0 for the text segment - and 2 for the data segment. + and 2 for the data segment. Beware that the low bits of non- + tetrabyte-aligned values are silently discarded when being + automatically incremented and when storing contents (in contrast + to e.g. its use as current location when followed by lop_fixo + et al before the next possibly-quoted tetrabyte contents). @item lop_skip 0x9802YYZZ. Increase the current location by @samp{YZ} bytes. @@ -195,8 +200,8 @@ EXAMPLE | 0x81000000 | 0x980c0005 - lop_end; symbol table contained five 32-bit words. */ -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "libbfd.h" #include "libiberty.h" #include "elf/mmix.h" @@ -361,7 +366,7 @@ static void mmo_find_sec_w_addr (bfd *, asection *, void *); static void mmo_find_sec_w_addr_grow (bfd *, asection *, void *); static asection *mmo_make_section (bfd *, const char *); static void mmo_get_symbol_info (bfd *, asymbol *, symbol_info *); -static void mmo_print_symbol (bfd *, void *, asymbol *, +static void mmo_print_symbol (bfd *, void *, asymbol *, bfd_print_symbol_type); static void mmo_init (void); static bfd_boolean mmo_mkobject (bfd *); @@ -387,8 +392,7 @@ static void mmo_print_symbol (bfd *, void *, asymbol *, bfd_print_symbol_type); static bfd_boolean mmo_set_section_contents (bfd *, sec_ptr, const void *, file_ptr, bfd_size_type); -static int mmo_sizeof_headers (bfd *, bfd_boolean); -static long mmo_get_reloc_upper_bound (bfd *, asection *); +static int mmo_sizeof_headers (bfd *, struct bfd_link_info *); static bfd_boolean mmo_internal_write_header (bfd *); static bfd_boolean mmo_internal_write_post (bfd *, int, asection *); static bfd_boolean mmo_internal_add_3_sym (bfd *, struct mmo_symbol_trie *, @@ -415,7 +419,6 @@ static void mmo_write_byte (bfd *, bfd_byte); static bfd_boolean mmo_new_section_hook (bfd *, asection *); static int mmo_sort_mmo_symbols (const void *, const void *); static bfd_boolean mmo_write_object_contents (bfd *); -static long mmo_canonicalize_reloc (bfd *, sec_ptr, arelent **, asymbol **); static bfd_boolean mmo_write_section_description (bfd *, asection *); static bfd_boolean mmo_has_leading_or_trailing_zero_tetra_p (bfd *, asection *); @@ -662,8 +665,9 @@ mmo_decide_section (bfd *abfd, bfd_vma vma) if (sec == NULL) return NULL; - if (! sec->user_set_vma) - bfd_set_section_vma (abfd, sec, vma); + if (! sec->user_set_vma && ! bfd_set_section_vma (abfd, sec, vma)) + return NULL; + if (! bfd_set_section_flags (abfd, sec, bfd_get_section_flags (abfd, sec) | SEC_CODE | SEC_LOAD | SEC_ALLOC)) @@ -676,8 +680,9 @@ mmo_decide_section (bfd *abfd, bfd_vma vma) if (sec == NULL) return NULL; - if (! sec->user_set_vma) - bfd_set_section_vma (abfd, sec, vma); + if (! sec->user_set_vma && ! bfd_set_section_vma (abfd, sec, vma)) + return NULL; + if (! bfd_set_section_flags (abfd, sec, bfd_get_section_flags (abfd, sec) | SEC_LOAD | SEC_ALLOC)) @@ -692,8 +697,9 @@ mmo_decide_section (bfd *abfd, bfd_vma vma) /* If there's still no suitable section, make a new one. */ sprintf (sec_name, ".MMIX.sec.%d", abfd->tdata.mmo_data->sec_no++); sec = mmo_make_section (abfd, sec_name); - if (! sec->user_set_vma) - bfd_set_section_vma (abfd, sec, vma); + + if (! sec->user_set_vma && ! bfd_set_section_vma (abfd, sec, vma)) + return NULL; if (! bfd_set_section_flags (abfd, sec, bfd_get_section_flags (abfd, sec) @@ -787,21 +793,21 @@ static INLINE bfd_boolean mmo_write_chunk (bfd *abfd, const bfd_byte *loc, unsigned int len) { bfd_boolean retval = TRUE; + struct mmo_data_struct *mmop = abfd->tdata.mmo_data; /* Fill up a tetra from bytes remaining from a previous chunk. */ - if (abfd->tdata.mmo_data->byte_no != 0) + if (mmop->byte_no != 0) { - while (abfd->tdata.mmo_data->byte_no < 4 && len != 0) + while (mmop->byte_no < 4 && len != 0) { - abfd->tdata.mmo_data->buf[abfd->tdata.mmo_data->byte_no++] = *loc++; + mmop->buf[mmop->byte_no++] = *loc++; len--; } - if (abfd->tdata.mmo_data->byte_no == 4) + if (mmop->byte_no == 4) { - mmo_write_tetra (abfd, - bfd_get_32 (abfd, abfd->tdata.mmo_data->buf)); - abfd->tdata.mmo_data->byte_no = 0; + mmo_write_tetra (abfd, bfd_get_32 (abfd, mmop->buf)); + mmop->byte_no = 0; } } @@ -811,7 +817,7 @@ mmo_write_chunk (bfd *abfd, const bfd_byte *loc, unsigned int len) mmo_write_tetra_raw (abfd, LOP_QUOTE_NEXT); retval = (retval - && ! abfd->tdata.mmo_data->have_error + && ! mmop->have_error && 4 == bfd_bwrite (loc, 4, abfd)); loc += 4; @@ -820,12 +826,15 @@ mmo_write_chunk (bfd *abfd, const bfd_byte *loc, unsigned int len) if (len) { - memcpy (abfd->tdata.mmo_data->buf, loc, len); - abfd->tdata.mmo_data->byte_no = len; + /* We must have flushed a previous remainder if we get one from + this chunk too. */ + BFD_ASSERT (mmop->byte_no == 0); + memcpy (mmop->buf, loc, len); + mmop->byte_no = len; } if (! retval) - abfd->tdata.mmo_data->have_error = TRUE; + mmop->have_error = TRUE; return retval; } @@ -867,25 +876,27 @@ static bfd_boolean mmo_write_loc_chunk (bfd *abfd, bfd_vma vma, const bfd_byte *loc, unsigned int len, bfd_vma *last_vmap) { - /* Find an initial and trailing section of zero tetras; we don't need to - write out zeros. FIXME: When we do this, we should emit section size - and address specifiers, else objcopy can't always perform an identity - translation. Only do this if we *don't* have left-over data from a - previous write or the vma of this chunk is *not* the next address, - because then data isn't tetrabyte-aligned and we're concatenating to - that left-over data. */ - - if (abfd->tdata.mmo_data->byte_no == 0 || vma != *last_vmap) + /* Find an initial and trailing section of zero (aligned) tetras; we don't + need to write out zeros. FIXME: When we do this, we should emit + section size and address specifiers, else objcopy can't always perform + an identity translation. Only do this if we *don't* have left-over + data from a previous write (and will not add any) or else the vma of + this chunk is *not* the next address, because then data isn't + tetrabyte-aligned and we're concatenating to that left-over data. */ + + if ((vma & 3) == 0 + && (abfd->tdata.mmo_data->byte_no == 0 || vma != *last_vmap)) { - while (len >= 4 && bfd_get_32 (abfd, loc) == 0) + while (len > 4 && bfd_get_32 (abfd, loc) == 0) { vma += 4; len -= 4; loc += 4; } - while (len >= 4 && bfd_get_32 (abfd, loc + len - 4) == 0) - len -= 4; + if ((len & 3) == 0) + while (len > 4 && bfd_get_32 (abfd, loc + len - 4) == 0) + len -= 4; } /* Only write out the location if it's different than the one the caller @@ -895,6 +906,22 @@ mmo_write_loc_chunk (bfd *abfd, bfd_vma vma, const bfd_byte *loc, /* We might be in the middle of a sequence. */ mmo_flush_chunk (abfd); + /* This should not happen during normal usage, but can presumably + happen with an erroneous linker-script, so handle gracefully. + Avoid Knuth-specific terms in the message, such as "tetrabyte". + Note that this function will get non-4-multiple lengths and + unaligned vmas but those come in tuples (mostly pairs) and are + continuous (i.e. the if-condition above false) and they are + group-wise aligned. */ + if ((vma & 3) != 0) + { + (*_bfd_error_handler) + (_("%s: attempt to emit contents at non-multiple-of-4 address 0x%lx\n"), + bfd_get_filename (abfd), (unsigned long) vma); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + /* We always write the location as 64 bits; no use saving bytes here. */ mmo_write_tetra_raw (abfd, (LOP << 24) | (LOP_LOC << 16) | 2); @@ -1204,8 +1231,8 @@ Symbol-table, mmo section mapping, File layout, mmo SUBSECTION Symbol table format - From mmixal.w (or really, the generated mmixal.tex) in - @url{http://www-cs-faculty.stanford.edu/~knuth/programs/mmix.tar.gz}): + From mmixal.w (or really, the generated mmixal.tex) in the + MMIXware package which also contains the @command{mmix} simulator: ``Symbols are stored and retrieved by means of a @samp{ternary search trie}, following ideas of Bentley and Sedgewick. (See ACM--SIAM Symp.@: on Discrete Algorithms @samp{8} (1997), 360--369; @@ -1530,13 +1557,13 @@ mmo_scan (bfd *abfd) asection *sec = bfd_make_section_old_way (abfd, MMO_TEXT_SECTION_NAME); asection *non_spec_sec = NULL; bfd_vma non_spec_vma = 0; - char *current_filename = NULL; bfd_size_type nbytes_read = 0; /* Buffer with room to read a 64-bit value. */ bfd_byte buf[8]; long stab_loc = -1; char *file_names[256]; + abfd->symcount = 0; memset (file_names, 0, sizeof (file_names)); if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) @@ -1581,9 +1608,9 @@ mmo_scan (bfd *abfd) if (bfd_bread (buf, 4, abfd) != 4) goto error_return; + vma &= ~3; mmo_xore_32 (sec, vma, bfd_get_32 (abfd, buf)); vma += 4; - vma &= ~3; lineno++; break; @@ -1615,7 +1642,10 @@ mmo_scan (bfd *abfd) goto error_return; } - sec = mmo_decide_section (abfd, vma); + /* When we decide which section the data goes into, we might + create the section. If that happens, make sure the VMA at + creation time is tetra-aligned. */ + sec = mmo_decide_section (abfd, vma & ~3); if (sec == NULL) goto error_return; break; @@ -1789,7 +1819,6 @@ mmo_scan (bfd *abfd) goto error_return; } - current_filename = file_names[y]; lineno = 0; break; @@ -1917,7 +1946,7 @@ mmo_scan (bfd *abfd) /* This must be the last 32-bit word in an mmo file. Let's find out. */ struct stat statbuf; - long curpos = bfd_tell (abfd); + file_ptr curpos = bfd_tell (abfd); if (bfd_stat (abfd, &statbuf) < 0) goto error_return; @@ -2007,19 +2036,21 @@ mmo_scan (bfd *abfd) we point out the shape of allocated section contents. */ static bfd_boolean -mmo_new_section_hook (bfd *abfd ATTRIBUTE_UNUSED, asection *newsect) +mmo_new_section_hook (bfd *abfd, asection *newsect) { - /* We zero-fill all fields and assume NULL is represented by an all - zero-bit pattern. */ - newsect->used_by_bfd = - bfd_zalloc (abfd, sizeof (struct mmo_section_data_struct)); - if (!newsect->used_by_bfd) - return FALSE; + { + /* We zero-fill all fields and assume NULL is represented by an all + zero-bit pattern. */ + newsect->used_by_bfd + = bfd_zalloc (abfd, sizeof (struct mmo_section_data_struct)); + if (!newsect->used_by_bfd) + return FALSE; + } /* Always align to at least 32-bit words. */ newsect->alignment_power = 2; - return TRUE; + return _bfd_generic_new_section_hook (abfd, newsect); } /* We already have section contents loaded for sections that have @@ -2095,7 +2126,7 @@ mmo_canonicalize_symtab (bfd *abfd, asymbol **alocation) unsigned int i; csymbols = abfd->tdata.mmo_data->csymbols; - if (csymbols == NULL) + if (csymbols == NULL && symcount != 0) { asymbol *c; struct mmo_symbol *s; @@ -2117,8 +2148,8 @@ mmo_canonicalize_symtab (bfd *abfd, asymbol **alocation) mmo_sort_mmo_symbols); csymbols = (asymbol *) bfd_alloc (abfd, symcount * sizeof (asymbol)); - if (csymbols == NULL && symcount != 0) - return FALSE; + if (csymbols == NULL) + return -1; abfd->tdata.mmo_data->csymbols = csymbols; for (msp = (struct mmo_symbol **) alocation, c = csymbols; @@ -2229,7 +2260,7 @@ mmo_print_symbol (bfd *abfd, void *afile, asymbol *symbol, static int mmo_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED, - bfd_boolean exec ATTRIBUTE_UNUSED) + struct bfd_link_info *info ATTRIBUTE_UNUSED) { return 0; } @@ -2419,10 +2450,10 @@ mmo_internal_write_section (bfd *abfd, asection *sec) bfd_set_error (bfd_error_bad_value); return FALSE; } - else if (strncmp (sec->name, MMIX_OTHER_SPEC_SECTION_PREFIX, - strlen (MMIX_OTHER_SPEC_SECTION_PREFIX)) == 0) + else if (CONST_STRNEQ (sec->name, MMIX_OTHER_SPEC_SECTION_PREFIX)) { int n = atoi (sec->name + strlen (MMIX_OTHER_SPEC_SECTION_PREFIX)); + mmo_write_tetra_raw (abfd, (LOP << 24) | (LOP_SPEC << 16) | n); return (! abfd->tdata.mmo_data->have_error && mmo_write_chunk_list (abfd, mmo_section_data (sec)->head)); @@ -2825,7 +2856,6 @@ static bfd_boolean mmo_write_symbols_and_terminator (bfd *abfd) { int count = bfd_get_symcount (abfd); - asymbol *maintable[2]; asymbol **table; asymbol **orig_table = bfd_get_outsymbols (abfd); int serno; @@ -2841,8 +2871,6 @@ mmo_write_symbols_and_terminator (bfd *abfd) fakemain->value = bfd_get_start_address (abfd); fakemain->name = MMIX_START_SYMBOL_NAME; fakemain->section = bfd_abs_section_ptr; - maintable[0] = fakemain; - maintable[1] = NULL; memset (&root, 0, sizeof (root)); @@ -3159,28 +3187,6 @@ mmo_write_object_contents (bfd *abfd) return mmo_write_symbols_and_terminator (abfd); } -/* Return the size of a NULL pointer, so we support linking in an mmo - object. */ - -static long -mmo_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, - asection *sec ATTRIBUTE_UNUSED) -{ - return sizeof (void *); -} - -/* Similarly canonicalize relocs to empty, filling in the terminating NULL - pointer. */ - -long -mmo_canonicalize_reloc (bfd *abfd ATTRIBUTE_UNUSED, - sec_ptr section ATTRIBUTE_UNUSED, arelent **relptr, - asymbol **symbols ATTRIBUTE_UNUSED) -{ - *relptr = NULL; - return 0; -} - /* If there's anything in particular in a mmo bfd that we want to free, make this a real function. Only do this if you see major memory thrashing; zealous free:ing will cause unwanted behavior, especially if @@ -3204,6 +3210,7 @@ mmo_canonicalize_reloc (bfd *abfd ATTRIBUTE_UNUSED, /* FIXME: We can do better on this one, if we have a dwarf2 .debug_line section or if MMO line numbers are implemented. */ #define mmo_find_nearest_line _bfd_nosymbols_find_nearest_line +#define mmo_find_line _bfd_nosymbols_find_line #define mmo_find_inliner_info _bfd_nosymbols_find_inliner_info #define mmo_make_empty_symbol _bfd_generic_make_empty_symbol #define mmo_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol @@ -3215,10 +3222,12 @@ mmo_canonicalize_reloc (bfd *abfd ATTRIBUTE_UNUSED, #define mmo_bfd_get_relocated_section_contents \ bfd_generic_get_relocated_section_contents #define mmo_bfd_gc_sections bfd_generic_gc_sections +#define mmo_bfd_lookup_section_flags bfd_generic_lookup_section_flags #define mmo_bfd_link_hash_table_create _bfd_generic_link_hash_table_create -#define mmo_bfd_link_hash_table_free _bfd_generic_link_hash_table_free #define mmo_bfd_link_add_symbols _bfd_generic_link_add_symbols #define mmo_bfd_link_just_syms _bfd_generic_link_just_syms +#define mmo_bfd_copy_link_hash_symbol_type \ + _bfd_generic_copy_link_hash_symbol_type #define mmo_bfd_final_link _bfd_generic_final_link #define mmo_bfd_link_split_section _bfd_generic_link_split_section @@ -3231,18 +3240,7 @@ mmo_canonicalize_reloc (bfd *abfd ATTRIBUTE_UNUSED, #define mmo_bfd_discard_group bfd_generic_discard_group #define mmo_section_already_linked \ _bfd_generic_section_already_linked - -/* objcopy will be upset if we return -1 from bfd_get_reloc_upper_bound by - using BFD_JUMP_TABLE_RELOCS (_bfd_norelocs) rather than 0. FIXME: Most - likely a bug in the _bfd_norelocs definition. - - On the other hand, we smuggle in an mmo object (because setting up ELF - is too cumbersome) when linking (from other formats, presumably ELF) to - represent the g255 entry. We need to link that object, so need to say - it has no relocs. Upper bound for the size of the relocation table is - the size of a NULL pointer, and we support "canonicalization" for that - pointer. */ -#define mmo_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup +#define mmo_bfd_define_common_symbol bfd_generic_define_common_symbol /* We want to copy time of creation, otherwise we'd use BFD_JUMP_TABLE_COPY (_bfd_generic). */ @@ -3253,7 +3251,7 @@ mmo_canonicalize_reloc (bfd *abfd ATTRIBUTE_UNUSED, #define mmo_bfd_set_private_flags _bfd_generic_bfd_set_private_flags #define mmo_bfd_print_private_bfd_data _bfd_generic_bfd_print_private_bfd_data -const bfd_target bfd_mmo_vec = +const bfd_target mmix_mmo_vec = { "mmo", /* name */ bfd_target_mmo_flavour, @@ -3272,6 +3270,7 @@ const bfd_target bfd_mmo_vec = 0, /* leading underscore */ ' ', /* ar_pad_char */ 16, /* ar_max_namelen */ + 0, /* match priority. */ bfd_getb64, bfd_getb_signed_64, bfd_putb64, bfd_getb32, bfd_getb_signed_32, bfd_putb32, bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ @@ -3303,9 +3302,7 @@ const bfd_target bfd_mmo_vec = BFD_JUMP_TABLE_CORE (_bfd_nocore), BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), BFD_JUMP_TABLE_SYMBOLS (mmo), - /* We have to provide a valid method for getting relocs, returning zero, - so we can't say BFD_JUMP_TABLE_RELOCS (_bfd_norelocs). */ - BFD_JUMP_TABLE_RELOCS (mmo), + BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), BFD_JUMP_TABLE_WRITE (mmo), BFD_JUMP_TABLE_LINK (mmo), BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),