From 7e1b5887642d6c7c341c2db09ae912041d670a79 Mon Sep 17 00:00:00 2001 From: Oleg Tolmatcev Date: Wed, 3 May 2023 15:36:43 +0100 Subject: [PATCH] Improve the speed of computing checksums for COFF binaries. * coffcode.h (coff_read_word_from_buffer): New function. * coffcode.h (COFF_CHECKSUM_BUFFER_SIZE): New constant. * coffcode.h (coff_compute_checksum): Improve speed by reducing the number of seeks and reads used. --- bfd/ChangeLog | 7 ++++++ bfd/coffcode.h | 66 +++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 31e810e0625..61a488c348b 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2023-05-03 Oleg Tolmatcev + + * coffcode.h (coff_read_word_from_buffer): New function. + * coffcode.h (COFF_CHECKSUM_BUFFER_SIZE): New constant. + * coffcode.h (coff_compute_checksum): Improve speed by reducing + the number of seeks and reads used. + 2023-04-24 Nick Clifton * po/la.po: New Georgian translation. diff --git a/bfd/coffcode.h b/bfd/coffcode.h index 96c53aa2b34..974c8ad9854 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -3367,29 +3367,83 @@ coff_read_word (bfd *abfd, unsigned int *value, unsigned int *pelength) return true; } +/* Read a two byte number from buffer B returning the result in VALUE. + No more than BUF_SIZE bytes will be read. + Returns true upobn success, false otherwise. + If successful, increases the value stored in PELENGTH by the number + of bytes read. */ + +static bool +coff_read_word_from_buffer (unsigned char * b, + int buf_size, + unsigned int * value, + unsigned int * pelength) +{ + if (buf_size < 1) + { + *value = 0; + return false; + } + + if (buf_size == 1) + { + *value = (unsigned int)b[0]; + *pelength += 1; + } + else + { + *value = (unsigned int)(b[0] + (b[1] << 8)); + *pelength += 2; + } + + return true; +} + +#define COFF_CHECKSUM_BUFFER_SIZE 0x800000 + static unsigned int coff_compute_checksum (bfd *abfd, unsigned int *pelength) { - bool more_data; file_ptr filepos; unsigned int value; unsigned int total; + unsigned char *buf; + int buf_size; total = 0; *pelength = 0; filepos = (file_ptr) 0; + buf = (unsigned char *) bfd_malloc (COFF_CHECKSUM_BUFFER_SIZE); + if (buf == NULL) + return 0; + buf_size = 0; do { + unsigned char *cur_buf; + int cur_buf_size; + if (bfd_seek (abfd, filepos, SEEK_SET) != 0) return 0; - more_data = coff_read_word (abfd, &value, pelength); - total += value; - total = 0xffff & (total + (total >> 0x10)); - filepos += 2; + buf_size = bfd_bread (buf, COFF_CHECKSUM_BUFFER_SIZE, abfd); + cur_buf_size = buf_size; + cur_buf = buf; + + while (cur_buf_size > 0) + { + coff_read_word_from_buffer (cur_buf, cur_buf_size, &value, pelength); + cur_buf += 2; + cur_buf_size -= 2; + total += value; + total = 0xffff & (total + (total >> 0x10)); + } + + filepos += buf_size; } - while (more_data); + while (buf_size > 0); + + free (buf); return (0xffff & (total + (total >> 0x10))); } -- 2.30.2