summaryrefslogtreecommitdiff
path: root/bfd/peicode.h
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>1999-12-17 19:03:09 +0000
committerNick Clifton <nickc@redhat.com>1999-12-17 19:03:09 +0000
commitcb665cd3e27a53bdc921ba8df64d44dfce65291d (patch)
tree1e366ebf64f07b581199e75900fd5845135f90aa /bfd/peicode.h
parenteaeaa15ca4218d3486bb5d9a3a27201c55311e56 (diff)
Move PE format object file detection code into common place.
Diffstat (limited to 'bfd/peicode.h')
-rw-r--r--bfd/peicode.h81
1 files changed, 81 insertions, 0 deletions
diff --git a/bfd/peicode.h b/bfd/peicode.h
index 0b6bde4e44..84dfe57372 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