* mmo.c (mmo File layout documentation): Add note about low bits

of address.
	(mmo_write_chunk): When handling data remainder, assert that
	previous remaining data is flushed.
	(mmo_write_loc_chunk): Only look for trailing and leading zeros
	when dealing with an aligned VMA and for aligned lengths.  Don't skip
	the last 32-bit-word of zeros.
	(mmo_write_loc_chunk): Emit an error if the VMA is not aligned.
	(mmo_scan) <case LOP_QUOTE>: Move re-alignment of vma before
	emitting data, not after updating it.
	<case LOP_LOC>: Call mmo_decide_section with aligned vma.
This commit is contained in:
Hans-Peter Nilsson 2014-05-02 00:30:42 +02:00
parent 39d1b2aef3
commit 1218d67db1
2 changed files with 56 additions and 14 deletions

View file

@ -1,3 +1,17 @@
2014-05-01 Hans-Peter Nilsson <hp@bitrange.com>
* mmo.c (mmo File layout documentation): Add note about low bits
of address.
(mmo_write_chunk): When handling data remainder, assert that
previous remaining data is flushed.
(mmo_write_loc_chunk): Only look for trailing and leading zeros
when dealing with an aligned VMA and for aligned lengths. Don't skip
the last 32-bit-word of zeros.
(mmo_write_loc_chunk): Emit an error if the VMA is not aligned.
(mmo_scan) <case LOP_QUOTE>: Move re-alignment of vma before
emitting data, not after updating it.
<case LOP_LOC>: Call mmo_decide_section with aligned vma.
2014-04-30 Nick Clifton <nickc@redhat.com>
* compress.c (bfd_is_section_compressed): When checking the

View file

@ -88,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.
@ -822,6 +826,9 @@ mmo_write_chunk (bfd *abfd, const bfd_byte *loc, unsigned int len)
if (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;
}
@ -869,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. */
/* 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 (abfd->tdata.mmo_data->byte_no == 0 || vma != *last_vmap)
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
@ -897,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);
@ -1583,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;
@ -1617,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;