This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[PATCH] PE image checksum
- From: Casper Hornstrup <chorns at users dot sourceforge dot net>
- To: binutils at sourceware dot cygnus dot com
- Date: Sat, 1 Dec 2001 01:18:41 -0500
- Subject: [PATCH] PE image checksum
Hi all.
This patch computes and applies a checksum to PE images.
One thing I'm unsure of is if the call to coff_apply_checksum () is in the
right place - inside the "if (abfd->flags & EXEC_P)" statement. Does
EXEC_P mean that the output is an executable file?
Casper Hornstrup
2001-12-01 Casper S. Hornstrup <chorns@users.sourceforge.net>
* coffcode.h (coff_read_word): New.
(coff_compute_checksum): New.
(coff_apply_checksum): New.
(coff_write_object_contents): Call coff_apply_checksum () to
apply checksum to PE image.
Index: bfd/coffcode.h
===================================================================
RCS file: /cvs/src/src/bfd/coffcode.h,v
retrieving revision 1.64
diff -u -w -r1.64 coffcode.h
--- coffcode.h 2001/10/10 12:08:27 1.64
+++ coffcode.h 2001/12/01 00:06:24
@@ -324,6 +324,9 @@
static boolean coff_set_arch_mach
PARAMS ((bfd *, enum bfd_architecture, unsigned long)) ATTRIBUTE_UNUSED;
static boolean coff_compute_section_file_positions PARAMS ((bfd *));
+static boolean coff_read_word PARAMS ((bfd *, unsigned int *));
+static unsigned int coff_compute_checksum PARAMS ((bfd *));
+static boolean coff_apply_checksum PARAMS ((bfd *));
static boolean coff_write_object_contents PARAMS ((bfd *)) ATTRIBUTE_UNUSED;
static boolean coff_set_section_contents
PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
@@ -3216,6 +3219,95 @@
#endif /* 0 */
+static unsigned int pelength;
+static unsigned int peheader;
+
+static boolean
+coff_read_word (abfd, value)
+ bfd *abfd;
+ unsigned int *value;
+{
+ unsigned char b[2];
+ int status;
+
+ status = bfd_bread (b, (bfd_size_type) 2, abfd);
+ if (status < 1)
+ {
+ *value = 0;
+ return false;
+ }
+
+ *value = (unsigned int) (b[0] + (b[1] << 8));
+
+ pelength += (unsigned int) status;
+
+ return true;
+}
+
+static unsigned int
+coff_compute_checksum (abfd)
+ bfd *abfd;
+{
+ boolean more_data;
+ file_ptr filepos;
+ unsigned int value;
+ unsigned int total;
+
+ total = 0;
+ pelength = 0;
+ filepos = (file_ptr) 0;
+
+ do
+ {
+ if (bfd_seek (abfd, filepos, SEEK_SET) != 0)
+ {
+ return 0;
+ }
+ more_data = coff_read_word (abfd, &value);
+ total += value;
+ total = 0xffff & (total + (total >> 0x10));
+ filepos += 2;
+ } while (more_data);
+
+ return (0xffff & (total + (total >> 0x10)));
+}
+
+static boolean
+coff_apply_checksum (abfd)
+ bfd *abfd;
+{
+ unsigned int computed;
+ unsigned int checksum = 0;
+
+ if (bfd_seek (abfd, 0x3c, SEEK_SET) != 0)
+ {
+ return false;
+ }
+
+ if (!coff_read_word (abfd, &peheader))
+ {
+ return false;
+ }
+
+ if (bfd_seek (abfd, peheader, SEEK_SET) != 0)
+ {
+ return false;
+ }
+
+ computed = coff_compute_checksum (abfd);
+
+ checksum = computed + pelength;
+
+ if (bfd_seek (abfd, peheader + 0x58, SEEK_SET) != 0)
+ {
+ return false;
+ }
+
+ bfd_bwrite (&checksum, (bfd_size_type) 4, abfd);
+
+ return true;
+}
+
/* SUPPRESS 558 */
/* SUPPRESS 529 */
static boolean
@@ -4001,6 +4093,9 @@
if (amount != bfd_coff_aoutsz (abfd))
return false;
+
+ if (!coff_apply_checksum (abfd))
+ return false;
}
#ifdef RS6000COFF_C
else