Fix problems in libbacktrace.
- Add a wait for stop to backtrace_test. There is a possible race condition that is exposed when using libunwind. - Fix a few calls to unwind function calls. Bug: 8410085 Change-Id: I7487d687f6d4b7b05b8a96ad1c5f7183681e5c95
This commit is contained in:
parent
61afb07b9b
commit
a16a4e10e1
|
@ -22,6 +22,7 @@
|
|||
#include <signal.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/wait.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
@ -29,6 +30,8 @@
|
|||
|
||||
#define FINISH(pid) dump_frames(&backtrace); if (pid < 0) exit(1); else return false;
|
||||
|
||||
#define WAIT_INTERVAL_USECS 1000
|
||||
|
||||
// Prototypes for functions in the test library.
|
||||
int test_level_one(int, int, int, int, bool (*)(pid_t));
|
||||
|
||||
|
@ -52,6 +55,21 @@ void dump_frames(const backtrace_t* backtrace) {
|
|||
}
|
||||
}
|
||||
|
||||
void wait_for_stop(pid_t pid, size_t max_usecs_to_wait) {
|
||||
siginfo_t si;
|
||||
size_t usecs_waited = 0;
|
||||
|
||||
while (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) < 0 && (errno == EINTR || errno == ESRCH)) {
|
||||
if (usecs_waited >= max_usecs_to_wait) {
|
||||
printf("The process did not get to a stopping point in %zu usecs.\n",
|
||||
usecs_waited);
|
||||
break;
|
||||
}
|
||||
usleep(WAIT_INTERVAL_USECS);
|
||||
usecs_waited += WAIT_INTERVAL_USECS;
|
||||
}
|
||||
}
|
||||
|
||||
bool check_frame(const backtrace_t* backtrace, size_t frame_num,
|
||||
const char* expected_name) {
|
||||
if (backtrace->frames[frame_num].proc_name == NULL) {
|
||||
|
@ -153,6 +171,10 @@ void verify_proc_test(pid_t pid, bool (*verify_func)(pid_t)) {
|
|||
kill(pid, SIGKILL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Wait up to 1 second for the process to get to a point that we can trace it.
|
||||
wait_for_stop(pid, 1000000);
|
||||
|
||||
bool pass = verify_func(pid);
|
||||
if (ptrace(PTRACE_DETACH, pid, 0, 0) != 0) {
|
||||
printf("Failed to detach from pid %d\n", pid);
|
||||
|
|
|
@ -48,6 +48,7 @@ static bool local_get_frames(backtrace_t* backtrace) {
|
|||
bool returnValue = true;
|
||||
backtrace->num_frames = 0;
|
||||
uintptr_t map_start;
|
||||
unw_word_t value;
|
||||
do {
|
||||
frame = &backtrace->frames[backtrace->num_frames];
|
||||
frame->stack_size = 0;
|
||||
|
@ -56,18 +57,21 @@ static bool local_get_frames(backtrace_t* backtrace) {
|
|||
frame->proc_name = NULL;
|
||||
frame->proc_offset = 0;
|
||||
|
||||
ret = unw_get_reg(&cursor, UNW_REG_IP, &frame->pc);
|
||||
ret = unw_get_reg(&cursor, UNW_REG_IP, &value);
|
||||
if (ret < 0) {
|
||||
ALOGW("get_frames: Failed to read IP %d\n", ret);
|
||||
returnValue = false;
|
||||
break;
|
||||
}
|
||||
ret = unw_get_reg(&cursor, UNW_REG_SP, &frame->sp);
|
||||
frame->pc = (uintptr_t)value;
|
||||
ret = unw_get_reg(&cursor, UNW_REG_SP, &value);
|
||||
if (ret < 0) {
|
||||
ALOGW("get_frames: Failed to read IP %d\n", ret);
|
||||
returnValue = false;
|
||||
break;
|
||||
}
|
||||
frame->sp = (uintptr_t)value;
|
||||
|
||||
if (backtrace->num_frames) {
|
||||
backtrace_frame_data_t* prev = &backtrace->frames[backtrace->num_frames-1];
|
||||
prev->stack_size = frame->sp - prev->sp;
|
||||
|
@ -111,8 +115,11 @@ char* local_get_proc_name(const backtrace_t* backtrace, uintptr_t pc,
|
|||
unw_context_t* context = (unw_context_t*)backtrace->private_data;
|
||||
char buf[512];
|
||||
|
||||
*offset = 0;
|
||||
unw_word_t value;
|
||||
if (unw_get_proc_name_by_ip(unw_local_addr_space, pc, buf, sizeof(buf),
|
||||
offset, context) >= 0 && buf[0] != '\0') {
|
||||
&value, context) >= 0 && buf[0] != '\0') {
|
||||
*offset = (uintptr_t)value;
|
||||
char* symbol = demangle_symbol_name(buf);
|
||||
if (!symbol) {
|
||||
symbol = strdup(buf);
|
||||
|
|
|
@ -46,6 +46,7 @@ static bool remote_get_frames(backtrace_t* backtrace) {
|
|||
bool returnValue = true;
|
||||
backtrace->num_frames = 0;
|
||||
uintptr_t map_start;
|
||||
unw_word_t value;
|
||||
do {
|
||||
frame = &backtrace->frames[backtrace->num_frames];
|
||||
frame->stack_size = 0;
|
||||
|
@ -54,18 +55,21 @@ static bool remote_get_frames(backtrace_t* backtrace) {
|
|||
frame->proc_name = NULL;
|
||||
frame->proc_offset = 0;
|
||||
|
||||
ret = unw_get_reg(&cursor, UNW_REG_IP, &frame->pc);
|
||||
ret = unw_get_reg(&cursor, UNW_REG_IP, &value);
|
||||
if (ret < 0) {
|
||||
ALOGW("remote_get_frames: Failed to read IP %d\n", ret);
|
||||
returnValue = false;
|
||||
break;
|
||||
}
|
||||
ret = unw_get_reg(&cursor, UNW_REG_SP, &frame->sp);
|
||||
frame->pc = (uintptr_t)value;
|
||||
ret = unw_get_reg(&cursor, UNW_REG_SP, &value);
|
||||
if (ret < 0) {
|
||||
ALOGW("remote_get_frames: Failed to read SP %d\n", ret);
|
||||
returnValue = false;
|
||||
break;
|
||||
}
|
||||
frame->sp = (uintptr_t)value;
|
||||
|
||||
if (backtrace->num_frames) {
|
||||
backtrace_frame_data_t* prev = &backtrace->frames[backtrace->num_frames-1];
|
||||
prev->stack_size = frame->sp - prev->sp;
|
||||
|
@ -139,8 +143,11 @@ char* remote_get_proc_name(const backtrace_t* backtrace, uintptr_t pc,
|
|||
backtrace_private_t* data = (backtrace_private_t*)backtrace->private_data;
|
||||
char buf[512];
|
||||
|
||||
if (unw_get_proc_name_by_ip(data->addr_space, pc, buf, sizeof(buf), offset,
|
||||
*offset = 0;
|
||||
unw_word_t value;
|
||||
if (unw_get_proc_name_by_ip(data->addr_space, pc, buf, sizeof(buf), &value,
|
||||
data->upt_info) >= 0 && buf[0] != '\0') {
|
||||
*offset = (uintptr_t)value;
|
||||
char* symbol = demangle_symbol_name(buf);
|
||||
if (!symbol) {
|
||||
symbol = strdup(buf);
|
||||
|
|
Loading…
Reference in New Issue