On Sun, Mar 18, 2018 at 01:43:23AM +0100, Mark Wielaard wrote: > If possible use process_vm_readv to read 4K blocks instead of fetching > each word individually with ptrace. For unwinding this often means we > only have to do one process_vm_readv of the stack instead of dozens of > ptrace calls. There is one 4K cache per process, cleared whenever a > thread is detached.
It seems to work well, but the GCC undefined sanitizer (configure --enable-sanitize-undefined) found an issue in the run-backtrace-native-biarch.sh testcase (from x86_64 to i686) when reading unaligned data. To fix that don't assign to the Dwarf_Word directly when unaligned, but use memcpy (which gcc seems to inline). diff --git a/libdwfl/linux-pid-attach.c b/libdwfl/linux-pid-attach.c index ea65618f..6295e391 100644 --- a/libdwfl/linux-pid-attach.c +++ b/libdwfl/linux-pid-attach.c @@ -144,7 +144,10 @@ read_cached_memory (struct __libdwfl_pid_arg *pid_arg, if (addr >= mem_cache->addr && addr - mem_cache->addr < mem_cache->len) { d = &mem_cache->buf[addr - mem_cache->addr]; - *result = *(unsigned long *) d; + if ((((uintptr_t) d) & (sizeof (unsigned long) - 1)) == 0) + *result = *(unsigned long *) d; + else + memcpy (result, d, sizeof (unsigned long)); return true; } @@ -165,7 +168,10 @@ read_cached_memory (struct __libdwfl_pid_arg *pid_arg, mem_cache->len = res; d = &mem_cache->buf[addr - mem_cache->addr]; - *result = *((unsigned long *) d); + if ((((uintptr_t) d) & (sizeof (unsigned long) - 1)) == 0) + *result = *(unsigned long *) d; + else + memcpy (result, d, sizeof (unsigned long)); return true; } #endif /* HAVE_PROCESS_VM_READV */