From 064af42167bf4fc9aaea2702d80ce08074b889c0 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 8 Jul 2009 13:19:16 -0700 Subject: Import from old repository commit 61ef2b42a9c4ba8e1600f15bb0236765edc2ad45. --- lib/backtrace.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 lib/backtrace.c (limited to 'lib/backtrace.c') diff --git a/lib/backtrace.c b/lib/backtrace.c new file mode 100644 index 000000000..070603900 --- /dev/null +++ b/lib/backtrace.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2008, 2009 Nicira Networks. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include "backtrace.h" +#include +#include +#include +#include +#include "compiler.h" + +#define THIS_MODULE VLM_backtrace +#include "vlog.h" + +static uintptr_t UNUSED +get_max_stack(void) +{ + static const char file_name[] = "/proc/self/maps"; + char line[1024]; + int line_number; + FILE *f; + + f = fopen(file_name, "r"); + if (f == NULL) { + VLOG_WARN("opening %s failed: %s", file_name, strerror(errno)); + return -1; + } + + for (line_number = 1; fgets(line, sizeof line, f); line_number++) { + if (strstr(line, "[stack]")) { + uintptr_t end; + if (sscanf(line, "%*"SCNxPTR"-%"SCNxPTR, &end) != 1) { + VLOG_WARN("%s:%d: parse error", file_name, line_number); + continue; + } + fclose(f); + return end; + } + } + fclose(f); + + VLOG_WARN("%s: no stack found", file_name); + return -1; +} + +static uintptr_t +stack_high(void) +{ + static uintptr_t high; + if (!high) { + high = get_max_stack(); + } + return high; +} + +static uintptr_t +stack_low(void) +{ +#ifdef __i386__ + uintptr_t low; + asm("movl %%esp,%0" : "=g" (low)); + return low; +#else + /* This causes a warning in GCC that cannot be disabled, so use it only on + * non-x86. */ + int dummy; + return (uintptr_t) &dummy; +#endif +} + +static bool +in_stack(void *p) +{ + uintptr_t address = (uintptr_t) p; + return address >= stack_low() && address < stack_high(); +} + +void +backtrace_capture(struct backtrace *backtrace) +{ + void **frame; + size_t n; + + n = 0; + for (frame = __builtin_frame_address(1); + frame != NULL && in_stack(frame) && frame[0] != NULL + && n < BACKTRACE_MAX_FRAMES; + frame = frame[0]) + { + backtrace->frames[n++] = (uintptr_t) frame[1]; + } + backtrace->n_frames = n; +} -- cgit v1.2.1