From cc1ebdb0ed624f418102921c47f4a11181e8e99c Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sat, 13 Aug 2005 22:05:02 +0000 Subject: [PATCH] Fix elf_begin for 64-bit and optimize a bit. --- libelf/ChangeLog | 6 ++++ libelf/elf_begin.c | 80 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 62 insertions(+), 24 deletions(-) diff --git a/libelf/ChangeLog b/libelf/ChangeLog index 67d4f3951..c687539d3 100644 --- a/libelf/ChangeLog +++ b/libelf/ChangeLog @@ -1,3 +1,9 @@ +2005-08-13 Ulrich Drepper + + * elf_begin.c (get_shnum): Optimize memory handling. Always read from + mapped file if available. Fix access to 64-bit sh_size. Recognize + overflow. + 2005-08-12 Roland McGrath * elf32_offscn.c: Do not match empty sections at OFFSET unless diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c index 404cbe832..bed3f5509 100644 --- a/libelf/elf_begin.c +++ b/libelf/elf_begin.c @@ -69,6 +69,11 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset, Elf64_Ehdr *e64; void *p; } ehdr; + union + { + Elf32_Ehdr e32; + Elf64_Ehdr e64; + } ehdr_mem; bool is32 = e_ident[EI_CLASS] == ELFCLASS32; /* Make the ELF header available. */ @@ -83,11 +88,17 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset, /* We have to read the data from the file. */ size_t len = is32 ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr); - ehdr.p = alloca (len); - /* Fill it. */ - if ((size_t) pread (fildes, ehdr.p, len, offset) != len) - /* Failed reading. */ - return (size_t) -1l; + if (likely (map_address != NULL)) + ehdr.p = memcpy (&ehdr_mem, (char *) map_address + offset, len); + else + { + /* Fill it. */ + if ((size_t) TEMP_FAILURE_RETRY (pread (fildes, &ehdr_mem, len, + offset)) != len) + /* Failed reading. */ + return (size_t) -1l; + ehdr.p = &ehdr_mem; + } if (e_ident[EI_DATA] != MY_ELFDATA) { @@ -120,18 +131,27 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset, || (((size_t) ((char *) map_address + offset)) & (__alignof__ (Elf32_Ehdr) - 1)) == 0)) /* We can directly access the memory. */ - result = ((Elf32_Shdr *) ((char *) map_address - + ehdr.e32->e_shoff + result = ((Elf32_Shdr *) ((char *) map_address + ehdr.e32->e_shoff + offset))->sh_size; else { Elf32_Word size; - if (pread (fildes, &size, sizeof (Elf32_Word), - offset + ehdr.e32->e_shoff - + offsetof (Elf32_Shdr, sh_size)) - != sizeof (Elf32_Word)) - return (size_t) -1l; + if (likely (map_address != NULL)) + /* gcc will optimize the memcpy to a simple memory + access while taking care of alignment issues. */ + memcpy (&size, &((Elf32_Shdr *) ((char *) map_address + + ehdr.e32->e_shoff + + offset))->sh_size, + sizeof (Elf32_Word)); + else + if (TEMP_FAILURE_RETRY (pread (fildes, &size, + sizeof (Elf32_Word), + offset + ehdr.e32->e_shoff + + offsetof (Elf32_Shdr, + sh_size))) + != sizeof (Elf32_Word)) + return (size_t) -1l; if (e_ident[EI_DATA] != MY_ELFDATA) CONVERT (size); @@ -151,29 +171,41 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset, /* Cannot read the first section header. */ return (size_t) -1l; + Elf64_Xword size; if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA && (ALLOW_UNALIGNED || (((size_t) ((char *) map_address + offset)) & (__alignof__ (Elf64_Ehdr) - 1)) == 0)) /* We can directly access the memory. */ - result = ((Elf64_Shdr *) ((char *) map_address - + ehdr.e64->e_shoff - + offset))->sh_size; + size = ((Elf64_Shdr *) ((char *) map_address + ehdr.e64->e_shoff + + offset))->sh_size; else { - Elf64_Word size; - - if (pread (fildes, &size, sizeof (Elf64_Word), - offset + ehdr.e64->e_shoff - + offsetof (Elf64_Shdr, sh_size)) - != sizeof (Elf64_Word)) - return (size_t) -1l; + if (likely (map_address != NULL)) + /* gcc will optimize the memcpy to a simple memory + access while taking care of alignment issues. */ + memcpy (&size, &((Elf64_Shdr *) ((char *) map_address + + ehdr.e64->e_shoff + + offset))->sh_size, + sizeof (Elf64_Xword)); + else + if (TEMP_FAILURE_RETRY (pread (fildes, &size, + sizeof (Elf64_Word), + offset + ehdr.e64->e_shoff + + offsetof (Elf64_Shdr, + sh_size))) + != sizeof (Elf64_Xword)) + return (size_t) -1l; if (e_ident[EI_DATA] != MY_ELFDATA) CONVERT (size); - - result = size; } + + if (size > ~((GElf_Word) 0)) + /* Invalid value, it is too large. */ + return (size_t) -1l; + + result = size; } } -- 2.47.2