This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
SizeOfImage calculation for PECOFF
- From: Jeffrey Naset <jnaset at rsn dot hp dot com>
- To: binutils at sources dot redhat dot com
- Date: Tue, 26 Mar 2002 16:41:13 -0600
- Subject: SizeOfImage calculation for PECOFF
I'm seeing what might be an error in the way the SizeOfImage field in
the PECOFF Optional Header is calculated.
Using the gnu-efi-3.0 package to generate IA-64 EFI executables results
in the SizeOfImage being too small. Here's why:
The linking scheme for this package is to use the linker to generate an
ELF shared library [to get position-independent code generation] and
then objcopy to move the appropriate sections into the PECOFF-format
.EFI executable.
Not all sections of the shared library are copied; in particular, the
first section in the linker script, .hash, is not copied. (There is a
reason, which I do not know, why .hash must come first in the linker
script) The .text section has its VMA (load address) bumped up to
accommodate the space taken by the .hash section. It keeps this address
when copied into the PECOFF executable by objcopy.
The result is that I get a PECOFF with an ImageBase of 0x000000, but
whose first section actually starts at 0x002000. That is, there is a
"hole" in the address space of this file. (This problem also occurs if
there is a hole between sections)
Now, the SizeOfImage calculation done by BFD (peXXigen.c:666) reflects
what the "Microsoft Portable Executable and Common Object File Format
Specification" says:
... Size, in bytes, of image, including all headers; must be a multiple
of section alignment. ...
BFD adds up the section sizes (rounding each section up to a multiple of
section alignment) and sets SizeOfImage. In this case, I get a
SizeOfImage of 0x66000.
Now, when loading the executable from an IA-64 EFI firmware prompt, it
fails loading the last section, because the section begins at 0x64000
and extends for 0x2c00 bytes... past the 0x66000 mark.
I can fix this by changing the SizeOfImage calculation to be the
distance between the ImageBase and the highest address used by any
section. It appears this is compatible with the EFI firmware's
interpretation, which is using SizeOfImage as an indication of how much
contiguous memory to allocate to hold the image.
In making this calculation, I ignore the part of the MS spec that says
"...including all headers..." -- this doesn't apply to this type of
calculation.
Is there any interest for/against changing this calculation? Here's the
new method:
{
asection *sec;
bfd_vma dsize = 0;
bfd_vma isize = SA(abfd->sections->filepos);
bfd_vma tsize = 0;
bfd_vma sec_end;
for (sec = abfd->sections; sec; sec = sec->next)
{
int rounded = FA(sec->_raw_size);
if (sec->flags & SEC_DATA)
dsize += rounded;
if (sec->flags & SEC_CODE)
tsize += rounded;
sec_end = SA( FA( pei_section_data (abfd, sec)->virt_size +
sec->vma));
if (sec_end-ib > isize) isize = sec_end-ib;
}
aouthdr_in->dsize = dsize;
aouthdr_in->tsize = tsize;
extra->SizeOfImage = isize;
}
- Jeffrey Naset
jnaset@rsn.hp.com