* mmo.c (mmo_write_section_description): New function broken out

of mmo_internal_write_section.
	(mmo_internal_write_section): For each of .text and .data, call
	mmo_write_section_description before outputting contents if it has
	nontrivially deducible vma or contents.
	(mmo_has_leading_or_trailing_zero_tetra_p): New function.
	(mmo_canonicalize_symtab): Adjust absolute symbols to .data
	symbols if found within the .data address range.
This commit is contained in:
Hans-Peter Nilsson 2004-10-24 21:40:36 +00:00
parent 1fddb8daad
commit aa69fe43dd
2 changed files with 129 additions and 27 deletions

View file

@ -1,3 +1,14 @@
2004-10-24 Hans-Peter Nilsson <hp@bitrange.com>
* mmo.c (mmo_write_section_description): New function broken out
of mmo_internal_write_section.
(mmo_internal_write_section): For each of .text and .data, call
mmo_write_section_description before outputting contents if it has
nontrivially deducible vma or contents.
(mmo_has_leading_or_trailing_zero_tetra_p): New function.
(mmo_canonicalize_symtab): Adjust absolute symbols to .data
symbols if found within the .data address range.
2004-10-24 Daniel Jacobowitz <dan@debian.org>
* opncls.c (bfd_close): Return TRUE for BFD_IN_MEMORY.

145
bfd/mmo.c
View file

