summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2008-09-30 06:35:35 +0000
committerRoland McGrath <roland@redhat.com>2008-09-30 06:35:35 +0000
commit9cf28e4f899f97ecdc983a0af8e2be62f3d69058 (patch)
treedf4ddf5910d2854a66e71081fd4753acb1ebd6d8
parentbb48a2702b6db50614fbbf08b02a1c7d83e28ecf (diff)
downloadelfutils-9cf28e4f899f97ecdc983a0af8e2be62f3d69058.tar.gz
libdwfl/
2008-09-29 Roland McGrath <roland@redhat.com> * segment.c (insert): Must realloc DWFL->lookup_module here too. (dwfl_report_segment): Clear DWFL->lookup_module before insert calls.
-rw-r--r--libdwfl/ChangeLog14
-rw-r--r--libdwfl/linux-proc-maps.c3
-rw-r--r--libdwfl/segment.c40
-rw-r--r--libelf/ChangeLog6
-rw-r--r--libelf/elf_begin.c20
-rw-r--r--libelf/libelfP.h2
6 files changed, 70 insertions, 15 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 9e54a831..e29c7d60 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,17 @@
+2008-09-29 Roland McGrath <roland@redhat.com>
+
+ * segment.c (insert): Must realloc DWFL->lookup_module here too.
+ (dwfl_report_segment): Clear DWFL->lookup_module before insert calls.
+
+2008-08-28 Roland McGrath <roland@redhat.com>
+
+ * segment.c (reify_segments): Fix last change.
+
+2008-08-27 Roland McGrath <roland@redhat.com>
+
+ * linux-proc-maps.c (read_proc_memory): Return 0 for EINVAL or EPERM
+ failure from pread64.
+
2008-08-26 Roland McGrath <roland@redhat.com>
* segment.c (reify_segments): Insert a trailing segment for a module
diff --git a/libdwfl/linux-proc-maps.c b/libdwfl/linux-proc-maps.c
index b4bb6cfc..2206f63c 100644
--- a/libdwfl/linux-proc-maps.c
+++ b/libdwfl/linux-proc-maps.c
@@ -267,6 +267,9 @@ read_proc_memory (void *arg, void *data, GElf_Addr address,
{
const int fd = *(const int *) arg;
ssize_t nread = pread64 (fd, data, maxread, (off64_t) address);
+ /* Some kernels don't actually let us do this read, ignore those errors. */
+ if (nread < 0 && (errno == EINVAL || errno == EPERM))
+ return 0;
if (nread > 0 && (size_t) nread < minread)
nread = 0;
return nread;
diff --git a/libdwfl/segment.c b/libdwfl/segment.c
index 78220e3b..cb520e64 100644
--- a/libdwfl/segment.c
+++ b/libdwfl/segment.c
@@ -83,12 +83,26 @@ insert (Dwfl *dwfl, size_t i, GElf_Addr start, GElf_Addr end, int segndx)
int *nsegndx = realloc (dwfl->lookup_segndx, sizeof nsegndx[0] * n);
if (unlikely (nsegndx == NULL))
{
- free (naddr);
+ if (naddr != dwfl->lookup_addr)
+ free (naddr);
return true;
}
dwfl->lookup_alloc = n;
dwfl->lookup_addr = naddr;
dwfl->lookup_segndx = nsegndx;
+
+ if (dwfl->lookup_module != NULL)
+ {
+ /* Make sure this array is big enough too. */
+ Dwfl_Module **old = dwfl->lookup_module;
+ dwfl->lookup_module = realloc (dwfl->lookup_module,
+ sizeof dwfl->lookup_module[0] * n);
+ if (unlikely (dwfl->lookup_module == NULL))
+ {
+ free (old);
+ return true;
+ }
+ }
}
if (unlikely (i < dwfl->lookup_elts))
@@ -175,9 +189,17 @@ reify_segments (Dwfl *dwfl)
return true;
++idx;
}
+ else if (dwfl->lookup_addr[idx] < start)
+ {
+ /* The module starts past the end of this segment.
+ Add a new one. */
+ if (unlikely (insert (dwfl, idx + 1, start, end, -1)))
+ return true;
+ ++idx;
+ }
- if (((size_t) idx + 1 == dwfl->lookup_elts
- || end < dwfl->lookup_addr[idx + 1])
+ if ((size_t) idx + 1 < dwfl->lookup_elts
+ && end < dwfl->lookup_addr[idx + 1]
/* The module ends in the middle of this segment. Split it. */
&& unlikely (insert (dwfl, idx + 1,
end, dwfl->lookup_addr[idx + 1], -1)))
@@ -261,6 +283,12 @@ dwfl_report_segment (Dwfl *dwfl, int ndx, const GElf_Phdr *phdr, GElf_Addr bias,
phdr->p_align < dwfl->segment_align))
dwfl->segment_align = phdr->p_align;
+ if (unlikely (dwfl->lookup_module != NULL))
+ {
+ free (dwfl->lookup_module);
+ dwfl->lookup_module = NULL;
+ }
+
GElf_Addr start = segment_start (dwfl, bias + phdr->p_vaddr);
GElf_Addr end = segment_end (dwfl, bias + phdr->p_vaddr + phdr->p_memsz);
@@ -289,12 +317,6 @@ dwfl_report_segment (Dwfl *dwfl, int ndx, const GElf_Phdr *phdr, GElf_Addr bias,
dwfl->lookup_tail_offset = end - bias - phdr->p_vaddr + phdr->p_offset;
dwfl->lookup_tail_ndx = ndx + 1;
- if (unlikely (dwfl->lookup_module != NULL))
- {
- free (dwfl->lookup_module);
- dwfl->lookup_module = NULL;
- }
-
return ndx;
}
INTDEF (dwfl_report_segment)
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index d258de8d..18c34fcc 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,9 @@
+2008-08-27 Roland McGrath <roland@redhat.com>
+
+ * elf_begin.c (get_shnum): Avoid misaligned reads for matching endian.
+
+ * libelfP.h [!ALLOW_UNALIGNED] (__libelf_type_align): Fix CLASS index.
+
2008-08-25 Roland McGrath <roland@redhat.com>
* Makefile.am (libelf_so_LDLIBS): New variable.
diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c
index b95b06bf..bd385306 100644
--- a/libelf/elf_begin.c
+++ b/libelf/elf_begin.c
@@ -111,7 +111,11 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset,
bool is32 = e_ident[EI_CLASS] == ELFCLASS32;
/* Make the ELF header available. */
- if (e_ident[EI_DATA] == MY_ELFDATA)
+ if (e_ident[EI_DATA] == MY_ELFDATA
+ && (ALLOW_UNALIGNED
+ || (((size_t) e_ident
+ & ((is32 ? __alignof__ (Elf32_Ehdr) : __alignof__ (Elf64_Ehdr))
+ - 1)) == 0)))
ehdr.p = e_ident;
else
{
@@ -130,8 +134,11 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset,
else
memcpy (&ehdr_mem, e_ident, sizeof (Elf32_Ehdr));
- CONVERT (ehdr_mem.e32.e_shnum);
- CONVERT (ehdr_mem.e32.e_shoff);
+ if (e_ident[EI_DATA] != MY_ELFDATA)
+ {
+ CONVERT (ehdr_mem.e32.e_shnum);
+ CONVERT (ehdr_mem.e32.e_shoff);
+ }
}
else
{
@@ -143,8 +150,11 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset,
else
memcpy (&ehdr_mem, e_ident, sizeof (Elf64_Ehdr));
- CONVERT (ehdr_mem.e64.e_shnum);
- CONVERT (ehdr_mem.e64.e_shoff);
+ if (e_ident[EI_DATA] != MY_ELFDATA)
+ {
+ CONVERT (ehdr_mem.e64.e_shnum);
+ CONVERT (ehdr_mem.e64.e_shoff);
+ }
}
}
diff --git a/libelf/libelfP.h b/libelf/libelfP.h
index 1dc331fc..4cab3f38 100644
--- a/libelf/libelfP.h
+++ b/libelf/libelfP.h
@@ -460,7 +460,7 @@ extern int __libelf_version_initialized attribute_hidden;
version, binary class, and type. */
extern const uint_fast8_t __libelf_type_aligns[EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM] attribute_hidden;
# define __libelf_type_align(class, type) \
- (__libelf_type_aligns[LIBELF_EV_IDX][class][type] ?: 1)
+ (__libelf_type_aligns[LIBELF_EV_IDX][class - 1][type] ?: 1)
#else
# define __libelf_type_align(class, type) 1
#endif