X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=bfd%2Fmmo.c;h=2c74c764fc0879fb3621ca9f9ed6b7b65bf5bf86;hb=cbda93a56a0af8d7787ff091caad64af1b2bd085;hp=39cc2699e06e386da818ad06045c1e9bdfef4d5f;hpb=aa820537ead0135a7c38c619039dce8a6fc74ed1;p=platform%2Fupstream%2Fbinutils.git diff --git a/bfd/mmo.c b/bfd/mmo.c index 39cc269..2c74c76 100644 --- a/bfd/mmo.c +++ b/bfd/mmo.c @@ -1,6 +1,5 @@ /* BFD back-end for mmo objects (MMIX-specific object-format). - Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 - 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. @@ -30,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. @@ -76,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 @@ -89,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. @@ -363,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 *); @@ -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; @@ -2827,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; @@ -2843,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)); @@ -3184,6 +3210,7 @@ mmo_write_object_contents (bfd *abfd) /* 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 @@ -3195,10 +3222,12 @@ mmo_write_object_contents (bfd *abfd) #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 @@ -3222,7 +3251,7 @@ mmo_write_object_contents (bfd *abfd) #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, @@ -3241,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 */