diff options
-rw-r--r-- | bfd/ChangeLog | 8 | ||||
-rw-r--r-- | bfd/coffcode.h | 104 |
2 files changed, 112 insertions, 0 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 05ba950..39d5065 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2002-04-09 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. + 2002-04-08 Randolph Chung <tausq@debian.org> * elf32-hppa.c (hppa_unwind_entry_compare): Move to elf-hppa.h. diff --git a/bfd/coffcode.h b/bfd/coffcode.h index 010ed33..dad0ce5 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -341,6 +341,11 @@ static PTR coff_mkobject_hook PARAMS ((bfd *, PTR, PTR)); #ifdef COFF_WITH_PE static flagword handle_COMDAT PARAMS ((bfd *, flagword, PTR, const char *, asection *)); #endif +#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 /* void warning(); */ @@ -3270,6 +3275,100 @@ coff_add_missing_symbols (abfd) #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 @@ -4060,6 +4159,11 @@ coff_write_object_contents (abfd) 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 |