diff options
Diffstat (limited to 'bfd/peicode.h')
-rw-r--r-- | bfd/peicode.h | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/bfd/peicode.h b/bfd/peicode.h index 0b6bde4..84dfe57 100644 --- a/bfd/peicode.h +++ b/bfd/peicode.h @@ -361,3 +361,84 @@ pe_bfd_copy_private_bfd_data (ibfd, obfd) _bfd_pe_bfd_copy_private_section_data #define coff_get_symbol_info _bfd_pe_get_symbol_info + +static const bfd_target * +pe_bfd_object_p (abfd) + bfd * abfd; +{ + /* We need to handle a PE image correctly. In PE images created by + the GNU linker, the offset to the COFF header is always the size. + However, this is not the case in images generated by other PE + linkers. The PE format stores a four byte offset to the PE + signature just before the COFF header at location 0x3c of the file. + We pick up that offset, verify that the PE signature is there, and + then set ourselves up to read in the COFF header. */ + bfd_byte buffer[4]; + file_ptr offset; + unsigned long signature; + + /* Detect if this a Microsoft Import Library Format element. */ + if (bfd_seek (abfd, 0x00, SEEK_SET) != 0 + || bfd_read (buffer, 1, 4, abfd) != 4) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_wrong_format); + return NULL; + } + + signature = bfd_h_get_32 (abfd, buffer); + + if (signature == 0xffff0000) + { + _bfd_error_handler (_("%s: Import Library Format archives are not currently supported"), + bfd_get_filename (abfd)); + bfd_set_error (bfd_error_wrong_format); + + return NULL; + } + + if (bfd_seek (abfd, 0x3c, SEEK_SET) != 0 + || bfd_read (buffer, 1, 4, abfd) != 4) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_wrong_format); + return NULL; + } + + offset = bfd_h_get_32 (abfd, buffer); + + if (bfd_seek (abfd, offset, SEEK_SET) != 0 + || bfd_read (buffer, 1, 4, abfd) != 4) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_wrong_format); + return NULL; + } + + signature = bfd_h_get_32 (abfd, buffer); + + if (signature != 0x4550) + { + bfd_set_error (bfd_error_wrong_format); + return NULL; + } + + /* Here is the hack. coff_object_p wants to read filhsz bytes to + pick up the COFF header. We adjust so that that will work. 20 + is the size of the i386 COFF filehdr. */ + if (bfd_seek (abfd, + (bfd_tell (abfd) + - bfd_coff_filhsz (abfd) + + 20), + SEEK_SET) + != 0) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_wrong_format); + return NULL; + } + + return coff_object_p (abfd); +} + +#define coff_object_p pe_bfd_object_p |