Merge "Change return type of get_load_offset to bool."
diff --git a/include/libunwind-common.h b/include/libunwind-common.h
index 17cf001..f4cbc88 100644
--- a/include/libunwind-common.h
+++ b/include/libunwind-common.h
@@ -238,6 +238,7 @@
/* These routines work both for local and remote unwinding. */
+#define unw_local_access_addr_space_init UNW_OBJ(local_access_addr_space_init)
#define unw_local_addr_space UNW_OBJ(local_addr_space)
#define unw_create_addr_space UNW_OBJ(create_addr_space)
#define unw_destroy_addr_space UNW_OBJ(destroy_addr_space)
@@ -262,6 +263,7 @@
#define unw_flush_cache UNW_ARCH_OBJ(flush_cache)
#define unw_strerror UNW_ARCH_OBJ(strerror)
+extern void unw_local_access_addr_space_init (unw_addr_space_t);
extern unw_addr_space_t unw_create_addr_space (unw_accessors_t *, int);
extern void unw_destroy_addr_space (unw_addr_space_t);
extern unw_accessors_t *unw_get_accessors (unw_addr_space_t);
diff --git a/include/map_info.h b/include/map_info.h
index 4b53c32..9c50236 100644
--- a/include/map_info.h
+++ b/include/map_info.h
@@ -28,6 +28,12 @@
/* Must not conflict with PROT_{NONE,READ,WRITE}. */
#define MAP_FLAGS_DEVICE_MEM 0x8000
+enum map_create_type
+ {
+ UNW_MAP_CREATE_REMOTE,
+ UNW_MAP_CREATE_LOCAL,
+ };
+
struct map_info
{
uintptr_t start;
@@ -60,7 +66,7 @@
struct map_info *map_find_from_addr (struct map_info *, unw_word_t);
-struct map_info *map_create_list (pid_t);
+struct map_info *map_create_list (int, pid_t);
void map_destroy_list (struct map_info *);
diff --git a/src/Los-common.c b/src/Los-common.c
index c11cb7b..6341545 100644
--- a/src/Los-common.c
+++ b/src/Los-common.c
@@ -92,7 +92,7 @@
int ret_value = -1;
intrmask_t saved_mask;
- new_list = map_create_list (getpid());
+ new_list = map_create_list (UNW_MAP_CREATE_LOCAL, getpid());
map = map_find_from_addr (new_list, addr);
if (map && (expected_flags == 0 || (map->flags & expected_flags)))
{
diff --git a/src/aarch64/Ginit.c b/src/aarch64/Ginit.c
index 82be025..bbf28e8 100644
--- a/src/aarch64/Ginit.c
+++ b/src/aarch64/Ginit.c
@@ -196,6 +196,27 @@
return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp, arg);
}
+static int
+access_mem_unrestricted (unw_addr_space_t as, unw_word_t addr, unw_word_t *val,
+ int write, void *arg)
+{
+ if (write)
+ return -1;
+
+ *val = *(unw_word_t *) addr;
+ Debug (16, "mem[%lx] -> %lx\n", addr, *val);
+ return 0;
+}
+
+// This initializes just enough of the address space to call the
+// access memory function.
+PROTECTED void
+unw_local_access_addr_space_init (unw_addr_space_t as)
+{
+ memset (as, 0, sizeof (*as));
+ as->acc.access_mem = access_mem_unrestricted;
+}
+
HIDDEN void
aarch64_local_addr_space_init (void)
{
diff --git a/src/arm/Ginit.c b/src/arm/Ginit.c
index 13629e7..a382ac7 100644
--- a/src/arm/Ginit.c
+++ b/src/arm/Ginit.c
@@ -189,6 +189,27 @@
return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp, arg);
}
+static int
+access_mem_unrestricted (unw_addr_space_t as, unw_word_t addr, unw_word_t *val,
+ int write, void *arg)
+{
+ if (write)
+ return -1;
+
+ *val = *(unw_word_t *) addr;
+ Debug (16, "mem[%x] -> %x\n", addr, *val);
+ return 0;
+}
+
+// This initializes just enough of the address space to call the
+// access memory function.
+PROTECTED void
+unw_local_access_addr_space_init (unw_addr_space_t as)
+{
+ memset (as, 0, sizeof (*as));
+ as->acc.access_mem = access_mem_unrestricted;
+}
+
HIDDEN void
arm_local_addr_space_init (void)
{
diff --git a/src/mi/Lmap.c b/src/mi/Lmap.c
index 316b742..9d30fbb 100644
--- a/src/mi/Lmap.c
+++ b/src/mi/Lmap.c
@@ -67,7 +67,7 @@
lock_rdwr_wr_acquire (&local_rdwr_lock, saved_mask);
if (local_map_list_refs == 0)
{
- local_map_list = map_create_list (getpid());
+ local_map_list = map_create_list (UNW_MAP_CREATE_LOCAL, getpid());
if (local_map_list != NULL)
local_map_list_refs = 1;
else
diff --git a/src/mi/map.c b/src/mi/map.c
index f604755..b37ad14 100644
--- a/src/mi/map.c
+++ b/src/mi/map.c
@@ -41,7 +41,7 @@
PROTECTED int
unw_map_cursor_create (unw_map_cursor_t *map_cursor, pid_t pid)
{
- map_cursor->map_list = map_create_list (pid);
+ map_cursor->map_list = map_create_list (UNW_MAP_CREATE_REMOTE, pid);
return map_cursor->map_list == NULL;
}
diff --git a/src/mips/Ginit.c b/src/mips/Ginit.c
index 308c047..d7dddae 100644
--- a/src/mips/Ginit.c
+++ b/src/mips/Ginit.c
@@ -209,6 +209,27 @@
return elf_w (get_proc_name) (as, getpid (), ip, buf, buf_len, offp, arg);
}
+static int
+access_mem_unrestricted (unw_addr_space_t as, unw_word_t addr, unw_word_t *val,
+ int write, void *arg)
+{
+ if (write)
+ return -1;
+
+ *(unw_word_t *) (uintptr_t) addr = *val;
+ Debug (16, "mem[%llx] <- %llx\n", (long long) addr, (long long) *val);
+ return 0;
+}
+
+// This initializes just enough of the address space to call the
+// access memory function.
+PROTECTED void
+unw_local_access_addr_space_init (unw_addr_space_t as)
+{
+ memset (as, 0, sizeof (*as));
+ as->acc.access_mem = access_mem_unrestricted;
+}
+
HIDDEN void
mips_local_addr_space_init (void)
{
diff --git a/src/os-linux.c b/src/os-linux.c
index 0265a16..ed69813 100644
--- a/src/os-linux.c
+++ b/src/os-linux.c
@@ -27,17 +27,21 @@
#include <stdio.h>
#include "libunwind_i.h"
+#include "libunwind-ptrace.h"
#include "map_info.h"
#include "os-linux.h"
/* ANDROID support update. */
HIDDEN struct map_info *
-map_create_list (pid_t pid)
+map_create_list (int map_create_type, pid_t pid)
{
struct map_iterator mi;
unsigned long start, end, offset, flags;
struct map_info *map_list = NULL;
struct map_info *cur_map;
+ unw_addr_space_t as = NULL;
+ struct unw_addr_space local_as;
+ void* as_arg = NULL;
if (maps_init (&mi, pid) < 0)
return NULL;
@@ -74,13 +78,57 @@
&& !(cur_map->flags & MAP_FLAGS_DEVICE_MEM))
{
struct elf_image ei;
- if (elf_map_image (&ei, cur_map->path))
+ // Do not map elf for local unwinds, it's faster to read
+ // from memory directly.
+ if (map_create_type == UNW_MAP_CREATE_REMOTE
+ && elf_map_image (&ei, cur_map->path))
{
unw_word_t load_base;
if (elf_w (get_load_base) (&ei, offset, &load_base))
cur_map->load_base = load_base;
munmap (ei.u.mapped.image, ei.u.mapped.size);
}
+ else
+ {
+ // Create an address space right here with enough initialized
+ // to read data.
+ if (as == NULL)
+ {
+ if (map_create_type == UNW_MAP_CREATE_LOCAL)
+ {
+ as = &local_as;
+ unw_local_access_addr_space_init (as);
+ }
+ else
+ {
+ // For a remote unwind, create the address space
+ // and arg data the first time we need it.
+ // We'll reuse these values if we need to attempt
+ // to get elf data for another map.
+ as = unw_create_addr_space (&_UPT_accessors, 0);
+ if (as)
+ {
+ as_arg = (void*) _UPT_create (pid);
+ if (!as_arg)
+ {
+ unw_destroy_addr_space (as);
+ as = NULL;
+ }
+ }
+ }
+ }
+ if (as)
+ {
+ ei.mapped = false;
+ ei.u.memory.map = cur_map;
+ ei.u.memory.as = as;
+ ei.u.memory.as_arg = as_arg;
+ ei.valid = elf_w (valid_object_memory) (&ei);
+ unw_word_t load_base;
+ if (ei.valid && elf_w (get_load_base) (&ei, cur_map->offset, &load_base))
+ cur_map->load_base = load_base;
+ }
+ }
}
map_list = cur_map;
@@ -88,6 +136,12 @@
maps_close (&mi);
+ if (as && map_create_type == UNW_MAP_CREATE_REMOTE)
+ {
+ unw_destroy_addr_space (as);
+ _UPT_destroy (as_arg);
+ }
+
return map_list;
}
/* End of ANDROID update. */
diff --git a/src/x86/Ginit.c b/src/x86/Ginit.c
index b9da78a..0ecb6be 100644
--- a/src/x86/Ginit.c
+++ b/src/x86/Ginit.c
@@ -257,6 +257,27 @@
return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp, arg);
}
+static int
+access_mem_unrestricted (unw_addr_space_t as, unw_word_t addr, unw_word_t *val,
+ int write, void *arg)
+{
+ if (write)
+ return -1;
+
+ *val = *(unw_word_t *) addr;
+ Debug (16, "mem[%x] -> %x\n", addr, *val);
+ return 0;
+}
+
+// This initializes just enough of the address space to call the
+// access memory function.
+PROTECTED void
+unw_local_access_addr_space_init (unw_addr_space_t as)
+{
+ memset (as, 0, sizeof (*as));
+ as->acc.access_mem = access_mem_unrestricted;
+}
+
HIDDEN void
x86_local_addr_space_init (void)
{
diff --git a/src/x86_64/Ginit.c b/src/x86_64/Ginit.c
index db18485..468ca99 100644
--- a/src/x86_64/Ginit.c
+++ b/src/x86_64/Ginit.c
@@ -276,6 +276,27 @@
return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp, arg);
}
+static int
+access_mem_unrestricted (unw_addr_space_t as, unw_word_t addr, unw_word_t *val,
+ int write, void *arg)
+{
+ if (write)
+ return -1;
+
+ *val = *(unw_word_t *) addr;
+ Debug (16, "mem[%016lx] -> %lx\n", addr, *val);
+ return 0;
+}
+
+// This initializes just enough of the address space to call the
+// access memory function.
+PROTECTED void
+unw_local_access_addr_space_init (unw_addr_space_t as)
+{
+ memset (as, 0, sizeof (*as));
+ as->acc.access_mem = access_mem_unrestricted;
+}
+
HIDDEN void
x86_64_local_addr_space_init (void)
{