[PATCH] readelf: DW_CFA_set_loc operand is an address
by Ben Gamari
Previously this was incorrectly assumed to be an ULEB128. Hilarity
ensued.
This appears to be the case in both DWARF 3, DWARF 4, and LSB 5.
---
src/readelf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/readelf.c b/src/readelf.c
index 5f6e4ed..7c3237f 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -4971,7 +4971,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
case DW_CFA_set_loc:
if ((uint64_t) (endp - readp) < 1)
goto invalid;
- get_uleb128 (op1, readp, endp);
+ op1 = read_addr_unaligned_inc (ptr_size, dbg, readp);
op1 += vma_base;
printf (" set_loc %" PRIu64 "\n", op1 * code_align);
break;
--
2.6.2
7 years, 9 months
[PATCH] eblopenback: Warn when unable to find ebl backend
by Ben Gamari
This could have easily saved me three hours.
---
libebl/eblopenbackend.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libebl/eblopenbackend.c b/libebl/eblopenbackend.c
index b301400..662842d 100644
--- a/libebl/eblopenbackend.c
+++ b/libebl/eblopenbackend.c
@@ -376,7 +376,8 @@ openbackend (Elf *elf, const char *emulation, GElf_Half machine)
result->dlhandle = NULL;
result->elf = elf;
result->name = machines[cnt].prefix;
- fill_defaults (result);
+ fill_defaults (result);
+ fprintf(stderr, "ebl_openbackend: Failed to find backend DSO to handle machine.\n");
return result;
}
--
2.6.2
7 years, 9 months
[PATCH] readelf: Show set_loc argument as hexadecimal
by Ben Gamari
---
src/readelf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/readelf.c b/src/readelf.c
index 7c3237f..446c591 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -4973,7 +4973,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
goto invalid;
op1 = read_addr_unaligned_inc (ptr_size, dbg, readp);
op1 += vma_base;
- printf (" set_loc %" PRIu64 "\n", op1 * code_align);
+ printf (" set_loc %" PRIx64 "\n", op1 * code_align);
break;
case DW_CFA_advance_loc1:
if ((uint64_t) (endp - readp) < 1)
--
2.6.2
7 years, 9 months
[PATCH] Move nested functions in link_map.c to file scope.
by Chih-Hung Hsieh
* In libdwfl/link_map.c, nested functions check64, check32,
release_buffer, read_addrs, and consider_phdr are moved
to file scope to compile with clang.
Signed-off-by: Chih-Hung Hsieh <chh(a)google.com>
---
libdwfl/ChangeLog | 9 ++
libdwfl/link_map.c | 282 ++++++++++++++++++++++++++++++-----------------------
2 files changed, 167 insertions(+), 124 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 163a6f1..c103bc9 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,12 @@
+2015-11-17 Chih-Hung Hsieh <chh(a)google.com>
+
+ * link_map.c (auxv_format_probe): Move nested functions
+ check64 and check32 to file scope.
+ * link_map.c (report_r_debug): Move nested functions
+ release_buffer and read_addrs to file scope.
+ * link_map.c (dwfl_lnk_map_report): Move nested function
+ consider_phdr to file scope.
+
2015-11-13 Chih-Hung Hsieh <chh(a)google.com>
* gzip.c (unzip): Move nested functions to file scope.
diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c
index 13cac52..46d677a 100644
--- a/libdwfl/link_map.c
+++ b/libdwfl/link_map.c
@@ -42,64 +42,70 @@
#define PROBE_VAL64 sizeof (Elf64_Phdr)
-/* Examine an auxv data block and determine its format.
- Return true iff we figured it out. */
-static bool
-auxv_format_probe (const void *auxv, size_t size,
- uint_fast8_t *elfclass, uint_fast8_t *elfdata)
+static inline bool
+do_check64 (size_t i, const Elf64_auxv_t (*a64)[], uint_fast8_t *elfdata)
{
- const Elf32_auxv_t (*a32)[size / sizeof (Elf32_auxv_t)] = (void *) auxv;
- const Elf64_auxv_t (*a64)[size / sizeof (Elf64_auxv_t)] = (void *) auxv;
+ /* The AUXV pointer might not even be naturally aligned for 64-bit
+ data, because note payloads in a core file are not aligned. */
- inline bool check64 (size_t i)
- {
- /* The AUXV pointer might not even be naturally aligned for 64-bit
- data, because note payloads in a core file are not aligned. */
+ uint64_t type = read_8ubyte_unaligned_noncvt (&(*a64)[i].a_type);
+ uint64_t val = read_8ubyte_unaligned_noncvt (&(*a64)[i].a_un.a_val);
- uint64_t type = read_8ubyte_unaligned_noncvt (&(*a64)[i].a_type);
- uint64_t val = read_8ubyte_unaligned_noncvt (&(*a64)[i].a_un.a_val);
+ if (type == BE64 (PROBE_TYPE)
+ && val == BE64 (PROBE_VAL64))
+ {
+ *elfdata = ELFDATA2MSB;
+ return true;
+ }
- if (type == BE64 (PROBE_TYPE)
- && val == BE64 (PROBE_VAL64))
- {
- *elfdata = ELFDATA2MSB;
- return true;
- }
+ if (type == LE64 (PROBE_TYPE)
+ && val == LE64 (PROBE_VAL64))
+ {
+ *elfdata = ELFDATA2LSB;
+ return true;
+ }
- if (type == LE64 (PROBE_TYPE)
- && val == LE64 (PROBE_VAL64))
- {
- *elfdata = ELFDATA2LSB;
- return true;
- }
+ return false;
+}
- return false;
- }
+#define check64(n) do_check64 (n, a64, elfdata)
- inline bool check32 (size_t i)
- {
- /* The AUXV pointer might not even be naturally aligned for 32-bit
- data, because note payloads in a core file are not aligned. */
+static inline bool
+do_check32 (size_t i, const Elf32_auxv_t (*a32)[], uint_fast8_t *elfdata)
+{
+ /* The AUXV pointer might not even be naturally aligned for 32-bit
+ data, because note payloads in a core file are not aligned. */
- uint32_t type = read_4ubyte_unaligned_noncvt (&(*a32)[i].a_type);
- uint32_t val = read_4ubyte_unaligned_noncvt (&(*a32)[i].a_un.a_val);
+ uint32_t type = read_4ubyte_unaligned_noncvt (&(*a32)[i].a_type);
+ uint32_t val = read_4ubyte_unaligned_noncvt (&(*a32)[i].a_un.a_val);
- if (type == BE32 (PROBE_TYPE)
- && val == BE32 (PROBE_VAL32))
- {
- *elfdata = ELFDATA2MSB;
- return true;
- }
+ if (type == BE32 (PROBE_TYPE)
+ && val == BE32 (PROBE_VAL32))
+ {
+ *elfdata = ELFDATA2MSB;
+ return true;
+ }
- if (type == LE32 (PROBE_TYPE)
- && val == LE32 (PROBE_VAL32))
- {
- *elfdata = ELFDATA2LSB;
- return true;
- }
+ if (type == LE32 (PROBE_TYPE)
+ && val == LE32 (PROBE_VAL32))
+ {
+ *elfdata = ELFDATA2LSB;
+ return true;
+ }
- return false;
- }
+ return false;
+}
+
+#define check32(n) do_check32 (n, a32, elfdata)
+
+/* Examine an auxv data block and determine its format.
+ Return true iff we figured it out. */
+static bool
+auxv_format_probe (const void *auxv, size_t size,
+ uint_fast8_t *elfclass, uint_fast8_t *elfdata)
+{
+ const Elf32_auxv_t (*a32)[size / sizeof (Elf32_auxv_t)] = (void *) auxv;
+ const Elf64_auxv_t (*a64)[size / sizeof (Elf64_auxv_t)] = (void *) auxv;
for (size_t i = 0; i < size / sizeof (Elf64_auxv_t); ++i)
{
@@ -223,6 +229,80 @@ addrsize (uint_fast8_t elfclass)
return elfclass * 4;
}
+static inline int
+do_release_buffer (int result, Dwfl *dwfl,
+ void **pbuffer, size_t *pbuffer_available,
+ void *memory_callback_arg,
+ Dwfl_Memory_Callback *memory_callback)
+{
+ if (*pbuffer != NULL)
+ (void) (*memory_callback) (dwfl, -1, pbuffer, pbuffer_available, 0, 0,
+ memory_callback_arg);
+ return result;
+}
+
+#define release_buffer(result) \
+ do_release_buffer (result, dwfl, &buffer, &buffer_available, \
+ memory_callback_arg, memory_callback)
+
+static inline bool
+do_read_addrs (GElf_Addr vaddr, size_t n, GElf_Addr *addrs,
+ uint_fast8_t elfdata, GElf_Addr *pread_vaddr,
+ int elfclass, Dwfl *dwfl,
+ void **pbuffer, size_t *pbuffer_available,
+ void *memory_callback_arg,
+ Dwfl_Memory_Callback *memory_callback)
+{
+ size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read. */
+
+ /* Read a new buffer if the old one doesn't cover these words. */
+ if (*pbuffer == NULL
+ || vaddr < *pread_vaddr
+ || vaddr - *pread_vaddr + nb > *pbuffer_available)
+ {
+ do_release_buffer (0, dwfl, pbuffer, pbuffer_available,
+ memory_callback_arg, memory_callback);
+
+ *pread_vaddr = vaddr;
+ int segndx = INTUSE(dwfl_addrsegment) (dwfl, vaddr, NULL);
+ if (unlikely (segndx < 0)
+ || unlikely (! (*memory_callback) (dwfl, segndx,
+ pbuffer, pbuffer_available,
+ vaddr, nb, memory_callback_arg)))
+ return true;
+ }
+
+ Elf32_Addr (*a32)[n] = vaddr - *pread_vaddr + *pbuffer;
+ Elf64_Addr (*a64)[n] = (void *) a32;
+
+ if (elfclass == ELFCLASS32)
+ {
+ if (elfdata == ELFDATA2MSB)
+ for (size_t i = 0; i < n; ++i)
+ addrs[i] = BE32 (read_4ubyte_unaligned_noncvt (&(*a32)[i]));
+ else
+ for (size_t i = 0; i < n; ++i)
+ addrs[i] = LE32 (read_4ubyte_unaligned_noncvt (&(*a32)[i]));
+ }
+ else
+ {
+ if (elfdata == ELFDATA2MSB)
+ for (size_t i = 0; i < n; ++i)
+ addrs[i] = BE64 (read_8ubyte_unaligned_noncvt (&(*a64)[i]));
+ else
+ for (size_t i = 0; i < n; ++i)
+ addrs[i] = LE64 (read_8ubyte_unaligned_noncvt (&(*a64)[i]));
+ }
+
+ return false;
+}
+
+#define read_addrs(vaddr, n) \
+ do_read_addrs (vaddr, n, addrs, elfdata, &read_vaddr, elfclass, dwfl, \
+ &buffer, &buffer_available, \
+ memory_callback_arg, memory_callback)
+
+
/* Report a module for each struct link_map in the linked list at r_map
in the struct r_debug at R_DEBUG_VADDR. For r_debug_info description
see dwfl_link_map_report in libdwflP.h. If R_DEBUG_INFO is not NULL then no
@@ -247,59 +327,7 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
void *buffer = NULL;
size_t buffer_available = 0;
- inline int release_buffer (int result)
- {
- if (buffer != NULL)
- (void) (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0,
- memory_callback_arg);
- return result;
- }
-
GElf_Addr addrs[4];
- inline bool read_addrs (GElf_Addr vaddr, size_t n)
- {
- size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read. */
-
- /* Read a new buffer if the old one doesn't cover these words. */
- if (buffer == NULL
- || vaddr < read_vaddr
- || vaddr - read_vaddr + nb > buffer_available)
- {
- release_buffer (0);
-
- read_vaddr = vaddr;
- int segndx = INTUSE(dwfl_addrsegment) (dwfl, vaddr, NULL);
- if (unlikely (segndx < 0)
- || unlikely (! (*memory_callback) (dwfl, segndx,
- &buffer, &buffer_available,
- vaddr, nb, memory_callback_arg)))
- return true;
- }
-
- Elf32_Addr (*a32)[n] = vaddr - read_vaddr + buffer;
- Elf64_Addr (*a64)[n] = (void *) a32;
-
- if (elfclass == ELFCLASS32)
- {
- if (elfdata == ELFDATA2MSB)
- for (size_t i = 0; i < n; ++i)
- addrs[i] = BE32 (read_4ubyte_unaligned_noncvt (&(*a32)[i]));
- else
- for (size_t i = 0; i < n; ++i)
- addrs[i] = LE32 (read_4ubyte_unaligned_noncvt (&(*a32)[i]));
- }
- else
- {
- if (elfdata == ELFDATA2MSB)
- for (size_t i = 0; i < n; ++i)
- addrs[i] = BE64 (read_8ubyte_unaligned_noncvt (&(*a64)[i]));
- else
- for (size_t i = 0; i < n; ++i)
- addrs[i] = LE64 (read_8ubyte_unaligned_noncvt (&(*a64)[i]));
- }
-
- return false;
- }
if (unlikely (read_addrs (read_vaddr, 1)))
return release_buffer (-1);
@@ -684,6 +712,37 @@ find_executable (Dwfl *dwfl, GElf_Addr at_phdr, GElf_Addr at_entry,
}
+static inline bool
+do_consider_phdr (GElf_Word type, GElf_Addr vaddr, GElf_Xword filesz,
+ Dwfl *dwfl, GElf_Addr phdr, GElf_Addr *pdyn_bias,
+ GElf_Addr *pdyn_vaddr, GElf_Xword *pdyn_filesz)
+{
+ switch (type)
+ {
+ case PT_PHDR:
+ if (*pdyn_bias == (GElf_Addr) - 1
+ /* Do a sanity check on the putative address. */
+ && ((vaddr & (dwfl->segment_align - 1))
+ == (phdr & (dwfl->segment_align - 1))))
+ {
+ *pdyn_bias = phdr - vaddr;
+ return *pdyn_vaddr != 0;
+ }
+ break;
+
+ case PT_DYNAMIC:
+ *pdyn_vaddr = vaddr;
+ *pdyn_filesz = filesz;
+ return *pdyn_bias != (GElf_Addr) - 1;
+ }
+
+ return false;
+}
+
+#define consider_phdr(type, vaddr, filesz) \
+ do_consider_phdr (type, vaddr, filesz, \
+ dwfl, phdr, &dyn_bias, &dyn_vaddr, &dyn_filesz)
+
int
dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
Dwfl_Memory_Callback *memory_callback,
@@ -750,31 +809,6 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
GElf_Xword dyn_filesz = 0;
GElf_Addr dyn_bias = (GElf_Addr) -1;
- inline bool consider_phdr (GElf_Word type,
- GElf_Addr vaddr, GElf_Xword filesz)
- {
- switch (type)
- {
- case PT_PHDR:
- if (dyn_bias == (GElf_Addr) -1
- /* Do a sanity check on the putative address. */
- && ((vaddr & (dwfl->segment_align - 1))
- == (phdr & (dwfl->segment_align - 1))))
- {
- dyn_bias = phdr - vaddr;
- return dyn_vaddr != 0;
- }
- break;
-
- case PT_DYNAMIC:
- dyn_vaddr = vaddr;
- dyn_filesz = filesz;
- return dyn_bias != (GElf_Addr) -1;
- }
-
- return false;
- }
-
if (phdr != 0 && phnum != 0)
{
Dwfl_Module *phdr_mod;
--
2.6.0.rc2.230.g3dd15c0
7 years, 11 months
[PATCH] Move nested functions in linux-proc-maps.c to file scope.
by Chih-Hung Hsieh
* Move nested function 'report' to file scope to compile with clang.
Signed-off-by: Chih-Hung Hsieh <chh(a)google.com>
---
libdwfl/ChangeLog | 5 +++++
libdwfl/linux-proc-maps.c | 31 +++++++++++++++++--------------
2 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 163a6f1..8d5553c 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,8 @@
+2015-11-18 Chih-Hung Hsieh <chh(a)google.com>
+
+ * linux-proc-maps.c (proc_maps_report): Move nested function
+ 'report' to file scope.
+
2015-11-13 Chih-Hung Hsieh <chh(a)google.com>
* gzip.c (unzip): Move nested functions to file scope.
diff --git a/libdwfl/linux-proc-maps.c b/libdwfl/linux-proc-maps.c
index 2e2c8f9..9e7b2a2 100644
--- a/libdwfl/linux-proc-maps.c
+++ b/libdwfl/linux-proc-maps.c
@@ -175,6 +175,23 @@ grovel_auxv (pid_t pid, Dwfl *dwfl, GElf_Addr *sysinfo_ehdr)
return ENOEXEC;
}
+static inline bool
+do_report (Dwfl *dwfl, char **plast_file, Dwarf_Addr low, Dwarf_Addr high)
+{
+ if (*plast_file != NULL)
+ {
+ Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, *plast_file,
+ low, high);
+ free (*plast_file);
+ *plast_file = NULL;
+ if (unlikely (mod == NULL))
+ return true;
+ }
+ return false;
+}
+
+#define report() do_report(dwfl, &last_file, low, high)
+
static int
proc_maps_report (Dwfl *dwfl, FILE *f, GElf_Addr sysinfo_ehdr, pid_t pid)
{
@@ -183,20 +200,6 @@ proc_maps_report (Dwfl *dwfl, FILE *f, GElf_Addr sysinfo_ehdr, pid_t pid)
char *last_file = NULL;
Dwarf_Addr low = 0, high = 0;
- inline bool report (void)
- {
- if (last_file != NULL)
- {
- Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, last_file,
- low, high);
- free (last_file);
- last_file = NULL;
- if (unlikely (mod == NULL))
- return true;
- }
- return false;
- }
-
char *line = NULL;
size_t linesz;
ssize_t len;
--
2.6.0.rc2.230.g3dd15c0
7 years, 11 months
[PATCH] Move nested functions in core-file.c to file scope.
by Chih-Hung Hsieh
* Move nested functions 'fail', 'update_end', and 'more' to file scope.
Signed-off-by: Chih-Hung Hsieh <chh(a)google.com>
---
libdwfl/ChangeLog | 6 ++++
libdwfl/core-file.c | 94 +++++++++++++++++++++++++++++------------------------
2 files changed, 58 insertions(+), 42 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 163a6f1..0cc1ad3 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,9 @@
+2015-11-18 Chih-Hung Hsieh <chh(a)google.com>
+
+ * core-file.c (elf_begin_rand): Move nested function 'fail' to file scope.
+ * core-file.c (dwfl_elf_phdr_memory_callback): Move nested functions
+ 'update_end' and 'more' to file scope.
+
2015-11-13 Chih-Hung Hsieh <chh(a)google.com>
* gzip.c (unzip): Move nested functions to file scope.
diff --git a/libdwfl/core-file.c b/libdwfl/core-file.c
index b317eca..d54240e 100644
--- a/libdwfl/core-file.c
+++ b/libdwfl/core-file.c
@@ -39,6 +39,19 @@
#include "system.h"
+/* On failure return, we update *NEXT to point back at OFFSET. */
+static inline Elf *
+do_fail (int error, off_t *next, off_t offset)
+{
+ if (next != NULL)
+ *next = offset;
+ //__libelf_seterrno (error);
+ __libdwfl_seterrno (DWFL_E (LIBELF, error));
+ return NULL;
+}
+
+#define fail(error) do_fail (error, next, offset)
+
/* This is a prototype of what a new libelf interface might be.
This implementation is pessimal for non-mmap cases and should
be replaced by more diddling inside libelf internals. */
@@ -48,16 +61,6 @@ elf_begin_rand (Elf *parent, off_t offset, off_t size, off_t *next)
if (parent == NULL)
return NULL;
- /* On failure return, we update *NEXT to point back at OFFSET. */
- inline Elf *fail (int error)
- {
- if (next != NULL)
- *next = offset;
- //__libelf_seterrno (error);
- __libdwfl_seterrno (DWFL_E (LIBELF, error));
- return NULL;
- }
-
off_t min = (parent->kind == ELF_K_ELF ?
(parent->class == ELFCLASS32
? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr))
@@ -238,6 +241,44 @@ core_file_read_eagerly (Dwfl_Module *mod,
return cost <= MAX_EAGER_COST;
}
+static inline void
+update_end (GElf_Phdr *pphdr, const GElf_Off align,
+ GElf_Off *pend, GElf_Addr *pend_vaddr)
+{
+ *pend = (pphdr->p_offset + pphdr->p_filesz + align - 1) & -align;
+ *pend_vaddr = (pphdr->p_vaddr + pphdr->p_memsz + align - 1) & -align;
+}
+
+/* Use following contiguous segments to get towards SIZE. */
+static inline bool
+do_more (size_t size, GElf_Phdr *pphdr, const GElf_Off align,
+ Elf *elf, GElf_Off start, int *pndx,
+ GElf_Off *pend, GElf_Addr *pend_vaddr)
+{
+ while (*pend <= start || *pend - start < size)
+ {
+ if (pphdr->p_filesz < pphdr->p_memsz)
+ /* This segment is truncated, so no following one helps us. */
+ return false;
+
+ if (unlikely (gelf_getphdr (elf, (*pndx)++, pphdr) == NULL))
+ return false;
+
+ if (pphdr->p_type == PT_LOAD)
+ {
+ if (pphdr->p_offset > *pend
+ || pphdr->p_vaddr > *pend_vaddr)
+ /* It's discontiguous! */
+ return false;
+
+ update_end (pphdr, align, pend, pend_vaddr);
+ }
+ }
+ return true;
+}
+
+#define more(size) do_more (size, &phdr, align, elf, start, &ndx, &end, &end_vaddr)
+
bool
dwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx,
void **buffer, size_t *buffer_available,
@@ -270,38 +311,7 @@ dwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx,
GElf_Off end;
GElf_Addr end_vaddr;
- inline void update_end (void)
-{
- end = (phdr.p_offset + phdr.p_filesz + align - 1) & -align;
- end_vaddr = (phdr.p_vaddr + phdr.p_memsz + align - 1) & -align;
- }
-
- update_end ();
-
- /* Use following contiguous segments to get towards SIZE. */
- inline bool more (size_t size)
- {
- while (end <= start || end - start < size)
- {
- if (phdr.p_filesz < phdr.p_memsz)
- /* This segment is truncated, so no following one helps us. */
- return false;
-
- if (unlikely (gelf_getphdr (elf, ndx++, &phdr) == NULL))
- return false;
-
- if (phdr.p_type == PT_LOAD)
- {
- if (phdr.p_offset > end
- || phdr.p_vaddr > end_vaddr)
- /* It's discontiguous! */
- return false;
-
- update_end ();
- }
- }
- return true;
- }
+ update_end (&phdr, align, &end, &end_vaddr);
/* We need at least this much. */
if (! more (minread))
--
2.6.0.rc2.230.g3dd15c0
7 years, 11 months
[PATCH] Move nested functions in dwfl_module_getdwarf.c to file scope.
by Chih-Hung Hsieh
* In dwfl_module_getdwarf.c, nested functions 'consider_shdr'
and 'translate_offs' are moved to file scope to compile with clang.
Signed-off-by: Chih-Hung Hsieh <chh(a)google.com>
---
libdwfl/ChangeLog | 7 +
libdwfl/dwfl_module_getdwarf.c | 301 +++++++++++++++++++++--------------------
2 files changed, 160 insertions(+), 148 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 163a6f1..aac9e79 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,10 @@
+2015-11-16 Chih-Hung Hsieh <chh(a)google.com>
+
+ * dwfl_module_getdwarf.c (find_prelink_address_sync): Move nested
+ function 'consider_shdr' to file scope.
+ * dwfl_module_getdwarf.c (find_dynsym): Move nested function
+ 'translate_offs' to file scope.
+
2015-11-13 Chih-Hung Hsieh <chh(a)google.com>
* gzip.c (unzip): Move nested functions to file scope.
diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c
index 8483fa2..4d46d2f 100644
--- a/libdwfl/dwfl_module_getdwarf.c
+++ b/libdwfl/dwfl_module_getdwarf.c
@@ -34,6 +34,14 @@
#include "../libdw/libdwP.h" /* DWARF_E_* values are here. */
#include "../libelf/libelfP.h"
+enum {
+ i_symtab,
+ i_strtab,
+ i_hash,
+ i_gnu_hash,
+ i_max
+};
+
static inline Dwfl_Error
open_elf_file (Elf **elf, int *fd, char **name)
{
@@ -231,6 +239,24 @@ __libdwfl_getelf (Dwfl_Module *mod)
mod->main_bias = mod->e_type == ET_REL ? 0 : mod->low_addr - mod->main.vaddr;
}
+static inline void
+consider_shdr (GElf_Addr interp,
+ GElf_Word sh_type,
+ GElf_Xword sh_flags,
+ GElf_Addr sh_addr,
+ GElf_Xword sh_size,
+ GElf_Addr *phighest)
+{
+ if ((sh_flags & SHF_ALLOC)
+ && ((sh_type == SHT_PROGBITS && sh_addr != interp)
+ || sh_type == SHT_NOBITS))
+ {
+ const GElf_Addr sh_end = sh_addr + sh_size;
+ if (sh_end > *phighest)
+ *phighest = sh_end;
+ }
+}
+
/* If the main file might have been prelinked, then we need to
discover the correct synchronization address between the main and
debug files. Because of prelink's section juggling, we cannot rely
@@ -448,22 +474,6 @@ find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file)
GElf_Addr highest;
- inline void consider_shdr (GElf_Addr interp,
- GElf_Word sh_type,
- GElf_Xword sh_flags,
- GElf_Addr sh_addr,
- GElf_Xword sh_size)
- {
- if ((sh_flags & SHF_ALLOC)
- && ((sh_type == SHT_PROGBITS && sh_addr != interp)
- || sh_type == SHT_NOBITS))
- {
- const GElf_Addr sh_end = sh_addr + sh_size;
- if (sh_end > highest)
- highest = sh_end;
- }
- }
-
highest = 0;
scn = NULL;
while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL)
@@ -476,7 +486,7 @@ find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file)
return DWFL_E_LIBELF;
}
consider_shdr (main_interp, sh->sh_type, sh->sh_flags,
- sh->sh_addr, sh->sh_size);
+ sh->sh_addr, sh->sh_size, &highest);
}
if (highest > mod->main.vaddr)
{
@@ -489,7 +499,7 @@ find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file)
for (size_t i = 0; i < shnum - 1; ++i)
consider_shdr (undo_interp, (*s32)[i].sh_type,
(*s32)[i].sh_flags, (*s32)[i].sh_addr,
- (*s32)[i].sh_size);
+ (*s32)[i].sh_size, &highest);
}
else
{
@@ -497,7 +507,7 @@ find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file)
for (size_t i = 0; i < shnum - 1; ++i)
consider_shdr (undo_interp, (*s64)[i].sh_type,
(*s64)[i].sh_flags, (*s64)[i].sh_addr,
- (*s64)[i].sh_size);
+ (*s64)[i].sh_size, &highest);
}
if (highest > file->vaddr)
@@ -676,6 +686,128 @@ find_offsets (Elf *elf, GElf_Addr main_bias, size_t phnum, size_t n,
}
}
+/* Translate pointers into file offsets. ADJUST is either zero
+ in case the dynamic segment wasn't adjusted or mod->main_bias. */
+static void
+translate_offs (GElf_Addr adjust,
+ Dwfl_Module *mod, size_t phnum,
+ GElf_Addr addrs[i_max], GElf_Xword strsz,
+ GElf_Ehdr *ehdr, Elf_Data **pdata)
+{
+ GElf_Off offs[i_max] = { 0, };
+ find_offsets (mod->main.elf, adjust, phnum, i_max, addrs, offs);
+
+ /* Figure out the size of the symbol table. */
+ if (offs[i_hash] != 0)
+ {
+ /* In the original format, .hash says the size of .dynsym. */
+
+ size_t entsz = SH_ENTSIZE_HASH (ehdr);
+ *pdata = elf_getdata_rawchunk (mod->main.elf,
+ offs[i_hash] + entsz, entsz,
+ entsz == 4 ? ELF_T_WORD
+ : ELF_T_XWORD);
+ if (*pdata != NULL)
+ mod->syments = (entsz == 4
+ ? *(const GElf_Word *) (*pdata)->d_buf
+ : *(const GElf_Xword *) (*pdata)->d_buf);
+ }
+ if (offs[i_gnu_hash] != 0 && mod->syments == 0)
+ {
+ /* In the new format, we can derive it with some work. */
+
+ const struct
+ {
+ Elf32_Word nbuckets;
+ Elf32_Word symndx;
+ Elf32_Word maskwords;
+ Elf32_Word shift2;
+ } *header;
+
+ *pdata = elf_getdata_rawchunk (mod->main.elf, offs[i_gnu_hash],
+ sizeof *header, ELF_T_WORD);
+ if (*pdata != NULL)
+ {
+ header = (*pdata)->d_buf;
+ Elf32_Word nbuckets = header->nbuckets;
+ Elf32_Word symndx = header->symndx;
+ GElf_Off buckets_at = (offs[i_gnu_hash] + sizeof *header
+ + (gelf_getclass (mod->main.elf)
+ * sizeof (Elf32_Word)
+ * header->maskwords));
+
+ // elf_getdata_rawchunk takes a size_t, make sure it
+ // doesn't overflow.
+#if SIZE_MAX <= UINT32_MAX
+ if (nbuckets > SIZE_MAX / sizeof (Elf32_Word))
+ *pdata = NULL;
+ else
+#endif
+ *pdata = elf_getdata_rawchunk (mod->main.elf, buckets_at,
+ nbuckets * sizeof (Elf32_Word),
+ ELF_T_WORD);
+ if (*pdata != NULL && symndx < nbuckets)
+ {
+ const Elf32_Word *const buckets = (*pdata)->d_buf;
+ Elf32_Word maxndx = symndx;
+ for (Elf32_Word bucket = 0; bucket < nbuckets; ++bucket)
+ if (buckets[bucket] > maxndx)
+ maxndx = buckets[bucket];
+
+ GElf_Off hasharr_at = (buckets_at
+ + nbuckets * sizeof (Elf32_Word));
+ hasharr_at += (maxndx - symndx) * sizeof (Elf32_Word);
+ do
+ {
+ *pdata = elf_getdata_rawchunk (mod->main.elf,
+ hasharr_at,
+ sizeof (Elf32_Word),
+ ELF_T_WORD);
+ if (*pdata != NULL
+ && (*(const Elf32_Word *) (*pdata)->d_buf & 1u))
+ {
+ mod->syments = maxndx + 1;
+ break;
+ }
+ ++maxndx;
+ hasharr_at += sizeof (Elf32_Word);
+ } while (*pdata != NULL);
+ }
+ }
+ }
+ if (offs[i_strtab] > offs[i_symtab] && mod->syments == 0)
+ mod->syments = ((offs[i_strtab] - offs[i_symtab])
+ / gelf_fsize (mod->main.elf,
+ ELF_T_SYM, 1, EV_CURRENT));
+
+ if (mod->syments > 0)
+ {
+ mod->symdata = elf_getdata_rawchunk (mod->main.elf,
+ offs[i_symtab],
+ gelf_fsize (mod->main.elf,
+ ELF_T_SYM,
+ mod->syments,
+ EV_CURRENT),
+ ELF_T_SYM);
+ if (mod->symdata != NULL)
+ {
+ mod->symstrdata = elf_getdata_rawchunk (mod->main.elf,
+ offs[i_strtab],
+ strsz,
+ ELF_T_BYTE);
+ if (mod->symstrdata == NULL)
+ mod->symdata = NULL;
+ }
+ if (mod->symdata == NULL)
+ mod->symerr = DWFL_E (LIBELF, elf_errno ());
+ else
+ {
+ mod->symfile = &mod->main;
+ mod->symerr = DWFL_E_NOERROR;
+ }
+ }
+}
+
/* Try to find a dynamic symbol table via phdrs. */
static void
find_dynsym (Dwfl_Module *mod)
@@ -704,14 +836,6 @@ find_dynsym (Dwfl_Module *mod)
if (data == NULL)
continue;
- enum
- {
- i_symtab,
- i_strtab,
- i_hash,
- i_gnu_hash,
- i_max
- };
GElf_Addr addrs[i_max] = { 0, };
GElf_Xword strsz = 0;
size_t n = data->d_size / gelf_fsize (mod->main.elf,
@@ -752,131 +876,12 @@ find_dynsym (Dwfl_Module *mod)
break;
}
- /* Translate pointers into file offsets. ADJUST is either zero
- in case the dynamic segment wasn't adjusted or mod->main_bias. */
- void translate_offs (GElf_Addr adjust)
- {
- GElf_Off offs[i_max] = { 0, };
- find_offsets (mod->main.elf, adjust, phnum, i_max, addrs, offs);
-
- /* Figure out the size of the symbol table. */
- if (offs[i_hash] != 0)
- {
- /* In the original format, .hash says the size of .dynsym. */
-
- size_t entsz = SH_ENTSIZE_HASH (ehdr);
- data = elf_getdata_rawchunk (mod->main.elf,
- offs[i_hash] + entsz, entsz,
- entsz == 4 ? ELF_T_WORD
- : ELF_T_XWORD);
- if (data != NULL)
- mod->syments = (entsz == 4
- ? *(const GElf_Word *) data->d_buf
- : *(const GElf_Xword *) data->d_buf);
- }
- if (offs[i_gnu_hash] != 0 && mod->syments == 0)
- {
- /* In the new format, we can derive it with some work. */
-
- const struct
- {
- Elf32_Word nbuckets;
- Elf32_Word symndx;
- Elf32_Word maskwords;
- Elf32_Word shift2;
- } *header;
-
- data = elf_getdata_rawchunk (mod->main.elf, offs[i_gnu_hash],
- sizeof *header, ELF_T_WORD);
- if (data != NULL)
- {
- header = data->d_buf;
- Elf32_Word nbuckets = header->nbuckets;
- Elf32_Word symndx = header->symndx;
- GElf_Off buckets_at = (offs[i_gnu_hash] + sizeof *header
- + (gelf_getclass (mod->main.elf)
- * sizeof (Elf32_Word)
- * header->maskwords));
-
- // elf_getdata_rawchunk takes a size_t, make sure it
- // doesn't overflow.
-#if SIZE_MAX <= UINT32_MAX
- if (nbuckets > SIZE_MAX / sizeof (Elf32_Word))
- data = NULL;
- else
-#endif
- data
- = elf_getdata_rawchunk (mod->main.elf, buckets_at,
- nbuckets * sizeof (Elf32_Word),
- ELF_T_WORD);
- if (data != NULL && symndx < nbuckets)
- {
- const Elf32_Word *const buckets = data->d_buf;
- Elf32_Word maxndx = symndx;
- for (Elf32_Word bucket = 0; bucket < nbuckets; ++bucket)
- if (buckets[bucket] > maxndx)
- maxndx = buckets[bucket];
-
- GElf_Off hasharr_at = (buckets_at
- + nbuckets * sizeof (Elf32_Word));
- hasharr_at += (maxndx - symndx) * sizeof (Elf32_Word);
- do
- {
- data = elf_getdata_rawchunk (mod->main.elf,
- hasharr_at,
- sizeof (Elf32_Word),
- ELF_T_WORD);
- if (data != NULL
- && (*(const Elf32_Word *) data->d_buf & 1u))
- {
- mod->syments = maxndx + 1;
- break;
- }
- ++maxndx;
- hasharr_at += sizeof (Elf32_Word);
- } while (data != NULL);
- }
- }
- }
- if (offs[i_strtab] > offs[i_symtab] && mod->syments == 0)
- mod->syments = ((offs[i_strtab] - offs[i_symtab])
- / gelf_fsize (mod->main.elf,
- ELF_T_SYM, 1, EV_CURRENT));
-
- if (mod->syments > 0)
- {
- mod->symdata = elf_getdata_rawchunk (mod->main.elf,
- offs[i_symtab],
- gelf_fsize (mod->main.elf,
- ELF_T_SYM,
- mod->syments,
- EV_CURRENT),
- ELF_T_SYM);
- if (mod->symdata != NULL)
- {
- mod->symstrdata = elf_getdata_rawchunk (mod->main.elf,
- offs[i_strtab],
- strsz,
- ELF_T_BYTE);
- if (mod->symstrdata == NULL)
- mod->symdata = NULL;
- }
- if (mod->symdata == NULL)
- mod->symerr = DWFL_E (LIBELF, elf_errno ());
- else
- {
- mod->symfile = &mod->main;
- mod->symerr = DWFL_E_NOERROR;
- }
- }
- }
-
/* First try unadjusted, like ELF files from disk, vdso.
Then try for already adjusted dynamic section, like ELF
from remote memory. */
- translate_offs (0);
+ translate_offs (0, mod, phnum, addrs, strsz, ehdr, &data);
if (mod->symfile == NULL)
- translate_offs (mod->main_bias);
+ translate_offs (mod->main_bias, mod, phnum, addrs, strsz, ehdr, &data);
return;
}
--
2.6.0.rc2.230.g3dd15c0
7 years, 11 months
[PATCH] Move nested functions in dwfl_module_addrsym.c to file scope.
by Chih-Hung Hsieh
* Move nested functions 'same_section', 'binding_value',
'try_sym_value', and 'search_table'.
Signed-off-by: Chih-Hung Hsieh <chh(a)google.com>
---
libdwfl/ChangeLog | 6 +
libdwfl/dwfl_module_addrsym.c | 326 +++++++++++++++++++++++-------------------
2 files changed, 183 insertions(+), 149 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 163a6f1..1ce4274 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,9 @@
+2015-11-16 Chih-Hung Hsieh <chh(a)google.com>
+
+ * dwfl_module_addrsym.c (__libdwfl_addrsym): Move nested functions
+ 'same_section', 'binding_value', 'try_sym_value', and 'search_table'
+ to file scope.
+
2015-11-13 Chih-Hung Hsieh <chh(a)google.com>
* gzip.c (unzip): Move nested functions to file scope.
diff --git a/libdwfl/dwfl_module_addrsym.c b/libdwfl/dwfl_module_addrsym.c
index d205832..1aff02c 100644
--- a/libdwfl/dwfl_module_addrsym.c
+++ b/libdwfl/dwfl_module_addrsym.c
@@ -28,141 +28,136 @@
#include "libdwflP.h"
-/* Returns the name of the symbol "closest" to ADDR.
- Never returns symbols at addresses above ADDR. */
+struct search_state {
+ Dwfl_Module *mod;
+ GElf_Addr addr;
+ GElf_Sym *closest_sym;
+ bool adjust_st_value;
+ GElf_Word addr_shndx;
+ Elf *addr_symelf;
+ /* Keep track of the closest symbol we have seen so far.
+ Here we store only symbols with nonzero st_size. */
+ const char *closest_name;
+ GElf_Addr closest_value;
+ GElf_Word closest_shndx;
+ Elf *closest_elf;
+ /* Keep track of an eligible symbol with st_size == 0 as a fallback. */
+ const char *sizeless_name;
+ GElf_Sym sizeless_sym;
+ GElf_Addr sizeless_value;
+ GElf_Word sizeless_shndx;
+ Elf *sizeless_elf;
+ /* Keep track of the lowest address a relevant sizeless symbol could have. */
+ GElf_Addr min_label;
+};
-const char *
-internal_function
-__libdwfl_addrsym (Dwfl_Module *mod, GElf_Addr addr, GElf_Off *off,
- GElf_Sym *closest_sym, GElf_Word *shndxp,
- Elf **elfp, Dwarf_Addr *biasp, bool adjust_st_value)
+/* Return true iff we consider ADDR to lie in the same section as SYM. */
+static inline bool
+same_section (struct search_state *state, GElf_Addr value, Elf *symelf, GElf_Word shndx)
{
- int syments = INTUSE(dwfl_module_getsymtab) (mod);
- if (syments < 0)
- return NULL;
+ /* For absolute symbols and the like, only match exactly. */
+ if (shndx >= SHN_LORESERVE)
+ return value == state->addr;
- /* Return true iff we consider ADDR to lie in the same section as SYM. */
- GElf_Word addr_shndx = SHN_UNDEF;
- Elf *addr_symelf = NULL;
- inline bool same_section (GElf_Addr value, Elf *symelf, GElf_Word shndx)
+ /* If value might not be st_value, the shndx of the symbol might
+ not match the section of the value. Explicitly look both up. */
+ if (! state->adjust_st_value)
{
- /* For absolute symbols and the like, only match exactly. */
- if (shndx >= SHN_LORESERVE)
- return value == addr;
-
- /* If value might not be st_value, the shndx of the symbol might
- not match the section of the value. Explicitly look both up. */
- if (! adjust_st_value)
- {
- Dwarf_Addr v;
- if (addr_shndx == SHN_UNDEF)
- {
- v = addr;
- addr_shndx = __libdwfl_find_section_ndx (mod, &v);
- }
+ Dwarf_Addr v;
+ if (state->addr_shndx == SHN_UNDEF)
+ {
+ v = state->addr;
+ state->addr_shndx = __libdwfl_find_section_ndx (state->mod, &v);
+ }
- v = value;
- return addr_shndx == __libdwfl_find_section_ndx (mod, &v);
- }
-
- /* Figure out what section ADDR lies in. */
- if (addr_shndx == SHN_UNDEF || addr_symelf != symelf)
- {
- GElf_Addr mod_addr = dwfl_deadjust_st_value (mod, symelf, addr);
- Elf_Scn *scn = NULL;
- addr_shndx = SHN_ABS;
- addr_symelf = symelf;
- while ((scn = elf_nextscn (symelf, scn)) != NULL)
- {
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- if (likely (shdr != NULL)
- && mod_addr >= shdr->sh_addr
- && mod_addr < shdr->sh_addr + shdr->sh_size)
- {
- addr_shndx = elf_ndxscn (scn);
- break;
- }
- }
- }
-
- return shndx == addr_shndx && addr_symelf == symelf;
+ v = value;
+ return state->addr_shndx == __libdwfl_find_section_ndx (state->mod, &v);
}
- /* Keep track of the closest symbol we have seen so far.
- Here we store only symbols with nonzero st_size. */
- const char *closest_name = NULL;
- GElf_Addr closest_value = 0;
- GElf_Word closest_shndx = SHN_UNDEF;
- Elf *closest_elf = NULL;
+ /* Figure out what section ADDR lies in. */
+ if (state->addr_shndx == SHN_UNDEF || state->addr_symelf != symelf)
+ {
+ GElf_Addr mod_addr = dwfl_deadjust_st_value (state->mod, symelf, state->addr);
+ Elf_Scn *scn = NULL;
+ state->addr_shndx = SHN_ABS;
+ state->addr_symelf = symelf;
+ while ((scn = elf_nextscn (symelf, scn)) != NULL)
+ {
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+ if (likely (shdr != NULL)
+ && mod_addr >= shdr->sh_addr
+ && mod_addr < shdr->sh_addr + shdr->sh_size)
+ {
+ state->addr_shndx = elf_ndxscn (scn);
+ break;
+ }
+ }
+ }
- /* Keep track of an eligible symbol with st_size == 0 as a fallback. */
- const char *sizeless_name = NULL;
- GElf_Sym sizeless_sym = { 0, 0, 0, 0, 0, SHN_UNDEF };
- GElf_Addr sizeless_value = 0;
- GElf_Word sizeless_shndx = SHN_UNDEF;
- Elf *sizeless_elf = NULL;
+ return shndx == state->addr_shndx && state->addr_symelf == symelf;
+}
- /* Keep track of the lowest address a relevant sizeless symbol could have. */
- GElf_Addr min_label = 0;
+/* Return GELF_ST_BIND as higher-is-better integer. */
+static inline int
+binding_value (const GElf_Sym *symp)
+{
+ switch (GELF_ST_BIND (symp->st_info))
+ {
+ case STB_GLOBAL:
+ return 3;
+ case STB_WEAK:
+ return 2;
+ case STB_LOCAL:
+ return 1;
+ default:
+ return 0;
+ }
+}
- /* Try one symbol and associated value from the search table. */
- inline void try_sym_value (GElf_Addr value, GElf_Sym *sym,
- const char *name, GElf_Word shndx,
- Elf *elf, bool resolved)
- {
+/* Try one symbol and associated value from the search table. */
+static inline void
+try_sym_value (struct search_state *state,
+ GElf_Addr value, GElf_Sym *sym,
+ const char *name, GElf_Word shndx,
+ Elf *elf, bool resolved)
+{
/* Even if we don't choose this symbol, its existence excludes
any sizeless symbol (assembly label) that is below its upper
bound. */
- if (value + sym->st_size > min_label)
- min_label = value + sym->st_size;
+ if (value + sym->st_size > state->min_label)
+ state->min_label = value + sym->st_size;
- if (sym->st_size == 0 || addr - value < sym->st_size)
+ if (sym->st_size == 0 || state->addr - value < sym->st_size)
{
- /* Return GELF_ST_BIND as higher-is-better integer. */
- inline int binding_value (const GElf_Sym *symp)
- {
- switch (GELF_ST_BIND (symp->st_info))
- {
- case STB_GLOBAL:
- return 3;
- case STB_WEAK:
- return 2;
- case STB_LOCAL:
- return 1;
- default:
- return 0;
- }
- }
-
/* This symbol is a better candidate than the current one
if it's closer to ADDR or is global when it was local. */
- if (closest_name == NULL
- || closest_value < value
- || binding_value (closest_sym) < binding_value (sym))
+ if (state->closest_name == NULL
+ || state->closest_value < value
+ || binding_value (state->closest_sym) < binding_value (sym))
{
if (sym->st_size != 0)
{
- *closest_sym = *sym;
- closest_value = value;
- closest_shndx = shndx;
- closest_elf = elf;
- closest_name = name;
+ *state->closest_sym = *sym;
+ state->closest_value = value;
+ state->closest_shndx = shndx;
+ state->closest_elf = elf;
+ state->closest_name = name;
}
- else if (closest_name == NULL
- && value >= min_label
- && same_section (value,
- resolved ? mod->main.elf : elf, shndx))
+ else if (state->closest_name == NULL
+ && value >= state->min_label
+ && same_section (state, value,
+ resolved ? state->mod->main.elf : elf, shndx))
{
/* Handwritten assembly symbols sometimes have no
st_size. If no symbol with proper size includes
the address, we'll use the closest one that is in
the same section as ADDR. */
- sizeless_sym = *sym;
- sizeless_value = value;
- sizeless_shndx = shndx;
- sizeless_elf = elf;
- sizeless_name = name;
+ state->sizeless_sym = *sym;
+ state->sizeless_value = value;
+ state->sizeless_shndx = shndx;
+ state->sizeless_elf = elf;
+ state->sizeless_name = name;
}
}
/* When the beginning of its range is no closer,
@@ -170,26 +165,27 @@ __libdwfl_addrsym (Dwfl_Module *mod, GElf_Addr addr, GElf_Off *off,
GELF_ST_BIND preference. If all are equal prefer
the first symbol found. */
else if (sym->st_size != 0
- && closest_value == value
- && ((closest_sym->st_size > sym->st_size
- && (binding_value (closest_sym)
+ && state->closest_value == value
+ && ((state->closest_sym->st_size > sym->st_size
+ && (binding_value (state->closest_sym)
<= binding_value (sym)))
- || (closest_sym->st_size >= sym->st_size
- && (binding_value (closest_sym)
+ || (state->closest_sym->st_size >= sym->st_size
+ && (binding_value (state->closest_sym)
< binding_value (sym)))))
{
- *closest_sym = *sym;
- closest_value = value;
- closest_shndx = shndx;
- closest_elf = elf;
- closest_name = name;
+ *state->closest_sym = *sym;
+ state->closest_value = value;
+ state->closest_shndx = shndx;
+ state->closest_elf = elf;
+ state->closest_name = name;
}
}
- }
+}
- /* Look through the symbol table for a matching symbol. */
- inline void search_table (int start, int end)
- {
+/* Look through the symbol table for a matching symbol. */
+static inline void
+search_table (struct search_state *state, int start, int end)
+{
for (int i = start; i < end; ++i)
{
GElf_Sym sym;
@@ -197,32 +193,64 @@ __libdwfl_addrsym (Dwfl_Module *mod, GElf_Addr addr, GElf_Off *off,
GElf_Word shndx;
Elf *elf;
bool resolved;
- const char *name = __libdwfl_getsym (mod, i, &sym, &value,
+ const char *name = __libdwfl_getsym (state->mod, i, &sym, &value,
&shndx, &elf, NULL,
- &resolved, adjust_st_value);
+ &resolved, state->adjust_st_value);
if (name != NULL && name[0] != '\0'
&& sym.st_shndx != SHN_UNDEF
- && value <= addr
+ && value <= state->addr
&& GELF_ST_TYPE (sym.st_info) != STT_SECTION
&& GELF_ST_TYPE (sym.st_info) != STT_FILE
&& GELF_ST_TYPE (sym.st_info) != STT_TLS)
{
- try_sym_value (value, &sym, name, shndx, elf, resolved);
+ try_sym_value (state, value, &sym, name, shndx, elf, resolved);
/* If this is an addrinfo variant and the value could be
resolved then also try matching the (adjusted) st_value. */
- if (resolved && mod->e_type != ET_REL)
+ if (resolved && state->mod->e_type != ET_REL)
{
GElf_Addr adjusted_st_value;
- adjusted_st_value = dwfl_adjusted_st_value (mod, elf,
+ adjusted_st_value = dwfl_adjusted_st_value (state->mod, elf,
sym.st_value);
- if (value != adjusted_st_value && adjusted_st_value <= addr)
- try_sym_value (adjusted_st_value, &sym, name, shndx,
+ if (value != adjusted_st_value && adjusted_st_value <= state->addr)
+ try_sym_value (state, adjusted_st_value, &sym, name, shndx,
elf, false);
}
}
}
- }
+}
+
+/* Returns the name of the symbol "closest" to ADDR.
+ Never returns symbols at addresses above ADDR. */
+const char *
+internal_function
+__libdwfl_addrsym (Dwfl_Module *_mod, GElf_Addr _addr, GElf_Off *off,
+ GElf_Sym *_closest_sym, GElf_Word *shndxp,
+ Elf **elfp, Dwarf_Addr *biasp, bool _adjust_st_value)
+{
+ int syments = INTUSE(dwfl_module_getsymtab) (_mod);
+ if (syments < 0)
+ return NULL;
+
+ struct search_state state =
+ {
+ .addr = _addr,
+ .mod = _mod,
+ .closest_sym = _closest_sym,
+ .adjust_st_value = _adjust_st_value,
+ .addr_shndx = SHN_UNDEF,
+ .addr_symelf = NULL,
+ .closest_name = NULL,
+ .closest_value = 0,
+ .closest_shndx = SHN_UNDEF,
+ .closest_elf = NULL,
+ .sizeless_name = NULL,
+ .sizeless_sym = { 0, 0, 0, 0, 0, SHN_UNDEF },
+ .sizeless_value = 0,
+ .sizeless_shndx = SHN_UNDEF,
+ .sizeless_elf = NULL,
+ .min_label = 0
+ };
/* First go through global symbols. mod->first_global and
mod->aux_first_global are setup by dwfl_module_getsymtab to the
@@ -233,38 +261,38 @@ __libdwfl_addrsym (Dwfl_Module *mod, GElf_Addr addr, GElf_Off *off,
come first in the symbol table, then all globals. The zeroth,
null entry, in the auxiliary table is skipped if there is a main
table. */
- int first_global = INTUSE (dwfl_module_getsymtab_first_global) (mod);
+ int first_global = INTUSE (dwfl_module_getsymtab_first_global) (state.mod);
if (first_global < 0)
return NULL;
- search_table (first_global == 0 ? 1 : first_global, syments);
+ search_table (&state, first_global == 0 ? 1 : first_global, syments);
/* If we found nothing searching the global symbols, then try the locals.
Unless we have a global sizeless symbol that matches exactly. */
- if (closest_name == NULL && first_global > 1
- && (sizeless_name == NULL || sizeless_value != addr))
- search_table (1, first_global);
+ if (state.closest_name == NULL && first_global > 1
+ && (state.sizeless_name == NULL || state.sizeless_value != state.addr))
+ search_table (&state, 1, first_global);
/* If we found no proper sized symbol to use, fall back to the best
candidate sizeless symbol we found, if any. */
- if (closest_name == NULL
- && sizeless_name != NULL && sizeless_value >= min_label)
+ if (state.closest_name == NULL
+ && state.sizeless_name != NULL && state.sizeless_value >= state.min_label)
{
- *closest_sym = sizeless_sym;
- closest_value = sizeless_value;
- closest_shndx = sizeless_shndx;
- closest_elf = sizeless_elf;
- closest_name = sizeless_name;
+ *state.closest_sym = state.sizeless_sym;
+ state.closest_value = state.sizeless_value;
+ state.closest_shndx = state.sizeless_shndx;
+ state.closest_elf = state.sizeless_elf;
+ state.closest_name = state.sizeless_name;
}
- *off = addr - closest_value;
+ *off = state.addr - state.closest_value;
if (shndxp != NULL)
- *shndxp = closest_shndx;
+ *shndxp = state.closest_shndx;
if (elfp != NULL)
- *elfp = closest_elf;
+ *elfp = state.closest_elf;
if (biasp != NULL)
- *biasp = dwfl_adjusted_st_value (mod, closest_elf, 0);
- return closest_name;
+ *biasp = dwfl_adjusted_st_value (state.mod, state.closest_elf, 0);
+ return state.closest_name;
}
--
2.6.0.rc2.230.g3dd15c0
7 years, 11 months
[PATCH] Move nested functions in dwarf_entry_breakpoints.c to file scope.
by Chih-Hung Hsieh
No nested functions to compile with clang/llvm.
Signed-off-by: Chih-Hung Hsieh <chh(a)google.com>
---
libdw/ChangeLog | 5 ++
libdw/dwarf_entry_breakpoints.c | 110 +++++++++++++++++++++-------------------
2 files changed, 64 insertions(+), 51 deletions(-)
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 39c49aa..b91c8c7 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,8 @@
+2015-10-14 Chih-Hung Hsieh <chh(a)google.com>
+
+ * dwarf_entry_breakpoints.c (dwarf_entry_breakpoints): Move recursive
+ functions 'add_bkpt', 'entrypc_bkpt', and 'search_range' to file scope.
+
2015-10-09 Josh Stone <jistone(a)redhat.com>
* dwarf_begin.c (dwarf_begin): Replace stat64 and fstat64 with stat
diff --git a/libdw/dwarf_entry_breakpoints.c b/libdw/dwarf_entry_breakpoints.c
index abfee73..c3c0f39 100644
--- a/libdw/dwarf_entry_breakpoints.c
+++ b/libdw/dwarf_entry_breakpoints.c
@@ -34,54 +34,40 @@
#include <stdlib.h>
-int
-dwarf_entry_breakpoints (Dwarf_Die *die, Dwarf_Addr **bkpts)
+/* Add one breakpoint location to the result vector. */
+static inline int
+add_bkpt (Dwarf_Addr pc, Dwarf_Addr **bkpts, int *pnbkpts)
{
- int nbkpts = 0;
- *bkpts = NULL;
-
- /* Add one breakpoint location to the result vector. */
- inline int add_bkpt (Dwarf_Addr pc)
- {
- Dwarf_Addr *newlist = realloc (*bkpts, ++nbkpts * sizeof newlist[0]);
- if (newlist == NULL)
- {
- free (*bkpts);
- *bkpts = NULL;
- __libdw_seterrno (DWARF_E_NOMEM);
- return -1;
- }
- newlist[nbkpts - 1] = pc;
- *bkpts = newlist;
- return nbkpts;
- }
-
- /* Fallback result, break at the entrypc/lowpc value. */
- inline int entrypc_bkpt (void)
+ Dwarf_Addr *newlist = realloc (*bkpts, ++(*pnbkpts) * sizeof newlist[0]);
+ if (newlist == NULL)
{
- Dwarf_Addr pc;
- return INTUSE(dwarf_entrypc) (die, &pc) < 0 ? -1 : add_bkpt (pc);
- }
-
- /* Fetch the CU's line records to look for this DIE's addresses. */
- Dwarf_Die cudie = CUDIE (die->cu);
- Dwarf_Lines *lines;
- size_t nlines;
- if (INTUSE(dwarf_getsrclines) (&cudie, &lines, &nlines) < 0)
- {
- int error = INTUSE (dwarf_errno) ();
- if (error == 0) /* CU has no DW_AT_stmt_list. */
- return entrypc_bkpt ();
- __libdw_seterrno (error);
+ free (*bkpts);
+ *bkpts = NULL;
+ __libdw_seterrno (DWARF_E_NOMEM);
return -1;
}
+ newlist[*pnbkpts - 1] = pc;
+ *bkpts = newlist;
+ return *pnbkpts;
+}
- /* Search a contiguous PC range for prologue-end markers.
- If DWARF, look for proper markers.
- Failing that, if ADHOC, look for the ad hoc convention. */
- inline int search_range (Dwarf_Addr low, Dwarf_Addr high,
- bool dwarf, bool adhoc)
- {
+/* Fallback result, break at the entrypc/lowpc value. */
+static inline int
+entrypc_bkpt (Dwarf_Die *die, Dwarf_Addr **bkpts, int *pnbkpts)
+{
+ Dwarf_Addr pc;
+ return INTUSE(dwarf_entrypc) (die, &pc) < 0 ? -1 : add_bkpt (pc, bkpts, pnbkpts);
+}
+
+/* Search a contiguous PC range for prologue-end markers.
+ If DWARF, look for proper markers.
+ Failing that, if ADHOC, look for the ad hoc convention. */
+static inline int
+search_range (Dwarf_Addr low, Dwarf_Addr high,
+ bool dwarf, bool adhoc,
+ Dwarf_Lines *lines, size_t nlines,
+ Dwarf_Addr **bkpts, int *pnbkpts)
+{
size_t l = 0, u = nlines;
while (l < u)
{
@@ -103,16 +89,35 @@ dwarf_entry_breakpoints (Dwarf_Die *die, Dwarf_Addr **bkpts)
if (dwarf)
for (size_t i = l; i < u && lines->info[i].addr < high; ++i)
if (lines->info[i].prologue_end
- && add_bkpt (lines->info[i].addr) < 0)
+ && add_bkpt (lines->info[i].addr, bkpts, pnbkpts) < 0)
return -1;
- if (adhoc && nbkpts == 0)
+ if (adhoc && *pnbkpts == 0)
while (++l < nlines && lines->info[l].addr < high)
if (!lines->info[l].end_sequence)
- return add_bkpt (lines->info[l].addr);
- return nbkpts;
+ return add_bkpt (lines->info[l].addr, bkpts, pnbkpts);
+ return *pnbkpts;
}
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return -1;
+}
+
+int
+dwarf_entry_breakpoints (Dwarf_Die *die, Dwarf_Addr **bkpts)
+{
+ int nbkpts = 0;
+ *bkpts = NULL;
+
+ /* Fetch the CU's line records to look for this DIE's addresses. */
+ Dwarf_Die cudie = CUDIE (die->cu);
+ Dwarf_Lines *lines;
+ size_t nlines;
+ if (INTUSE(dwarf_getsrclines) (&cudie, &lines, &nlines) < 0)
+ {
+ int error = INTUSE (dwarf_errno) ();
+ if (error == 0) /* CU has no DW_AT_stmt_list. */
+ return entrypc_bkpt (die, bkpts, &nbkpts);
+ __libdw_seterrno (error);
+ return -1;
}
/* Search each contiguous address range for DWARF prologue_end markers. */
@@ -126,14 +131,16 @@ dwarf_entry_breakpoints (Dwarf_Die *die, Dwarf_Addr **bkpts)
/* Most often there is a single contiguous PC range for the DIE. */
if (offset == 1)
- return search_range (begin, end, true, true) ?: entrypc_bkpt ();
+ return search_range (begin, end, true, true, lines, nlines, bkpts, &nbkpts)
+ ?: entrypc_bkpt (die, bkpts, &nbkpts);
Dwarf_Addr lowpc = (Dwarf_Addr) -1l;
Dwarf_Addr highpc = (Dwarf_Addr) -1l;
while (offset > 0)
{
/* We have an address range entry. */
- if (search_range (begin, end, true, false) < 0)
+ if (search_range (begin, end, true, false,
+ lines, nlines, bkpts, &nbkpts) < 0)
return -1;
if (begin < lowpc)
@@ -150,6 +157,7 @@ dwarf_entry_breakpoints (Dwarf_Die *die, Dwarf_Addr **bkpts)
fall back to just using the entrypc value. */
return (nbkpts
?: (lowpc == (Dwarf_Addr) -1l ? 0
- : search_range (lowpc, highpc, false, true))
- ?: entrypc_bkpt ());
+ : search_range (lowpc, highpc, false, true,
+ lines, nlines, bkpts, &nbkpts))
+ ?: entrypc_bkpt (die, bkpts, &nbkpts));
}
--
2.6.0.rc2.230.g3dd15c0
7 years, 11 months
[PATCH] Move nested functions in libdw_visit_scopes.c to file scope.
by Chih-Hung Hsieh
* No nested functions to compile with clang/llvm.
Signed-off-by: Chih-Hung Hsieh <chh(a)google.com>
---
libdw/ChangeLog | 5 ++
libdw/libdw_visit_scopes.c | 163 +++++++++++++++++++++++++--------------------
2 files changed, 95 insertions(+), 73 deletions(-)
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 39c49aa..56ee808 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,8 @@
+2015-10-14 Chih-Hung Hsieh <chh(a)google.com>
+
+ * libdw_visit_scopes.c (__libdw_visit_scopes): Move recursive nested
+ function 'walk_children' to file scope; inline 'recurse' at its call site.
+
2015-10-09 Josh Stone <jistone(a)redhat.com>
* dwarf_begin.c (dwarf_begin): Replace stat64 and fstat64 with stat
diff --git a/libdw/libdw_visit_scopes.c b/libdw/libdw_visit_scopes.c
index 5e5c26f..9cd5bad 100644
--- a/libdw/libdw_visit_scopes.c
+++ b/libdw/libdw_visit_scopes.c
@@ -64,6 +64,22 @@ may_have_scopes (Dwarf_Die *die)
return false;
}
+struct walk_children_state {
+ /* Parameters of __libdw_visit_scopes. */
+ unsigned int depth;
+ struct Dwarf_Die_Chain *imports;
+ int (*previsit) (unsigned int depth, struct Dwarf_Die_Chain *, void *);
+ int (*postvisit) (unsigned int depth, struct Dwarf_Die_Chain *, void *);
+ void *arg;
+ /* Return value of recursive walker. */
+ int ret;
+ /* Extra local variables for the walker. */
+ struct Dwarf_Die_Chain child;
+};
+
+static inline int
+walk_children (struct walk_children_state *state);
+
int
internal_function
__libdw_visit_scopes (unsigned int depth, struct Dwarf_Die_Chain *root,
@@ -76,95 +92,96 @@ __libdw_visit_scopes (unsigned int depth, struct Dwarf_Die_Chain *root,
void *),
void *arg)
{
- struct Dwarf_Die_Chain child;
- int ret;
-
- child.parent = root;
- if ((ret = INTUSE(dwarf_child) (&root->die, &child.die)) != 0)
- return ret < 0 ? -1 : 0; // Having zero children is legal.
-
- inline int recurse (void)
+ struct walk_children_state state =
{
- return __libdw_visit_scopes (depth + 1, &child, imports,
- previsit, postvisit, arg);
- }
-
- /* Checks the given DIE hasn't been imported yet to prevent cycles. */
- inline bool imports_contains (Dwarf_Die *die)
- {
- for (struct Dwarf_Die_Chain *import = imports; import != NULL;
- import = import->parent)
- if (import->die.addr == die->addr)
- return true;
-
- return false;
- }
+ .depth = depth,
+ .imports = imports,
+ .previsit = previsit,
+ .postvisit = postvisit,
+ .arg = arg
+ };
+
+ state.child.parent = root;
+ if ((state.ret = INTUSE(dwarf_child) (&root->die, &state.child.die)) != 0)
+ return state.ret < 0 ? -1 : 0; // Having zero children is legal.
+
+ return walk_children (&state);
+}
- inline int walk_children (void)
+static inline int
+walk_children (struct walk_children_state *state)
{
- do
- {
- /* For an imported unit, it is logically as if the children of
- that unit are siblings of the other children. So don't do
- a full recursion into the imported unit, but just walk the
- children in place before moving to the next real child. */
- while (INTUSE(dwarf_tag) (&child.die) == DW_TAG_imported_unit)
- {
- Dwarf_Die orig_child_die = child.die;
- Dwarf_Attribute attr_mem;
- Dwarf_Attribute *attr = INTUSE(dwarf_attr) (&child.die,
- DW_AT_import,
- &attr_mem);
- if (INTUSE(dwarf_formref_die) (attr, &child.die) != NULL
- && INTUSE(dwarf_child) (&child.die, &child.die) == 0)
- {
- if (imports_contains (&orig_child_die))
- {
- __libdw_seterrno (DWARF_E_INVALID_DWARF);
- return -1;
- }
- struct Dwarf_Die_Chain *orig_imports = imports;
- struct Dwarf_Die_Chain import = { .die = orig_child_die,
- .parent = orig_imports };
- imports = &import;
- int result = walk_children ();
- imports = orig_imports;
- if (result != DWARF_CB_OK)
- return result;
- }
-
- /* Any "real" children left? */
- if ((ret = INTUSE(dwarf_siblingof) (&orig_child_die,
- &child.die)) != 0)
- return ret < 0 ? -1 : 0;
- };
-
- child.prune = false;
+ do
+ {
+ /* For an imported unit, it is logically as if the children of
+ that unit are siblings of the other children. So don't do
+ a full recursion into the imported unit, but just walk the
+ children in place before moving to the next real child. */
+ while (INTUSE(dwarf_tag) (&state->child.die) == DW_TAG_imported_unit)
+ {
+ Dwarf_Die orig_child_die = state->child.die;
+ Dwarf_Attribute attr_mem;
+ Dwarf_Attribute *attr = INTUSE(dwarf_attr) (&state->child.die,
+ DW_AT_import,
+ &attr_mem);
+ if (INTUSE(dwarf_formref_die) (attr, &state->child.die) != NULL
+ && INTUSE(dwarf_child) (&state->child.die, &state->child.die) == 0)
+ {
+ /* Checks the given DIE hasn't been imported yet
+ to prevent cycles. */
+ bool imported = false;
+ for (struct Dwarf_Die_Chain *import = state->imports; import != NULL;
+ import = import->parent)
+ if (import->die.addr == orig_child_die.addr)
+ {
+ imported = true;
+ break;
+ }
+ if (imported)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return -1;
+ }
+ struct Dwarf_Die_Chain *orig_imports = state->imports;
+ struct Dwarf_Die_Chain import = { .die = orig_child_die,
+ .parent = orig_imports };
+ state->imports = &import;
+ int result = walk_children (state);
+ state->imports = orig_imports;
+ if (result != DWARF_CB_OK)
+ return result;
+ }
+
+ /* Any "real" children left? */
+ if ((state->ret = INTUSE(dwarf_siblingof) (&orig_child_die,
+ &state->child.die)) != 0)
+ return state->ret < 0 ? -1 : 0;
+ };
+
+ state->child.prune = false;
/* previsit is declared NN */
- int result = (*previsit) (depth + 1, &child, arg);
+ int result = (*state->previsit) (state->depth + 1, &state->child, state->arg);
if (result != DWARF_CB_OK)
return result;
- if (!child.prune && may_have_scopes (&child.die)
- && INTUSE(dwarf_haschildren) (&child.die))
+ if (!state->child.prune && may_have_scopes (&state->child.die)
+ && INTUSE(dwarf_haschildren) (&state->child.die))
{
- result = recurse ();
+ result = __libdw_visit_scopes (state->depth + 1, &state->child, state->imports,
+ state->previsit, state->postvisit, state->arg);
if (result != DWARF_CB_OK)
return result;
}
- if (postvisit != NULL)
+ if (state->postvisit != NULL)
{
- result = (*postvisit) (depth + 1, &child, arg);
+ result = (*state->postvisit) (state->depth + 1, &state->child, state->arg);
if (result != DWARF_CB_OK)
return result;
}
- }
- while ((ret = INTUSE(dwarf_siblingof) (&child.die, &child.die)) == 0);
-
- return ret < 0 ? -1 : 0;
- }
+ }
+ while ((state->ret = INTUSE(dwarf_siblingof) (&state->child.die, &state->child.die)) == 0);
- return walk_children ();
+ return state->ret < 0 ? -1 : 0;
}
--
2.6.0.rc2.230.g3dd15c0
7 years, 11 months