This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]