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 sources dot redhat dot com
- Date: Sun, 20 Jan 2002 00:51:07 +0100
- Subject: [PATCH] PE image checksum
This patch replaces the patch found at:
http://sources.redhat.com/ml/binutils/2001-11/msg00763.html
It fixes a problem where strip would incorrectly recalculate the checksum
after stripping symbols from an executable as pointed out by Eric Kohl.
2002-01-20 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.67
diff -u -r1.67 coffcode.h
--- coffcode.h 2002/01/05 13:11:31 1.67
+++ coffcode.h 2002/01/19 23:43:06
@@ -324,6 +324,11 @@
static boolean coff_set_arch_mach
PARAMS ((bfd *, enum bfd_architecture, unsigned long)) ATTRIBUTE_UNUSED;
static boolean coff_compute_section_file_positions PARAMS ((bfd *));
+#ifdef COFF_IMAGE_WITH_PE
+static boolean coff_read_word PARAMS ((bfd *, unsigned int *));
+static unsigned int coff_compute_checksum PARAMS ((bfd *));
+static boolean coff_apply_checksum PARAMS ((bfd *));
+#endif
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));
@@ -341,7 +346,7 @@
#ifdef COFF_WITH_PE
static flagword handle_COMDAT PARAMS ((bfd *, flagword, PTR, const char *,
asection *));
#endif
-
+
/* void warning(); */
/* Return a word with STYP_* (scnhdr.s_flags) flags set to represent
@@ -3253,6 +3258,104 @@
#endif /* 0 */
+#ifdef COFF_IMAGE_WITH_PE
+
+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;
+ }
+
+ if (status == 1)
+ {
+ *value = (unsigned int) b[0];
+ }
+ else
+ {
+ *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 + 0x58, SEEK_SET) != 0)
+ return false;
+
+ checksum = 0;
+ bfd_bwrite (&checksum, (bfd_size_type) 4, abfd);
+
+ 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;
+}
+
+#endif /* COFF_IMAGE_WITH_PE */
+
/* SUPPRESS 558 */
/* SUPPRESS 529 */
static boolean
@@ -4038,6 +4141,11 @@
if (amount != bfd_coff_aoutsz (abfd))
return false;
+
+#ifdef COFF_IMAGE_WITH_PE
+ if (!coff_apply_checksum (abfd))
+ return false;
+#endif
}
#ifdef RS6000COFF_C
else