@ -464,6 +464,10 @@ static bfd_boolean mmo_write_object_contents
PARAMS ((bfd *));
static long mmo_canonicalize_reloc
PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));
static bfd_boolean mmo_write_section_description
PARAMS ((bfd *, asection *));
static bfd_boolean mmo_has_leading_or_trailing_zero_tetra_p
PARAMS ((bfd *, asection *));
/* Global "const" variables initialized once. Must not depend on
particular input or caller; put such things into the bfd or elsewhere.
@ -2264,6 +2268,7 @@ mmo_canonicalize_symtab (abfd, alocation)
{
asection *textsec
= bfd_get_section_by_name (abfd, MMO_TEXT_SECTION_NAME);
asection *datasec;
if (textsec != NULL
&& c->value >= textsec->vma
@ -2272,6 +2277,23 @@ mmo_canonicalize_symtab (abfd, alocation)
c->section = textsec;
c->value -= c->section->vma;
}
/* In mmo, symbol types depend on the VMA. Therefore, if
the data section isn't within the usual bounds, its
symbols are marked as absolute. Correct that. This
means we can't have absolute symbols with values matching
data section addresses, but we also can't have with
absolute symbols with values matching text section
addresses. For such needs, use the ELF format. */
else if ((datasec
= bfd_get_section_by_name (abfd,
MMO_DATA_SECTION_NAME))
!= NULL
&& c->value >= datasec->vma
&& c->value <= datasec->vma + datasec->size)
{
c->section = datasec;
c->value -= c->section->vma;
}
else
c->section = bfd_abs_section_ptr;
}
@ -2441,6 +2463,27 @@ bfd_sec_flags_from_mmo_flags (flags)
return oflags;
}
/* Return TRUE iff the leading or trailing tetrabyte in SEC is defined and
is 0. */
static bfd_boolean
mmo_has_leading_or_trailing_zero_tetra_p (abfd, sec)
bfd *abfd;
asection *sec;
{
bfd_vma secaddr = bfd_get_section_vma (abfd, sec);
if (sec->size < 4)
return FALSE;
if (bfd_get_32 (abfd, mmo_get_loc (sec, secaddr, 4)) == 0
&& bfd_get_32 (abfd,
mmo_get_loc (sec, secaddr + sec->size - 4, 4)) == 0)
return TRUE;
return FALSE;
}
/* Write a section. */
static bfd_boolean
@ -2461,10 +2504,44 @@ mmo_internal_write_section (abfd, sec)
above. */
if (strcmp (sec->name, MMO_TEXT_SECTION_NAME) == 0)
/* FIXME: Output source file name and line number. */
return mmo_write_loc_chunk_list (abfd, mmo_section_data (sec)->head);
{
bfd_vma secaddr = bfd_get_section_vma (abfd, sec);
/* Because leading and trailing zeros are omitted in output, we need to
specify the section boundaries so they're correct when the file
is read in again. That's also the case if this section is
specified as not within its usual boundaries or alignments. */
if (sec->size != 0
&& (secaddr + sec->size >= (bfd_vma) 1 << 56
|| (secaddr & 3) != 0
|| (sec->size & 3) != 0
|| mmo_has_leading_or_trailing_zero_tetra_p (abfd, sec)))
{
if (!mmo_write_section_description (abfd, sec))
return FALSE;
}
/* FIXME: Output source file name and line number. */
return mmo_write_loc_chunk_list (abfd, mmo_section_data (sec)->head);
}
else if (strcmp (sec->name, MMO_DATA_SECTION_NAME) == 0)
return mmo_write_loc_chunk_list (abfd, mmo_section_data (sec)->head);
{
bfd_vma secaddr = bfd_get_section_vma (abfd, sec);
/* Same goes as for MMO_TEXT_SECTION_NAME above. */
if (sec->size != 0
&& (secaddr < (bfd_vma) 0x20 << 56
|| secaddr + sec->size >= (bfd_vma) 0x21 << 56
|| (secaddr & 3) != 0
|| (sec->size & 3) != 0
|| mmo_has_leading_or_trailing_zero_tetra_p (abfd, sec)))
{
if (!mmo_write_section_description (abfd, sec))
return FALSE;
}
return mmo_write_loc_chunk_list (abfd, mmo_section_data (sec)->head);
}
else if (strcmp (sec->name, MMIX_REG_CONTENTS_SECTION_NAME) == 0)
/* Not handled here. */
{
@ -2486,7 +2563,31 @@ mmo_internal_write_section (abfd, sec)
else if ((bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS) != 0
&& sec->size != 0)
{
/* Keep the document-comment formatted the way it is. */
if (!mmo_write_section_description (abfd, sec))
return FALSE;
/* Writing a LOP_LOC ends the LOP_SPEC data, and makes data actually
loaded. */
if (bfd_get_section_flags (abfd, sec) & SEC_LOAD)
return (! abfd->tdata.mmo_data->have_error
&& mmo_write_loc_chunk_list (abfd,
mmo_section_data (sec)->head));
return (! abfd->tdata.mmo_data->have_error
&& mmo_write_chunk_list (abfd, mmo_section_data (sec)->head));
}
/* Some section without contents. */
return TRUE;
}
/* Write the description of a section, extended-mmo-style. */
static bfd_boolean
mmo_write_section_description (abfd, sec)
bfd *abfd;
asection *sec;
{
/* Keep the following document-comment formatted the way it is. */
/*
INODE
mmo section mapping, , Symbol-table, mmo
@ -2579,29 +2680,19 @@ EXAMPLE
special data. The address is usually unimportant but might
provide information for e.g.@: the DWARF 2 debugging format. */
mmo_write_tetra_raw (abfd, LOP_SPEC_SECTION);
mmo_write_tetra (abfd, (strlen (sec->name) + 3) / 4);
mmo_write_chunk (abfd, sec->name, strlen (sec->name));
mmo_flush_chunk (abfd);
/* FIXME: We can get debug sections (.debug_line & Co.) with a
section flag still having SEC_RELOC set. Investigate. This
might be true for all alien sections; perhaps mmo.em should clear
that flag. Might be related to weak references. */
mmo_write_tetra (abfd,
mmo_sec_flags_from_bfd_flags
(bfd_get_section_flags (abfd, sec)));
mmo_write_octa (abfd, sec->size);
mmo_write_octa (abfd, bfd_get_section_vma (abfd, sec));
/* Writing a LOP_LOC ends the LOP_SPEC data, and makes data actually
loaded. */
if (bfd_get_section_flags (abfd, sec) & SEC_LOAD)
return (! abfd->tdata.mmo_data->have_error
&& mmo_write_loc_chunk_list (abfd,
mmo_section_data (sec)->head));
return (! abfd->tdata.mmo_data->have_error
&& mmo_write_chunk_list (abfd, mmo_section_data (sec)->head));
}
mmo_write_tetra_raw (abfd, LOP_SPEC_SECTION);
mmo_write_tetra (abfd, (strlen (sec->name) + 3) / 4);
mmo_write_chunk (abfd, sec->name, strlen (sec->name));
mmo_flush_chunk (abfd);
/* FIXME: We can get debug sections (.debug_line & Co.) with a section
flag still having SEC_RELOC set. Investigate. This might be true
for all alien sections; perhaps mmo.em should clear that flag. Might
be related to weak references. */
mmo_write_tetra (abfd,
mmo_sec_flags_from_bfd_flags
(bfd_get_section_flags (abfd, sec)));
mmo_write_octa (abfd, sec->size);
mmo_write_octa (abfd, bfd_get_section_vma (abfd, sec));
return TRUE;
}