merge of 0bc367fba741939c3256bd69de909e6c23067adf

and bc359776b21dfd2c5106da8610683718e2dd2875
This commit is contained in:
Ulrich Drepper
2005-08-13 22:35:15 +00:00
parent f6895046ad
commit 0f6abbbc08
2 changed files with 92 additions and 37 deletions
+7
View File
@@ -1,3 +1,10 @@
2005-08-13 Ulrich Drepper <drepper@redhat.com>
* elf_begin.c (get_shnum): Optimize memory handling. Always read from
mapped file if available. Fix access to 64-bit sh_size. Recognize
overflow.
(file_read_elf): Likewise.
2005-08-12 Roland McGrath <roland@redhat.com>
* elf32_offscn.c: Do not match empty sections at OFFSET unless
+85 -37
View File
@@ -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;
}
}
@@ -188,6 +220,7 @@ file_read_elf (int fildes, void *map_address, off_t offset, size_t maxsize,
{
/* We only read the ELF header now. */
unsigned char *e_ident;
unsigned char e_ident_mem[EI_NIDENT];
size_t scncnt;
Elf *elf;
@@ -197,9 +230,10 @@ file_read_elf (int fildes, void *map_address, off_t offset, size_t maxsize,
e_ident = (unsigned char *) map_address + offset;
else
{
e_ident = (unsigned char *) alloca (EI_NIDENT);
e_ident = e_ident_mem;
if (pread (fildes, e_ident, EI_NIDENT, offset) != EI_NIDENT)
if (TEMP_FAILURE_RETRY (pread (fildes, e_ident, EI_NIDENT, offset))
!= EI_NIDENT)
{
__libelf_seterrno (ELF_E_READ_ERROR);
return NULL;
@@ -280,14 +314,21 @@ file_read_elf (int fildes, void *map_address, off_t offset, size_t maxsize,
}
else
{
/* Read the data. */
if (pread (elf->fildes, &elf->state.elf32.ehdr_mem,
sizeof (Elf32_Ehdr), offset) != sizeof (Elf32_Ehdr))
{
/* We must be able to read the ELF header. */
__libelf_seterrno (ELF_E_INVALID_FILE);
return NULL;
}
if (likely (map_address != NULL))
/* Copy the data. */
memcpy (&elf->state.elf32.ehdr_mem,
(char *) map_address + offset, sizeof (Elf32_Ehdr));
else
/* Read the data. */
if (TEMP_FAILURE_RETRY (pread (elf->fildes,
&elf->state.elf32.ehdr_mem,
sizeof (Elf32_Ehdr), offset))
!= sizeof (Elf32_Ehdr))
{
/* We must be able to read the ELF header. */
__libelf_seterrno (ELF_E_INVALID_FILE);
return NULL;
}
if (e_ident[EI_DATA] != MY_ELFDATA)
{
@@ -365,9 +406,16 @@ file_read_elf (int fildes, void *map_address, off_t offset, size_t maxsize,
}
else
{
/* Read the data. */
if (pread (elf->fildes, &elf->state.elf64.ehdr_mem,
sizeof (Elf64_Ehdr), offset) != sizeof (Elf64_Ehdr))
if (likely (map_address != NULL))
/* Copy the data. */
memcpy (&elf->state.elf64.ehdr_mem,
(char *) map_address + offset, sizeof (Elf64_Ehdr));
else
/* Read the data. */
if (TEMP_FAILURE_RETRY (pread (elf->fildes,
&elf->state.elf64.ehdr_mem,
sizeof (Elf64_Ehdr), offset))
!= sizeof (Elf64_Ehdr))
{
/* We must be able to read the ELF header. */
__libelf_seterrno (ELF_E_INVALID_FILE);