/* BFD back-end for mmo objects (MMIX-specific object-format).
- Copyright (C) 2001-2015 Free Software Foundation, Inc.
+ Copyright (C) 2001-2017 Free Software Foundation, Inc.
Written by Hans-Peter Nilsson (hp@bitrange.com).
Infrastructure and other bits originally copied from srec.c and
binary.c.
/* We also need a buffer to hold the bytes we count reading or writing. */
bfd_byte buf[4];
+
+ /* Whether we've calculated symbol consistency requirement yet. We do this
+ when-needed, which must be at some time after all section
+ contents is known. */
+ bfd_boolean symbol_consistency_override_calculated;
+
+ /* Whether to consistency-check symbol values, in particular "Main". */
+ bfd_boolean ignore_symbol_consistency;
};
typedef struct mmo_data_struct tdata_type;
if (newsecname == NULL)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: No core to allocate section name %s\n"),
bfd_get_filename (abfd), secname);
bfd_set_error (bfd_error_system_call);
if (abfd->tdata.mmo_data->lop_stab_symbol == NULL)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: No core to allocate a symbol %d bytes long\n"),
bfd_get_filename (abfd), abfd->tdata.mmo_data->max_symbol_length);
goto bad_final;
return TRUE;
}
+static bfd_boolean
+mmo_section_has_contents (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *p ATTRIBUTE_UNUSED)
+{
+ /* The point is to match what --extract-symbols does (well, negated). */
+ return bfd_get_section_size (sec) != 0;
+}
+
+/* Find out whether we should omit symbol consistency checks for this
+ bfd and cache the value.
+
+ This function must only be called when all section contents is
+ known. However, calculating symbol consistency at the time the
+ private BFD data is initialized is too late for some uses. */
+
+static bfd_boolean
+mmo_ignore_symbol_consistency (bfd *abfd)
+{
+ if (!abfd->tdata.mmo_data->symbol_consistency_override_calculated)
+ {
+ abfd->tdata.mmo_data->ignore_symbol_consistency =
+ bfd_sections_find_if (abfd, mmo_section_has_contents, NULL) == NULL;
+
+ abfd->tdata.mmo_data->symbol_consistency_override_calculated = TRUE;
+ }
+
+ return abfd->tdata.mmo_data->ignore_symbol_consistency;
+}
+
static bfd_boolean
mmo_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
{
group-wise aligned. */
if ((vma & 3) != 0)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%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);
object. For written objects, we do it while setting the symbol
table. */
if (strcmp (symname, MMIX_START_SYMBOL_NAME) == 0
- && bfd_get_start_address (abfd) != addr)
+ && bfd_get_start_address (abfd) != addr
+ && !mmo_ignore_symbol_consistency (abfd))
{
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("%s: invalid mmo file: initialization value for $255 is not `Main'\n"),
bfd_get_filename (abfd));
bfd_set_error (bfd_error_bad_value);
abfd->tdata.mmo_data->lop_stab_symbol
[abfd->tdata.mmo_data->symbol_position] = 0;
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: unsupported wide character sequence"
" 0x%02X 0x%02X after symbol name starting with `%s'\n"),
bfd_get_filename (abfd), c, c2,
switch (buf[1])
{
default:
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: invalid mmo file: unsupported lopcode `%d'\n"),
bfd_get_filename (abfd), buf[1]);
bfd_set_error (bfd_error_bad_value);
/* Quote the next 32-bit word. */
if (y != 0 || z != 1)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: invalid mmo file: expected YZ = 1 got YZ = %d for lop_quote\n"),
bfd_get_filename (abfd), y*256+z);
bfd_set_error (bfd_error_bad_value);
}
else
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: invalid mmo file: expected z = 1 or z = 2, got z = %d for lop_loc\n"),
bfd_get_filename (abfd), z);
bfd_set_error (bfd_error_bad_value);
}
else
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: invalid mmo file: expected z = 1 or z = 2, got z = %d for lop_fixo\n"),
bfd_get_filename (abfd), z);
bfd_set_error (bfd_error_bad_value);
if (y != 0)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: invalid mmo file: expected y = 0, got y = %d for lop_fixrx\n"),
bfd_get_filename (abfd), y);
bfd_set_error (bfd_error_bad_value);
if (z != 16 && z != 24)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: invalid mmo file: expected z = 16 or z = 24, got z = %d for lop_fixrx\n"),
bfd_get_filename (abfd), z);
bfd_set_error (bfd_error_bad_value);
p = vma - 4 * ((delta & 0xffffff) - (1 << z));
else
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: invalid mmo file: leading byte of operand word must be 0 or 1, got %d for lop_fixrx\n"),
bfd_get_filename (abfd), buf[0]);
bfd_set_error (bfd_error_bad_value);
if (fname == NULL)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: cannot allocate file name for file number %d, %d bytes\n"),
bfd_get_filename (abfd), y, z * 4 + 1);
bfd_set_error (bfd_error_system_call);
if (file_names[y] != NULL)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: invalid mmo file: file number %d `%s',"
" was already entered as `%s'\n"),
bfd_get_filename (abfd), y, fname, file_names[y]);
if (file_names[y] == NULL)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: invalid mmo file: file name for number %d"
" was not specified before use\n"),
bfd_get_filename (abfd), y);
/* We read in the symbols now, not later. */
if (y != 0 || z != 0)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: invalid mmo file: fields y and z of lop_stab"
" non-zero, y: %d, z: %d\n"),
bfd_get_filename (abfd), y, z);
if (statbuf.st_size != curpos)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: invalid mmo file: lop_end not last item in"
" file\n"),
bfd_get_filename (abfd));
it. */
if ((long) (y * 256 + z) * 4 != (curpos - stab_loc) - 4)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: invalid mmo file: YZ of lop_end (%ld)"
" not equal to the number of tetras to the preceding"
" lop_stab (%ld)\n"),
memcpy (location, loc, chunk_size);
- location += chunk_size;
+ location = (bfd_byte *) location + chunk_size;
bytes_to_do -= chunk_size;
offset += chunk_size;
}
memcpy (loc, location, chunk_size);
- location += chunk_size;
+ location = (bfd_byte *) location + chunk_size;
bytes_to_do -= chunk_size;
offset += chunk_size;
}
we discover it and bail out. */
if (trie->sym.name != NULL)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: invalid symbol table: duplicate symbol `%s'\n"),
bfd_get_filename (abfd), trie->sym.name);
bfd_set_error (bfd_error_bad_value);
&& (table[i]->flags & (BSF_DEBUGGING|BSF_GLOBAL)) == BSF_GLOBAL)
{
asymbol *mainsym = table[i];
+ bfd_vma mainvalue
+ = (mainsym->value
+ + mainsym->section->output_section->vma
+ + mainsym->section->output_offset);
memcpy (table + 1, orig_table, i * sizeof (asymbol *));
table[0] = mainsym;
/* Check that the value assigned to :Main is the same as the entry
address. The default linker script asserts this. This is as
good a place as any to check this consistency. */
- if ((mainsym->value
- + mainsym->section->output_section->vma
- + mainsym->section->output_offset)
- != bfd_get_start_address (abfd))
+ if (mainvalue != bfd_get_start_address (abfd)
+ && !mmo_ignore_symbol_consistency (abfd))
{
/* Arbitrary buffer to hold the printable representation of a
vma. */
char vmas_start[40];
bfd_vma vma_start = bfd_get_start_address (abfd);
- sprintf_vma (vmas_main, mainsym->value);
+ sprintf_vma (vmas_main, mainvalue);
sprintf_vma (vmas_start, vma_start);
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: Bad symbol definition: `Main' set to %s rather"
" than the start address %s\n"),
bfd_get_filename (abfd), vmas_main, vmas_start);
There's no specific test-case. */
struct mmo_symbol sym;
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: warning: symbol table too large for mmo, larger than 65535"
" 32-bit words: %d. Only `Main' will be emitted.\n"),
bfd_get_filename (abfd), trie_len);
/* I haven't seen this trig. It seems no use claiming this case
isn't debugged and abort if we get here. Instead emit a
diagnostic and fail "normally". */
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: internal error, symbol table changed size from %d to %d"
" words\n"),
bfd_get_filename (abfd), trie_len,
/* Make sure it hasn't got contents. It seems impossible to
make it carry contents, so we don't have a test-case for
this. */
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: internal error, internal register section %s had"
" contents\n"),
bfd_get_filename (abfd), sec->name);
if (sec->size == 0)
/* There must always be at least one such register. */
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("%s: no initialized registers; section length 0\n"),
bfd_get_filename (abfd));
else if (sec->vma > (256 - 32) * 8)
/* Provide better error message for the case of too many
global registers. */
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: too many initialized registers; section length %ld\n"),
bfd_get_filename (abfd),
(long) sec->size);
else
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%s: invalid start address for initialized registers of"
" length %ld: 0x%lx%08lx\n"),
bfd_get_filename (abfd),
_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
+#define mmo_bfd_link_check_relocs _bfd_generic_link_check_relocs
/* Strictly speaking, only MMIX uses this restricted format, but let's not
stop anybody from shooting themselves in the foot. */