Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEugene Tarassov2011-12-02 22:08:58 -0500
committerEugene Tarassov2011-12-02 22:08:58 -0500
commit495dd83ce0aadbe78aa62d076adb1d11e50cfcff (patch)
treec4585f956f0ca55284a89f26fc0cbf580e47f223
parentf42b051a2d5fe26988d15e1d2eaaa01f9f27d62c (diff)
downloadorg.eclipse.tcf.agent-495dd83ce0aadbe78aa62d076adb1d11e50cfcff.tar.gz
org.eclipse.tcf.agent-495dd83ce0aadbe78aa62d076adb1d11e50cfcff.tar.xz
org.eclipse.tcf.agent-495dd83ce0aadbe78aa62d076adb1d11e50cfcff.zip
TCF Agent: tested and fixed handling of "debuginfo" files in Linux. Added support for GNU extensions of DWARF.
-rw-r--r--agent/agent.vcproj8
-rw-r--r--agent/machine/x86_64/tcf/cpudefs-mdep.h85
-rw-r--r--agent/system/GNU/Linux/tcf/context-linux.c5
-rw-r--r--agent/system/Windows/tcf/context-win32.c4
-rw-r--r--agent/tcf/framework/link.h8
-rw-r--r--agent/tcf/framework/myalloc.c84
-rw-r--r--agent/tcf/framework/myalloc.h3
-rw-r--r--agent/tcf/main/test.c10
-rw-r--r--agent/tcf/main/test.h4
-rw-r--r--agent/tcf/services/dwarf.h7
-rw-r--r--agent/tcf/services/dwarfcache.c41
-rw-r--r--agent/tcf/services/dwarfcache.h7
-rw-r--r--agent/tcf/services/dwarfexpr.c304
-rw-r--r--agent/tcf/services/dwarfframe.c4
-rw-r--r--agent/tcf/services/elf-loader.c278
-rw-r--r--agent/tcf/services/elf-loader.h40
-rw-r--r--agent/tcf/services/expressions.c3
-rw-r--r--agent/tcf/services/linenumbers_elf.c9
-rw-r--r--agent/tcf/services/symbols.h5
-rw-r--r--agent/tcf/services/symbols_elf.c219
-rw-r--r--agent/tcf/services/symbols_proxy.c4
-rw-r--r--agent/tcf/services/symbols_win32.c8
-rw-r--r--agent/tcf/services/tcf_elf.c193
-rw-r--r--agent/tcf/services/tcf_elf.h7
-rw-r--r--agent/tcf/services/vm.c36
-rw-r--r--server/server.vcproj8
-rw-r--r--tests/mem-leaks/agent.vcproj16
-rw-r--r--tests/mem-leaks/tcf/services/memtrace.c16
-rw-r--r--tests/test-dwarf/dwarf-test.vcproj30
-rw-r--r--tests/test-dwarf/tcf/backend/backend.c52
30 files changed, 950 insertions, 548 deletions
diff --git a/agent/agent.vcproj b/agent/agent.vcproj
index c26fb507..f941d680 100644
--- a/agent/agent.vcproj
+++ b/agent/agent.vcproj
@@ -508,6 +508,14 @@
>
</File>
<File
+ RelativePath=".\tcf\services\elf-loader.c"
+ >
+ </File>
+ <File
+ RelativePath=".\tcf\services\elf-loader.h"
+ >
+ </File>
+ <File
RelativePath=".\tcf\services\expressions.c"
>
</File>
diff --git a/agent/machine/x86_64/tcf/cpudefs-mdep.h b/agent/machine/x86_64/tcf/cpudefs-mdep.h
index 0a1ab088..2bf2492b 100644
--- a/agent/machine/x86_64/tcf/cpudefs-mdep.h
+++ b/agent/machine/x86_64/tcf/cpudefs-mdep.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -26,6 +26,10 @@
# include <tcf/system/VxWorks/context-vxworks.h>
#endif
+#if defined(_AMD64_) && !defined(__x86_64__)
+#define __x86_64__ 1
+#endif
+
#if defined(__i386__) || defined(__x86_64__)
#include <tcf/regset.h>
@@ -47,8 +51,8 @@ RegisterDefinition regs_index[] = {
{ "edi", REG_OFFSET(Edi), 4, 7, 7 },
{ "eip", REG_OFFSET(Eip), 4, 8, 8 },
{ "eflags", REG_OFFSET(EFlags), 4, 9, 9 },
- { "cs", REG_OFFSET(SegCs), 4, -1, -1 },
- { "ss", REG_OFFSET(SegSs), 4, -1, -1 },
+ { "cs", REG_OFFSET(SegCs), 2, -1, -1 },
+ { "ss", REG_OFFSET(SegSs), 2, -1, -1 },
{ "ax", REG_OFFSET(Eax), 2, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 0 },
{ "al", REG_OFFSET(Eax), 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 12 },
@@ -81,6 +85,35 @@ RegisterDefinition regs_index[] = {
{ "status", REG_OFFSET(FloatSave.StatusWord), 2, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 24 },
{ "tag", REG_OFFSET(FloatSave.TagWord), 2, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 24 },
+#elif defined(WIN32) && defined(__x86_64__)
+# define REG_SP Esp
+# define REG_BP Ebp
+# define REG_IP Eip
+ { "rax", REG_OFFSET(Rax), 8, 0, 0},
+ { "rdx", REG_OFFSET(Rdx), 8, 1, 1},
+ { "rcx", REG_OFFSET(Rcx), 8, 2, 2},
+ { "rbx", REG_OFFSET(Rbx), 8, 3, 3},
+ { "rsi", REG_OFFSET(Rsi), 8, 4, 4},
+ { "rdi", REG_OFFSET(Rdi), 8, 5, 5},
+ { "rbp", REG_OFFSET(Rbp), 8, 6, 6},
+ { "rsp", REG_OFFSET(Rsp), 8, 7, 7},
+ { "r8", REG_OFFSET(R8), 8, 8, 8},
+ { "r9", REG_OFFSET(R9), 8, 9, 9},
+ { "r10", REG_OFFSET(R10), 8, 10, 10},
+ { "r11", REG_OFFSET(R11), 8, 11, 11},
+ { "r12", REG_OFFSET(R12), 8, 12, 12},
+ { "r13", REG_OFFSET(R13), 8, 13, 13},
+ { "r14", REG_OFFSET(R14), 8, 14, 14},
+ { "r15", REG_OFFSET(R15), 8, 15, 15},
+ { "rip", REG_OFFSET(Rip), 8, 16, 16},
+ { "eflags", REG_OFFSET(EFlags), 4, 49, -1},
+ { "es", REG_OFFSET(SegEs), 2, 50, -1},
+ { "cs", REG_OFFSET(SegCs), 2, 51, -1},
+ { "ss", REG_OFFSET(SegSs), 2, 52, -1},
+ { "ds", REG_OFFSET(SegDs), 2, 53, -1},
+ { "fs", REG_OFFSET(SegFs), 2, 54, -1},
+ { "gs", REG_OFFSET(SegGs), 2, 55, -1},
+
#elif defined(__APPLE__) && defined(__i386__)
# define REG_SP __esp
# define REG_BP __ebp
@@ -156,29 +189,51 @@ RegisterDefinition regs_index[] = {
{ "r15", REG_OFFSET(r15), 8, 15, 15},
{ "rip", REG_OFFSET(rip), 8, 16, 16},
{ "eflags", REG_OFFSET(eflags), 4, 49, -1},
- { "es", REG_OFFSET(es), 4, 50, -1},
- { "cs", REG_OFFSET(cs), 4, 51, -1},
- { "ss", REG_OFFSET(ss), 4, 52, -1},
- { "ds", REG_OFFSET(ds), 4, 53, -1},
- { "fs", REG_OFFSET(fs), 4, 54, -1},
- { "gs", REG_OFFSET(gs), 4, 55, -1},
- { "fs_base", REG_OFFSET(fs_base), 4, 58, -1},
- { "gs_base", REG_OFFSET(gs_base), 4, 59, -1},
-
-#else
+ { "es", REG_OFFSET(es), 2, 50, -1},
+ { "cs", REG_OFFSET(cs), 2, 51, -1},
+ { "ss", REG_OFFSET(ss), 2, 52, -1},
+ { "ds", REG_OFFSET(ds), 2, 53, -1},
+ { "fs", REG_OFFSET(fs), 2, 54, -1},
+ { "gs", REG_OFFSET(gs), 2, 55, -1},
+ { "fs_base", REG_OFFSET(fs_base), 8, 58, -1},
+ { "gs_base", REG_OFFSET(gs_base), 8, 59, -1},
+
+#elif defined(__i386__)
# define REG_SP esp
# define REG_BP ebp
# define REG_IP eip
{ "eax", REG_OFFSET(eax), 4, 0, 0},
+ { "ebx", REG_OFFSET(ebx), 4, 3, 3},
{ "ecx", REG_OFFSET(ecx), 4, 1, 1},
{ "edx", REG_OFFSET(edx), 4, 2, 2},
- { "ebx", REG_OFFSET(ebx), 4, 3, 3},
{ "esp", REG_OFFSET(esp), 4, 4, 4},
{ "ebp", REG_OFFSET(ebp), 4, 5, 5},
{ "esi", REG_OFFSET(esi), 4, 6, 6},
{ "edi", REG_OFFSET(edi), 4, 7, 7},
{ "eip", REG_OFFSET(eip), 4, 8, 8},
{ "eflags", REG_OFFSET(eflags), 4, 9, 9},
+ { "ds", REG_OFFSET(xds), 2, -1, -1},
+ { "es", REG_OFFSET(xes), 2, -1, -1},
+ { "fs", REG_OFFSET(xfs), 2, -1, -1},
+ { "gs", REG_OFFSET(xgs), 2, -1, -1},
+ { "cs", REG_OFFSET(xcs), 2, -1, -1},
+ { "ss", REG_OFFSET(xss), 2, -1, -1},
+
+ { "ax", REG_OFFSET(eax), 2, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 0 },
+ { "al", REG_OFFSET(eax), 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 16 },
+ { "ah", REG_OFFSET(eax) + 1, 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 16 },
+
+ { "bx", REG_OFFSET(ebx), 2, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 1 },
+ { "bl", REG_OFFSET(ebx), 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 19 },
+ { "bh", REG_OFFSET(ebx) + 1, 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 19 },
+
+ { "cx", REG_OFFSET(ecx), 2, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 2 },
+ { "cl", REG_OFFSET(ecx), 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 22 },
+ { "ch", REG_OFFSET(ecx) + 1, 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 22 },
+
+ { "dx", REG_OFFSET(edx), 2, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 3 },
+ { "dl", REG_OFFSET(edx), 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 25 },
+ { "dh", REG_OFFSET(edx) + 1, 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 25 },
#endif
@@ -419,4 +474,4 @@ unsigned char BREAK_INST[] = { 0xcc };
# error "Unknown CPU"
-#endif
+#endif \ No newline at end of file
diff --git a/agent/system/GNU/Linux/tcf/context-linux.c b/agent/system/GNU/Linux/tcf/context-linux.c
index 41dcd183..eca536d1 100644
--- a/agent/system/GNU/Linux/tcf/context-linux.c
+++ b/agent/system/GNU/Linux/tcf/context-linux.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -43,6 +43,7 @@
#include <tcf/services/expressions.h>
#include <tcf/services/memorymap.h>
#include <tcf/services/runctrl.h>
+#include <tcf/services/elf-loader.h>
#include <tcf/services/tcf_elf.h>
#include <system/GNU/Linux/tcf/regset.h>
@@ -1184,4 +1185,4 @@ void init_contexts_sys_dep(void) {
}
#endif /* if ENABLE_DebugContext */
-#endif /* __linux__ */
+#endif /* __linux__ */ \ No newline at end of file
diff --git a/agent/system/Windows/tcf/context-win32.c b/agent/system/Windows/tcf/context-win32.c
index 3ed34c11..115cb984 100644
--- a/agent/system/Windows/tcf/context-win32.c
+++ b/agent/system/Windows/tcf/context-win32.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -211,7 +211,9 @@ static void get_registers(Context * ctx) {
static DWORD event_win32_context_stopped(Context * ctx) {
ContextExtensionWin32 * ext = EXT(ctx);
+#if USE_HW_BPS
DebugState * debug_state = EXT(ctx->mem)->debug_state;
+#endif
ContextAddress exception_addr = (ContextAddress)ext->suspend_reason.ExceptionRecord.ExceptionAddress;
DWORD exception_code = ext->suspend_reason.ExceptionRecord.ExceptionCode;
DWORD continue_status = DBG_CONTINUE;
diff --git a/agent/tcf/framework/link.h b/agent/tcf/framework/link.h
index 5d60da68..e47f7e5a 100644
--- a/agent/tcf/framework/link.h
+++ b/agent/tcf/framework/link.h
@@ -39,10 +39,10 @@ struct LINK {
#define list_is_empty(list) ((list)->next == (list) || (list)->next == NULL)
#define list_remove(item) { \
- LINK * l = item; \
- l->prev->next = l->next; \
- l->next->prev = l->prev; \
- l->next = l->prev = l; \
+ LINK * _l_ = item; \
+ _l_->prev->next = _l_->next; \
+ _l_->next->prev = _l_->prev; \
+ _l_->next = _l_->prev = _l_; \
}
#define list_add_first(item,list) { \
diff --git a/agent/tcf/framework/myalloc.c b/agent/tcf/framework/myalloc.c
index 12852d65..76c34133 100644
--- a/agent/tcf/framework/myalloc.c
+++ b/agent/tcf/framework/myalloc.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -20,39 +20,40 @@
#include <tcf/config.h>
#include <assert.h>
#include <string.h>
+#include <tcf/framework/link.h>
#include <tcf/framework/trace.h>
#include <tcf/framework/events.h>
#include <tcf/framework/myalloc.h>
-typedef struct TmpBuffer TmpBuffer;
-
-struct TmpBuffer {
- TmpBuffer * next;
-};
+#define ALIGNMENT (sizeof(size_t *))
+#define POOL_SIZE (0x100000 * MEM_USAGE_FACTOR)
static char * tmp_pool = NULL;
static unsigned tmp_pool_pos = 0;
static unsigned tmp_pool_max = 0;
static unsigned tmp_pool_avr = 0;
static unsigned tmp_alloc_size = 0;
-static TmpBuffer * tmp_alloc_list = NULL;
+static LINK tmp_alloc_list = TCF_LIST_INIT(tmp_alloc_list);
static int tmp_gc_posted = 0;
static void tmp_gc(void * args) {
- if (tmp_alloc_list != NULL) {
- tmp_pool_max += tmp_pool_max > tmp_alloc_size ? tmp_pool_max : tmp_alloc_size;
- tmp_pool = (char *)loc_realloc(tmp_pool, tmp_pool_max);
- while (tmp_alloc_list != NULL) {
- TmpBuffer * buf = tmp_alloc_list;
- tmp_alloc_list = buf->next;
- loc_free(buf);
+ if (!list_is_empty(&tmp_alloc_list)) {
+ if (tmp_pool_max < POOL_SIZE) {
+ tmp_pool_max += tmp_pool_max > tmp_alloc_size ? tmp_pool_max : tmp_alloc_size;
+ if (tmp_pool_max > POOL_SIZE) tmp_pool_max = POOL_SIZE;
+ tmp_pool = (char *)loc_realloc(tmp_pool, tmp_pool_max);
+ }
+ while (!list_is_empty(&tmp_alloc_list)) {
+ LINK * l = tmp_alloc_list.next;
+ list_remove(l);
+ loc_free(l);
}
}
if (tmp_pool_pos + tmp_alloc_size >= tmp_pool_avr) {
tmp_pool_avr = tmp_pool_pos + tmp_alloc_size;
}
- else if (tmp_pool_avr > 0) {
- tmp_pool_avr--;
+ else if (tmp_pool_avr > POOL_SIZE / 100) {
+ tmp_pool_avr -= POOL_SIZE / 100;
}
if (tmp_pool_avr < tmp_pool_max / 4) {
tmp_pool_max /= 2;
@@ -70,24 +71,49 @@ void * tmp_alloc(size_t size) {
post_event(tmp_gc, NULL);
tmp_gc_posted = 1;
}
- if (tmp_pool_pos + size <= tmp_pool_max) {
+ if (tmp_pool_pos + size + ALIGNMENT + sizeof(size_t *) <= tmp_pool_max) {
+ tmp_pool_pos += sizeof(size_t *);
+ tmp_pool_pos = (tmp_pool_pos + ALIGNMENT - 1) & ~(ALIGNMENT - 1);
p = tmp_pool + tmp_pool_pos;
- tmp_pool_pos += (size + 7) & ~7u;
+ *((size_t *)p - 1) = size;
+ tmp_pool_pos += size;
}
else {
- TmpBuffer * buf = (TmpBuffer *)loc_alloc(sizeof(TmpBuffer) + size);
- buf->next = tmp_alloc_list;
- tmp_alloc_list = buf;
+ LINK * l = (LINK *)loc_alloc(sizeof(LINK) + size);
+ list_add_last(l, &tmp_alloc_list);
tmp_alloc_size += size;
- p = buf + 1;
+ p = l + 1;
}
return p;
}
void * tmp_alloc_zero(size_t size) {
- void * p = tmp_alloc(size);
- memset(p, 0, size);
- return p;
+ return memset(tmp_alloc(size), 0, size);
+}
+
+void * tmp_realloc(void * ptr, size_t size) {
+ if (ptr == NULL) return tmp_alloc(size);
+ if ((char *)ptr >= tmp_pool && (char *)ptr <= tmp_pool + tmp_pool_max) {
+ size_t m = *((size_t *)ptr - 1);
+ unsigned pos = tmp_pool_pos - m;
+ if (ptr == tmp_pool + pos && pos + size <= tmp_pool_max) {
+ tmp_pool_pos = pos + size;
+ *((size_t *)ptr - 1) = size;
+ }
+ else {
+ void * p = tmp_alloc(size);
+ if (m > size) m = size;
+ ptr = memcpy(p, ptr, m);
+ }
+ }
+ else {
+ LINK * l = (LINK *)ptr - 1;
+ list_remove(l);
+ l = (LINK *)loc_realloc(l, sizeof(LINK) + size);
+ list_add_last(l, &tmp_alloc_list);
+ ptr = l + 1;
+ }
+ return ptr;
}
void * loc_alloc(size_t size) {
@@ -107,9 +133,7 @@ void * loc_alloc(size_t size) {
void * loc_alloc_zero(size_t size) {
void * p;
- if (size == 0) {
- size = 1;
- }
+ if (size == 0) size = 1;
if ((p = malloc(size)) == NULL) {
perror("malloc");
exit(1);
@@ -122,9 +146,7 @@ void * loc_alloc_zero(size_t size) {
void * loc_realloc(void * ptr, size_t size) {
void * p;
- if (size == 0) {
- size = 1;
- }
+ if (size == 0) size = 1;
if ((p = realloc(ptr, size)) == NULL) {
perror("realloc");
exit(1);
diff --git a/agent/tcf/framework/myalloc.h b/agent/tcf/framework/myalloc.h
index ffb42f1a..847d31fe 100644
--- a/agent/tcf/framework/myalloc.h
+++ b/agent/tcf/framework/myalloc.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -37,5 +37,6 @@ extern void loc_free(const void * p);
*/
extern void * tmp_alloc(size_t size);
extern void * tmp_alloc_zero(size_t size);
+extern void * tmp_realloc(void * ptr, size_t size);
#endif /* D_myalloc */
diff --git a/agent/tcf/main/test.c b/agent/tcf/main/test.c
index 4b236850..77ac3d8a 100644
--- a/agent/tcf/main/test.c
+++ b/agent/tcf/main/test.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -106,12 +106,16 @@ int tcf_test_func2(void) {
int func2_local1 = 1;
int func2_local2 = 2;
test_struct func2_local3 = { enum_val3, 153, NULL, 3.14f, 2.71 };
+ int * func2_local4 = NULL;
+
func2_local3.f_struct = &func2_local3;
tcf_test_short++;
+ errno = tcf_test_short;
+ func2_local4 = &errno;
tcf_test_func3();
func2_local1++;
func2_local2 = func2_local1;
- return func2_local2;
+ return func2_local2 + *func2_local4;
}
void tcf_test_func1(void) {
@@ -161,7 +165,7 @@ void test_proc(void) {
}
}
-int find_test_symbol(Context * ctx, char * name, void ** addr, int * sym_class) {
+int find_test_symbol(Context * ctx, const char * name, void ** addr, int * sym_class) {
/* This code allows to run TCF diagnostic tests when symbols info is not available */
if (is_test_process(ctx) && strncmp(name, "tcf_test_", 9) == 0) {
*addr = NULL;
diff --git a/agent/tcf/main/test.h b/agent/tcf/main/test.h
index 25af613a..48c36aa0 100644
--- a/agent/tcf/main/test.h
+++ b/agent/tcf/main/test.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -29,7 +29,7 @@
extern void test_proc(void);
extern int run_test_process(ContextAttachCallBack * done, void * data);
-extern int find_test_symbol(Context * ctx, char * name, void ** addr, int * sym_class);
+extern int find_test_symbol(Context * ctx, const char * name, void ** addr, int * sym_class);
#else /* ENABLE_RCBP_TEST */
diff --git a/agent/tcf/services/dwarf.h b/agent/tcf/services/dwarf.h
index 142d76c8..677a2377 100644
--- a/agent/tcf/services/dwarf.h
+++ b/agent/tcf/services/dwarf.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 1996, 2010 Wind River Systems, Inc. and others.
+ * Copyright (c) 1996, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -383,6 +383,11 @@
#define OP_stack_value 0x9f /* v4 */
#define OP_lo_user 0xe0
#define OP_hi_user 0xff
+/* GCC extensions */
+#define OP_GNU_push_tls_address 0xe0
+#define OP_GNU_uninit 0xf0
+#define OP_GNU_encoded_addr 0xf1
+#define OP_GNU_implicit_pointer 0xf2
#define FT_char 0x0001
#define FT_signed_char 0x0002
diff --git a/agent/tcf/services/dwarfcache.c b/agent/tcf/services/dwarfcache.c
index 2fa9d063..869ce7d5 100644
--- a/agent/tcf/services/dwarfcache.c
+++ b/agent/tcf/services/dwarfcache.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -674,6 +674,34 @@ static void load_pub_names(ELF_Section * debug_info, ELF_Section * pub_names, Pu
dio_ExitSection();
}
+static void create_pub_names(ELF_Section * debug_info, PubNamesTable * tbl) {
+ ObjectInfo * unit = sCache->mCompUnits;
+ tbl->mMax = (unsigned)(debug_info->size / 256) + 16;
+ tbl->mHash = (unsigned *)loc_alloc_zero(sizeof(unsigned) * SYM_HASH_SIZE);
+ tbl->mNext = (PubNamesInfo *)loc_alloc(sizeof(PubNamesInfo) * tbl->mMax);
+ memset(tbl->mNext + tbl->mCnt++, 0, sizeof(PubNamesInfo));
+ while (unit != NULL) {
+ ObjectInfo * obj = unit->mChildren;
+ while (obj != NULL) {
+ if (obj->mFlags & DOIF_external) {
+ unsigned h;
+ PubNamesInfo * info = NULL;
+ if (tbl->mCnt >= tbl->mMax) {
+ tbl->mMax = tbl->mMax * 3 / 2;
+ tbl->mNext = (PubNamesInfo *)loc_realloc(tbl->mNext, sizeof(PubNamesInfo) * tbl->mMax);
+ }
+ info = tbl->mNext + tbl->mCnt;
+ h = calc_symbol_name_hash(obj->mName);
+ info->mID = obj->mID;
+ info->mNext = tbl->mHash[h];
+ tbl->mHash[h] = tbl->mCnt++;
+ }
+ obj = obj->mSibling;
+ }
+ unit = unit->mSibling;
+ }
+}
+
static void load_debug_sections(void) {
Trap trap;
unsigned idx;
@@ -736,6 +764,7 @@ static void load_debug_sections(void) {
if (debug_info) {
if (pub_names) load_pub_names(debug_info, pub_names, &sCache->mPubNames);
+ else create_pub_names(debug_info, &sCache->mPubNames);
if (pub_types) load_pub_names(debug_info, pub_types, &sCache->mPubTypes);
}
@@ -1032,6 +1061,14 @@ static void free_dwarf_cache(ELF_File * file) {
}
}
+ELF_File * get_dwarf_file(ELF_File * file) {
+ if (file->debug_info_file_name != NULL && !file->debug_info_file) {
+ ELF_File * debug = elf_open(file->debug_info_file_name);
+ if (debug != NULL) return debug;
+ }
+ return file;
+}
+
DWARFCache * get_dwarf_cache(ELF_File * file) {
DWARFCache * Cache = (DWARFCache *)file->dwarf_dt_cache;
if (Cache == NULL) {
@@ -1251,7 +1288,7 @@ static void load_line_numbers_v2(CompUnit * Unit, U8_T unit_size, int dwarf64) {
}
break;
case DW_LNE_set_discriminator:
- state.mDiscriminator = dio_ReadULEB128();
+ state.mDiscriminator = (U1_T)dio_ReadULEB128();
break;
default:
dio_Skip(op_size - 1);
diff --git a/agent/tcf/services/dwarfcache.h b/agent/tcf/services/dwarfcache.h
index 6797b9ac..2983ab37 100644
--- a/agent/tcf/services/dwarfcache.h
+++ b/agent/tcf/services/dwarfcache.h
@@ -248,6 +248,13 @@ struct DWARFCache {
FileInfo ** mFileInfoHash;
};
+/*
+ * Return ELF file that contains DWARF info for given file.
+ * On some systems, DWARF is kept in a separate file.
+ * If such file is not available, return 'file'.
+ */
+extern ELF_File * get_dwarf_file(ELF_File * file);
+
/* Return DWARF cache for given file, create and populate the cache if needed, throw an exception if error */
extern DWARFCache * get_dwarf_cache(ELF_File * file);
diff --git a/agent/tcf/services/dwarfexpr.c b/agent/tcf/services/dwarfexpr.c
index 016af6ac..a6c161e9 100644
--- a/agent/tcf/services/dwarfexpr.c
+++ b/agent/tcf/services/dwarfexpr.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2008, 2010 Wind River Systems, Inc. and others.
+ * Copyright (c) 2008, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -32,59 +32,27 @@
#include <tcf/services/dwarfio.h>
#include <tcf/services/dwarfexpr.h>
#include <tcf/services/stacktrace.h>
+#include <tcf/services/elf-loader.h>
#include <tcf/services/vm.h>
-typedef struct ValuePieces {
- U4_T mCnt;
- U4_T mMax;
- PropertyValuePiece * mArray;
- struct ValuePieces * mNext;
-} ValuePieces;
-
-static VMState sState;
+static VMState * sState = NULL;
static ELF_Section * sSection = NULL;
static U8_T sSectionOffs = 0;
static PropertyValue * sValue = NULL;
-static ValuePieces * sValuePieces = NULL;
-
-static ValuePieces * sFreeValuePieces = NULL;
-static ValuePieces * sBusyValuePieces = NULL;
-static unsigned sValuePiecesCnt = 0;
-static int sValuePiecesPosted = 0;
-
-static void free_value_pieces(void * args) {
- while (sBusyValuePieces != NULL) {
- ValuePieces * Pieces = sBusyValuePieces;
- sBusyValuePieces = Pieces->mNext;
- Pieces->mNext = sFreeValuePieces;
- sFreeValuePieces = Pieces;
- }
- while (sFreeValuePieces != NULL && sValuePiecesCnt > 16) {
- ValuePieces * Pieces = sFreeValuePieces;
- sFreeValuePieces = sFreeValuePieces->mNext;
- sValuePiecesCnt--;
- loc_free(Pieces->mArray);
- loc_free(Pieces);
- }
-}
-
-static ValuePieces * alloc_value_pieces(void) {
- ValuePieces * Pieces = sFreeValuePieces;
- if (Pieces == NULL) {
- Pieces = (ValuePieces *)loc_alloc_zero(sizeof(ValuePieces));
- sValuePiecesCnt++;
- }
- else {
- sFreeValuePieces = sFreeValuePieces->mNext;
- }
- Pieces->mNext = sBusyValuePieces;
- sBusyValuePieces = Pieces;
- if (!sValuePiecesPosted && sValuePiecesCnt > 8) {
- post_event(free_value_pieces, NULL);
- sValuePiecesPosted = 1;
+static PropertyValuePiece * sValuePieces = NULL;
+static U4_T sValuePiecesCnt = 0;
+static U4_T sValuePiecesMax = 0;
+
+static PropertyValuePiece * add_piece(void) {
+ PropertyValuePiece * Piece;
+ if (sValuePiecesCnt >= sValuePiecesMax) {
+ sValuePiecesMax += 8;
+ sValuePieces = (PropertyValuePiece *)tmp_realloc(sValuePieces,
+ sizeof(PropertyValuePiece) * sValuePiecesMax);
}
- Pieces->mCnt = 0;
- return Pieces;
+ Piece = sValuePieces + sValuePiecesCnt++;
+ memset(Piece, 0, sizeof(PropertyValuePiece));
+ return Piece;
}
static StackFrame * get_stack_frame(PropertyValue * sValue) {
@@ -115,7 +83,7 @@ static U8_T read_address(void) {
CompUnit * Unit = sValue->mObject->mCompUnit;
addr = dio_ReadAddress(&section);
- addr = elf_map_to_run_time_address(sState.ctx, Unit->mFile, section, (ContextAddress)addr);
+ addr = elf_map_to_run_time_address(sState->ctx, Unit->mFile, section, (ContextAddress)addr);
if (addr == 0) str_exception(ERR_INV_ADDRESS, "Object has no RT address");
return addr;
}
@@ -128,29 +96,7 @@ static U8_T get_fbreg(void) {
if (Parent == NULL) str_exception(ERR_INV_DWARF, "OP_fbreg: no parent function");
memset(&FP, 0, sizeof(FP));
-
- {
- PropertyValue * OrgValue = sValue;
- ValuePieces * OrgValuePieces = sValuePieces;
- ELF_Section * OrgSection = sSection;
- U8_T OrgSectionOffs = sSectionOffs;
- VMState OrgState = sState;
-
- read_and_evaluate_dwarf_object_property(sState.ctx, sState.stack_frame, 0, Parent, AT_frame_base, &FP);
-
- assert(sState.ctx == OrgState.ctx);
- assert(sState.addr_size == OrgState.addr_size);
- assert(sState.big_endian == OrgState.big_endian);
-
- sState.code = OrgState.code;
- sState.code_pos = OrgState.code_pos;
- sState.code_len = OrgState.code_len;
- sState.object_address = OrgState.object_address;
- sSectionOffs = OrgSectionOffs;
- sSection = OrgSection;
- sValuePieces = OrgValuePieces;
- sValue = OrgValue;
- }
+ read_and_evaluate_dwarf_object_property(sState->ctx, sState->stack_frame, 0, Parent, AT_frame_base, &FP);
if (FP.mRegister != NULL) {
if (read_reg_value(get_stack_frame(&FP), FP.mRegister, &addr) < 0) exception(errno);
@@ -158,70 +104,141 @@ static U8_T get_fbreg(void) {
else {
addr = get_numeric_property_value(&FP);
}
- dio_EnterSection(&Unit->mDesc, sSection, sSectionOffs + sState.code_pos);
+ dio_EnterSection(&Unit->mDesc, sSection, sSectionOffs + sState->code_pos);
return addr + dio_ReadS8LEB128();
}
+static U8_T evaluate_tls_address(U8_T Offset) {
+ U8_T addr = 0;
+ CompUnit * Unit = sValue->mObject->mCompUnit;
+ U8_T DioPos = dio_GetPos();
+
+ if (!context_has_state(sState->ctx)) str_exception(ERR_INV_CONTEXT,
+ "Thread local variable, but context is not a thread");
+
+ addr = get_tls_address(sState->ctx, Unit->mFile) + Offset;
+
+ dio_EnterSection(&Unit->mDesc, sSection, DioPos);
+ return addr;
+}
+
+static void evaluate_implicit_pointer(void) {
+ PropertyValue FP;
+ CompUnit * Unit = sValue->mObject->mCompUnit;
+ ObjectInfo * Info = find_object(get_dwarf_cache(Unit->mFile), dio_ReadU4());
+ U4_T Offset = dio_ReadULEB128();
+ U8_T DioPos = dio_GetPos();
+ if (Info == NULL) str_exception(ERR_INV_DWARF, "OP_GNU_implicit_pointer: invalid object reference");
+ memset(&FP, 0, sizeof(FP));
+ read_and_evaluate_dwarf_object_property(sState->ctx, sState->stack_frame, 0, Info, sValue->mAttr, &FP);
+ if (FP.mPieces != NULL) {
+ U4_T Cnt = 0;
+ U4_T BitOffset = 0;
+ while (Cnt < FP.mPieceCnt) {
+ PropertyValuePiece * OrgPiece = FP.mPieces + Cnt++;
+ if (BitOffset + OrgPiece->mBitSize > Offset * 8) {
+ PropertyValuePiece * Piece = add_piece();
+ *Piece = *OrgPiece;
+ if (BitOffset < Offset * 8) {
+ Piece->mBitOffset += Offset * 8 - BitOffset;
+ Piece->mBitSize -= Offset * 8 - BitOffset;
+ }
+ }
+ BitOffset += OrgPiece->mBitSize;
+ }
+ }
+ else if (FP.mRegister != NULL) {
+ PropertyValuePiece * Piece = add_piece();
+ if (Offset > FP.mRegister->size) str_exception(ERR_INV_DWARF, "Invalid OP_GNU_implicit_pointer");
+ Piece->mBigEndian = FP.mRegister->big_endian;
+ Piece->mRegister = FP.mRegister;
+ Piece->mBitOffset = Offset * 8;
+ Piece->mBitSize = (FP.mRegister->size - Offset) * 8;
+ }
+ else if (FP.mAddr != NULL) {
+ PropertyValuePiece * Piece = add_piece();
+ if (Offset > FP.mSize) str_exception(ERR_INV_DWARF, "Invalid OP_GNU_implicit_pointer");
+ Piece->mBigEndian = FP.mBigEndian;
+ Piece->mValue = FP.mAddr;
+ Piece->mBitOffset = Offset * 8;
+ Piece->mBitSize = (FP.mSize - Offset) * 8;
+ }
+ else {
+ PropertyValuePiece * Piece = add_piece();
+ if (Offset > sizeof(FP.mValue)) str_exception(ERR_INV_DWARF, "Invalid OP_GNU_implicit_pointer");
+ Piece->mBigEndian = big_endian_host();
+ Piece->mValue = (U1_T *)tmp_alloc(sizeof(FP.mValue));
+ Piece->mBitOffset = Offset * 8;
+ Piece->mBitSize = (sizeof(FP.mValue) - Offset) * 8;
+ }
+ dio_EnterSection(&Unit->mDesc, sSection, DioPos);
+}
+
static void client_op(uint8_t op) {
- dio_SetPos(sSectionOffs + sState.code_pos);
+ dio_SetPos(sSectionOffs + sState->code_pos);
switch (op) {
case OP_addr:
- sState.stk[sState.stk_pos++] = read_address();
+ sState->stk[sState->stk_pos++] = read_address();
break;
case OP_fbreg:
- if (sState.stack_frame == STACK_NO_FRAME) str_exception(ERR_INV_CONTEXT, "Invalid stack frame");
- sState.stk[sState.stk_pos++] = get_fbreg();
+ if (sState->stack_frame == STACK_NO_FRAME) str_exception(ERR_INV_CONTEXT, "Invalid stack frame");
+ sState->stk[sState->stk_pos++] = get_fbreg();
+ break;
+ case OP_GNU_push_tls_address:
+ if (sState->stk_pos == 0) str_exception(ERR_INV_DWARF, "Invalid DWARF expression stack");
+ sState->stk[sState->stk_pos - 1] = evaluate_tls_address(sState->stk[sState->stk_pos - 1]);
+ break;
+ case OP_GNU_implicit_pointer:
+ evaluate_implicit_pointer();
break;
default:
- trace(LOG_ALWAYS, "Unsupported DWARF expression op 0x%02x", op);
- str_exception(ERR_UNSUPPORTED, "Unsupported DWARF expression op");
+ str_fmt_exception(ERR_UNSUPPORTED, "Unsupported DWARF expression op 0x%02x", op);
}
- sState.code_pos = (size_t)(dio_GetPos() - sSectionOffs);
+ sState->code_pos = (size_t)(dio_GetPos() - sSectionOffs);
}
static void evaluate_expression(ELF_Section * Section, U1_T * Buf, size_t Size) {
int error = 0;
CompUnit * Unit = sValue->mObject->mCompUnit;
- sState.code = Buf;
- sState.code_len = Size;
- sState.code_pos = 0;
+ sState->code = Buf;
+ sState->code_len = Size;
+ sState->code_pos = 0;
sSection = Section;
sSectionOffs = Buf - (U1_T *)Section->data;
dio_EnterSection(&Unit->mDesc, sSection, sSectionOffs);
- if (evaluate_vm_expression(&sState) < 0) error = errno;
- if (!error && sState.piece_bits) {
- sValuePieces = alloc_value_pieces();
+ if (evaluate_vm_expression(sState) < 0) error = errno;
+ if (!error && sState->piece_bits) {
while (!error) {
- PropertyValuePiece * Piece;
- if (sValuePieces->mCnt >= sValuePieces->mMax) {
- sValuePieces->mMax += 8;
- sValuePieces->mArray = (PropertyValuePiece *)loc_realloc(sValuePieces->mArray,
- sizeof(PropertyValuePiece) * sValuePieces->mMax);
+ PropertyValuePiece * Piece = add_piece();
+ if (sState->reg) {
+ Piece->mRegister = sState->reg;
+ Piece->mBigEndian = sState->reg->big_endian;
}
- Piece = sValuePieces->mArray + sValuePieces->mCnt++;
- memset(Piece, 0, sizeof(PropertyValuePiece));
- if (sState.reg) {
- Piece->mRegister = sState.reg;
- Piece->mBigEndian = sState.reg->big_endian;
+ else if (sState->value_addr) {
+ Piece->mValue = (U1_T *)sState->value_addr;
+ if (sState->value_size * 8 < sState->piece_bits) str_exception(ERR_INV_DWARF, "Invalid object piece size");
+ Piece->mBigEndian = sState->big_endian;
}
- else if (sState.value_addr) {
- Piece->mValue = (U1_T *)sState.value_addr;
- if (sState.value_size * 8 < sState.piece_bits) str_exception(ERR_INV_DWARF, "Invalid object piece size");
- Piece->mBigEndian = sState.big_endian;
+ else if (sState->stk_pos == 0) {
+ /* An empty location description represents a piece or all of an object that is
+ * present in the source but not in the object code (perhaps due to optimization). */
+ size_t size = (sState->piece_bits + 7) / 8;
+ Piece->mValue = (U1_T *)tmp_alloc_zero(size);
}
else {
- Piece->mAddress = sState.stk[--sState.stk_pos];
- Piece->mBigEndian = sState.big_endian;
+ Piece->mAddress = sState->stk[--sState->stk_pos];
+ Piece->mBigEndian = sState->big_endian;
}
- Piece->mBitOffset = sState.piece_offs;
- Piece->mBitSize = sState.piece_bits;
- if (sState.code_pos >= sState.code_len) break;
- if (evaluate_vm_expression(&sState) < 0) error = errno;
+ Piece->mBitOffset = sState->piece_offs;
+ Piece->mBitSize = sState->piece_bits;
+ if (sState->stk_pos != 0) str_exception(ERR_INV_DWARF, "Invalid DWARF expression stack");
+ if (sState->code_pos >= sState->code_len) break;
+ if (evaluate_vm_expression(sState) < 0) error = errno;
}
}
dio_ExitSection();
- assert(error || sState.code_pos == sState.code_len);
+ assert(error || sState->code_pos == sState->code_len);
if (error) exception(error);
}
@@ -276,34 +293,37 @@ static void evaluate_location(void) {
}
void dwarf_evaluate_expression(U8_T BaseAddress, PropertyValue * v) {
- unsigned stk_pos = 0;
CompUnit * Unit = v->mObject->mCompUnit;
+ VMState * OrgState = sState;
+ ELF_Section * OrgSection = sSection;
+ U8_T OrgSectionOffs = sSectionOffs;
+ PropertyValue * OrgValue = sValue;
+ PropertyValuePiece * OrgValuePieces = sValuePieces;
+ U4_T OrgValuePiecesCnt = sValuePiecesCnt;
+ U4_T OrgValuePiecesMax = sValuePiecesMax;
sValue = v;
sValuePieces = NULL;
- sState.ctx = sValue->mContext;
- sState.addr_size = Unit->mDesc.mAddressSize;
- sState.big_endian = Unit->mFile->big_endian;
- sState.stack_frame = sValue->mFrame;
- sState.reg_id_scope = Unit->mRegIdScope;
- sState.object_address = BaseAddress;
- sState.client_op = client_op;;
-
- if (sValue->mAttr != AT_frame_base) sState.stk_pos = 0;
- stk_pos = sState.stk_pos;
+ sValuePiecesCnt = 0;
+ sValuePiecesMax = 0;
+ sState = (VMState *)tmp_alloc_zero(sizeof(VMState));
+ sState->ctx = sValue->mContext;
+ sState->addr_size = Unit->mDesc.mAddressSize;
+ sState->big_endian = Unit->mFile->big_endian;
+ sState->stack_frame = sValue->mFrame;
+ sState->reg_id_scope = Unit->mRegIdScope;
+ sState->object_address = BaseAddress;
+ sState->client_op = client_op;;
if (sValue->mAttr == AT_data_member_location) {
- if (sState.stk_pos >= sState.stk_max) {
- sState.stk_max += 8;
- sState.stk = (U8_T *)loc_alloc(sizeof(U8_T) * sState.stk_max);
- }
- sState.stk[sState.stk_pos++] = BaseAddress;
+ sState->stk = (U8_T *)tmp_alloc(sizeof(U8_T) * (sState->stk_max = 8));
+ sState->stk[sState->stk_pos++] = BaseAddress;
}
if (sValue->mRegister != NULL || sValue->mAddr == NULL || sValue->mSize == 0) {
- str_exception(ERR_INV_DWARF, "invalid DWARF expression reference");
+ str_exception(ERR_INV_DWARF, "Invalid DWARF expression reference");
}
if (sValue->mForm == FORM_DATA4 || sValue->mForm == FORM_DATA8) {
- if (sValue->mFrame == STACK_NO_FRAME) str_exception(ERR_INV_CONTEXT, "need stack frame");
+ if (sValue->mFrame == STACK_NO_FRAME) str_exception(ERR_INV_CONTEXT, "Need stack frame");
evaluate_location();
}
else {
@@ -314,32 +334,40 @@ void dwarf_evaluate_expression(U8_T BaseAddress, PropertyValue * v) {
sValue->mAddr = NULL;
sValue->mValue = 0;
sValue->mSize = 0;
- sValue->mBigEndian = sState.big_endian;
+ sValue->mBigEndian = sState->big_endian;
sValue->mRegister = NULL;
sValue->mPieces = NULL;
sValue->mPieceCnt = 0;
if (sValuePieces) {
- sValue->mPieces = sValuePieces->mArray;
- sValue->mPieceCnt = sValuePieces->mCnt;
+ sValue->mPieces = sValuePieces;
+ sValue->mPieceCnt = sValuePiecesCnt;
}
- else if (sState.reg) {
- sValue->mSize = sState.reg->size;
- sValue->mBigEndian = sState.reg->big_endian;
- sValue->mRegister = sState.reg;
+ else if (sState->reg) {
+ sValue->mSize = sState->reg->size;
+ sValue->mBigEndian = sState->reg->big_endian;
+ sValue->mRegister = sState->reg;
}
- else if (sState.value_addr) {
- sValue->mAddr = (U1_T *)sState.value_addr;
- sValue->mSize = sState.value_size;
- sValue->mBigEndian = sState.big_endian;
+ else if (sState->value_addr) {
+ sValue->mAddr = (U1_T *)sState->value_addr;
+ sValue->mSize = sState->value_size;
+ sValue->mBigEndian = sState->big_endian;
}
else {
- sValue->mValue = sState.stk[--sState.stk_pos];
+ sValue->mValue = sState->stk[--sState->stk_pos];
}
- if (sState.stk_pos != stk_pos) {
+ if (sState->stk_pos != 0) {
str_exception(ERR_INV_DWARF, "Invalid DWARF expression stack");
}
+
+ sState = OrgState;
+ sSection = OrgSection;
+ sSectionOffs = OrgSectionOffs;
+ sValue = OrgValue;
+ sValuePieces = OrgValuePieces;
+ sValuePiecesCnt = OrgValuePiecesCnt;
+ sValuePiecesMax = OrgValuePiecesMax;
}
#endif /* ENABLE_ELF && ENABLE_DebugContext */
diff --git a/agent/tcf/services/dwarfframe.c b/agent/tcf/services/dwarfframe.c
index e47310ec..5d1c5a77 100644
--- a/agent/tcf/services/dwarfframe.c
+++ b/agent/tcf/services/dwarfframe.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -978,7 +978,7 @@ void get_dwarf_stack_frame_info(Context * ctx, ELF_File * file, ELF_Section * se
dwarf_stack_trace_addr = 0;
dwarf_stack_trace_size = 0;
- if (section == NULL) section = cache->mEHFrame;
+ if (section == NULL && !file->debug_info_file) section = cache->mEHFrame;
if (section == NULL) return;
memset(&rules, 0, sizeof(StackFrameRules));
diff --git a/agent/tcf/services/elf-loader.c b/agent/tcf/services/elf-loader.c
new file mode 100644
index 00000000..28321e53
--- /dev/null
+++ b/agent/tcf/services/elf-loader.c
@@ -0,0 +1,278 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ * The Eclipse Public License is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ * You may elect to redistribute this code under either of these licenses.
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+
+/*
+ * This module implements access to ELF dynamic loader data.
+ */
+
+#include <tcf/config.h>
+
+#if ENABLE_ELF && ENABLE_DebugContext
+
+#include <tcf/framework/exceptions.h>
+#include <tcf/services/symbols.h>
+#include <tcf/services/dwarfcache.h>
+#include <tcf/services/elf-loader.h>
+
+static ContextAddress to_address(uint8_t * buf, size_t size, int big_endian) {
+ size_t i;
+ ContextAddress addr = 0;
+ for (i = 0; i < size; i++) {
+ addr = addr << 8;
+ addr |= buf[big_endian ? i : size - i - 1];
+ }
+ return addr;
+}
+
+static int get_dynamic_tag(Context * ctx, ELF_File * file, int tag, ContextAddress * addr) {
+ unsigned i, j;
+
+ for (i = 1; i < file->section_cnt; i++) {
+ ELF_Section * sec = file->sections + i;
+ if (sec->size == 0) continue;
+ if (sec->name == NULL) continue;
+ if (strcmp(sec->name, ".dynamic") == 0) {
+ ContextAddress sec_addr = elf_map_to_run_time_address(ctx, file, sec, (ContextAddress)sec->addr);
+ if (elf_load(sec) < 0) return -1;
+ if (file->elf64) {
+ unsigned cnt = (unsigned)(sec->size / sizeof(Elf64_Dyn));
+ for (j = 0; j < cnt; j++) {
+ Elf64_Dyn dyn = *((Elf64_Dyn *)sec->data + j);
+ if (file->byte_swap) SWAP(dyn.d_tag);
+ if (dyn.d_tag == DT_NULL) break;
+ if (dyn.d_tag == tag) {
+ if (context_read_mem(ctx, sec_addr + j * sizeof(dyn), &dyn, sizeof(dyn)) < 0) return -1;
+ if (file->byte_swap) {
+ SWAP(dyn.d_tag);
+ SWAP(dyn.d_un.d_ptr);
+ }
+ if (dyn.d_tag != tag) continue;
+ if (addr != NULL) *addr = (ContextAddress)dyn.d_un.d_ptr;
+ return 0;
+ }
+ }
+ }
+ else {
+ unsigned cnt = (unsigned)(sec->size / sizeof(Elf32_Dyn));
+ for (j = 0; j < cnt; j++) {
+ Elf32_Dyn dyn = *((Elf32_Dyn *)sec->data + j);
+ if (file->byte_swap) SWAP(dyn.d_tag);
+ if (dyn.d_tag == DT_NULL) break;
+ if (dyn.d_tag == tag) {
+ if (context_read_mem(ctx, sec_addr + j * sizeof(dyn), &dyn, sizeof(dyn)) < 0) return -1;
+ if (file->byte_swap) {
+ SWAP(dyn.d_tag);
+ SWAP(dyn.d_un.d_ptr);
+ }
+ if (dyn.d_tag != tag) continue;
+ if (addr != NULL) *addr = (ContextAddress)dyn.d_un.d_ptr;
+ return 0;
+ }
+ }
+ }
+ }
+ }
+ errno = ENOENT;
+ return -1;
+}
+
+static int sym_name_cmp(const char * x, const char * y) {
+ while (*x && *x == *y) {
+ x++;
+ y++;
+ }
+ if (*x == 0 && *y == 0) return 0;
+ if (*x == '@' && *(x + 1) == '@' && *y == 0) return 0;
+ if (*x < *y) return -1;
+ return 1;
+}
+
+static int get_global_symbol_address(Context * ctx, ELF_File * file, const char * name, ContextAddress * addr) {
+ unsigned i, j;
+
+ for (i = 1; i < file->section_cnt; i++) {
+ ELF_Section * sec = file->sections + i;
+ if (sec->size == 0) continue;
+ if (sec->type == SHT_SYMTAB) {
+ ELF_Section * str = NULL;
+ if (sec->link == 0 || sec->link >= file->section_cnt) {
+ errno = EINVAL;
+ return -1;
+ }
+ str = file->sections + sec->link;
+ if (elf_load(sec) < 0) return -1;
+ if (elf_load(str) < 0) return -1;
+ if (file->elf64) {
+ unsigned cnt = (unsigned)(sec->size / sizeof(Elf64_Sym));
+ for (j = 0; j < cnt; j++) {
+ Elf64_Sym sym = *((Elf64_Sym *)sec->data + j);
+ if (ELF64_ST_BIND(sym.st_info) != STB_GLOBAL) continue;
+ if (file->byte_swap) SWAP(sym.st_name);
+ if (sym_name_cmp((char *)str->data + sym.st_name, name) != 0) continue;
+ switch (ELF64_ST_TYPE(sym.st_info)) {
+ case STT_OBJECT:
+ case STT_FUNC:
+ if (file->byte_swap) SWAP(sym.st_value);
+ *addr = elf_map_to_run_time_address(ctx, file, NULL, (ContextAddress)sym.st_value);
+ if (*addr != 0) return 0;
+ }
+ }
+ }
+ else {
+ unsigned cnt = (unsigned)(sec->size / sizeof(Elf32_Sym));
+ for (j = 0; j < cnt; j++) {
+ Elf32_Sym sym = *((Elf32_Sym *)sec->data + j);
+ if (ELF32_ST_BIND(sym.st_info) != STB_GLOBAL) continue;
+ if (file->byte_swap) SWAP(sym.st_name);
+ if (sym_name_cmp((char *)str->data + sym.st_name, name) != 0) continue;
+ switch (ELF32_ST_TYPE(sym.st_info)) {
+ case STT_OBJECT:
+ case STT_FUNC:
+ if (file->byte_swap) SWAP(sym.st_value);
+ *addr = elf_map_to_run_time_address(ctx, file, NULL, (ContextAddress)sym.st_value);
+ if (*addr != 0) return 0;
+ }
+ }
+ }
+ }
+ }
+ errno = ENOENT;
+ return -1;
+}
+
+ContextAddress elf_get_debug_structure_address(Context * ctx, ELF_File ** file_ptr) {
+ ELF_File * file = NULL;
+ ContextAddress addr = 0;
+
+ for (file = elf_list_first(ctx, 0, ~(ContextAddress)0); file != NULL; file = elf_list_next(ctx)) {
+ if (file->type != ET_EXEC) continue;
+ if (file_ptr != NULL) *file_ptr = file;
+#ifdef DT_MIPS_RLD_MAP
+ if (get_dynamic_tag(ctx, file, DT_MIPS_RLD_MAP, &addr) == 0) {
+ if (elf_read_memory_word(ctx, file, addr, &addr) < 0) continue;
+ break;
+ }
+#endif
+ if (get_dynamic_tag(ctx, file, DT_DEBUG, &addr) == 0) break;
+ if (get_global_symbol_address(ctx, file, "_r_debug", &addr) == 0) break;
+ }
+ elf_list_done(ctx);
+
+ return addr;
+}
+
+static ContextAddress find_module(Context * ctx, ELF_File * exe_file, ELF_File * module,
+ ContextAddress r_map, ContextAddress r_brk) {
+#if ENABLE_Symbols
+ Symbol * sym = NULL;
+ int i = 0, n = 0;
+ Symbol ** children = NULL;
+ ContextAddress link = r_map;
+ ContextAddress offs_l_addr = 0;
+ ContextAddress offs_l_next = 0;
+ ContextAddress offs_l_tls_modid = 0;
+ if (find_symbol_by_name(ctx, STACK_NO_FRAME, r_brk, "link_map", &sym) < 0)
+ str_exception(errno, "Cannot find loader symbol: link_map");
+ if (get_symbol_children(sym, &children, &n) < 0) exception(errno);
+ for (i = 0; i < n; i++) {
+ char * name = NULL;
+ ContextAddress offs = 0;
+ if (get_symbol_name(children[i], &name) < 0) exception(errno);
+ if (name == NULL) continue;
+ if (get_symbol_offset(children[i], &offs) < 0) exception(errno);
+ if (strcmp(name, "l_map_start") == 0) offs_l_addr = offs;
+ else if (strcmp(name, "l_next") == 0) offs_l_next = offs;
+ else if (strcmp(name, "l_tls_modid") == 0) offs_l_tls_modid = offs;
+ }
+ if (offs_l_addr == 0 || offs_l_next == 0 || offs_l_tls_modid == 0)
+ str_exception(errno, "Invalid 'link_map' fields");
+ while (link != 0) {
+ ContextAddress l_tls_modid = 0;
+ if (elf_read_memory_word(ctx, exe_file, link + offs_l_tls_modid, &l_tls_modid) < 0) exception(errno);
+ if (l_tls_modid != 0) {
+ ContextAddress l_addr = 0;
+ ELF_File * link_file = NULL;
+ if (elf_read_memory_word(ctx, exe_file, link + offs_l_addr, &l_addr) < 0) exception(errno);
+ elf_map_to_link_time_address(ctx, l_addr, &link_file, NULL);
+ //printf("link 0x%016" PRIX64 " 0x%016" PRIX64 " 0x%016" PRIX64 " 0x%X\n", (U8_T)link, (U8_T)l_addr, (U8_T)l_tls_modid, link_file);
+ if (link_file != NULL) {
+ if (link_file == module) return l_tls_modid;
+ if (link_file->debug_info_file_name != NULL &&
+ strcmp(link_file->debug_info_file_name, module->name) == 0) return l_tls_modid;
+ }
+ }
+ if (elf_read_memory_word(ctx, exe_file, link + offs_l_next, &link) < 0) exception(errno);
+ }
+#endif
+ return 0;
+}
+
+static ContextAddress get_module_id(Context * ctx, ELF_File * module) {
+ ELF_File * exe_file = NULL;
+ ContextAddress addr = elf_get_debug_structure_address(ctx, &exe_file);
+ size_t word_size = exe_file && exe_file->elf64 ? 8 : 4;
+ Trap trap;
+
+ if (addr == 0 || exe_file == NULL) str_exception(ERR_OTHER, "Cannot find loader debug data");
+ if (set_trap(&trap)) {
+ ContextAddress r_map = 0;
+ ContextAddress r_brk = 0;
+ ContextAddress mod_id = 0;
+ if (elf_read_memory_word(ctx, exe_file, addr + word_size * 1, &r_map) < 0) exception(errno);
+ if (elf_read_memory_word(ctx, exe_file, addr + word_size * 2, &r_brk) < 0) exception(errno);
+ if (r_map != 0 && r_brk != 0) mod_id = find_module(ctx, exe_file, module, r_map, r_brk);
+ clear_trap(&trap);
+ if (mod_id) return mod_id;
+ }
+ else {
+ str_exception(trap.error, "Cannot access target ELF loader data");
+ }
+ str_exception(ERR_OTHER, "Cannot get TLS module ID");
+ return 0;
+}
+
+ContextAddress get_tls_address(Context * ctx, ELF_File * file) {
+ ContextAddress mod_tls_addr = 0;
+ RegisterIdScope reg_id_scope = { file->machine, file->os_abi, file->big_endian, REGNUM_DWARF };
+ switch (file->machine) {
+ case EM_X86_64:
+ {
+ uint8_t buf[8];
+ ContextAddress tcb_addr = 0;
+ ContextAddress vdt_addr = 0;
+ ContextAddress mod_id = 0;
+ RegisterDefinition * reg_def = get_reg_by_id(ctx, 58, &reg_id_scope);
+ if (reg_def == NULL) exception(errno);
+ if (context_read_reg(ctx, reg_def, 0, reg_def->size, buf) < 0)
+ str_exception(errno, "Cannot read TCB base register");
+ tcb_addr = to_address(buf, reg_def->size, reg_def->big_endian);
+ if (elf_read_memory_word(ctx, file, tcb_addr + 8, &vdt_addr) < 0)
+ str_exception(errno, "Cannot read TCB");
+ mod_id = get_module_id(ctx, file);
+ if (elf_read_memory_word(ctx, file, vdt_addr + mod_id * 16, &mod_tls_addr) < 0)
+ str_exception(errno, "Cannot read VDT");
+ if (mod_tls_addr == 0 || mod_tls_addr == ~(U8_T)0)
+ str_exception(errno, "Thread local storage is not allocated yet");
+ }
+ break;
+ default:
+ str_fmt_exception(ERR_INV_CONTEXT,
+ "Thread local storage access is not supported yet for machine type %d",
+ file->machine);
+ }
+ return mod_tls_addr;
+}
+
+#endif
diff --git a/agent/tcf/services/elf-loader.h b/agent/tcf/services/elf-loader.h
new file mode 100644
index 00000000..84129a4f
--- /dev/null
+++ b/agent/tcf/services/elf-loader.h
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ * The Eclipse Public License is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ * You may elect to redistribute this code under either of these licenses.
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+
+/*
+ * This module implements access to ELF dynamic loader data.
+ */
+
+#ifndef D_elf_loader
+#define D_elf_loader
+
+#include <tcf/config.h>
+
+#if ENABLE_ELF && ENABLE_DebugContext
+
+#include <tcf/framework/context.h>
+#include <tcf/services/tcf_elf.h>
+
+/*
+ * Return run-time address of the debug structrure that is normally pointed by DT_DEBUG entry in ".dynamic" section.
+ * "file" is assigned a file that contains DT_DEBUG entry.
+ * Return 0 if the structure could not be found.
+ */
+extern ContextAddress elf_get_debug_structure_address(Context * ctx, ELF_File ** file_ptr);
+
+extern ContextAddress get_tls_address(Context * ctx, ELF_File * file);
+
+#endif /* ENABLE_ELF && ENABLE_DebugContext */
+#endif /* D_elf_loader */
diff --git a/agent/tcf/services/expressions.c b/agent/tcf/services/expressions.c
index a1ed3d43..6ba8b326 100644
--- a/agent/tcf/services/expressions.c
+++ b/agent/tcf/services/expressions.c
@@ -2588,7 +2588,8 @@ static void command_evaluate_cache_client(void * x) {
int size = (size_t)value.size - offs;
if (size > (int)sizeof(buf)) size = (int)sizeof(buf);
memset(buf, 0, size);
- if (!err && context_read_mem(ctx, value.address + offs, buf, size) < 0) err = errno;
+ if (!err && context_read_mem(ctx, value.address + offs, buf, size) < 0)
+ err = set_errno(errno, "Cannot read target memory");
json_write_binary_data(&state, buf, size);
offs += size;
}
diff --git a/agent/tcf/services/linenumbers_elf.c b/agent/tcf/services/linenumbers_elf.c
index 22107bb3..13dc4e80 100644
--- a/agent/tcf/services/linenumbers_elf.c
+++ b/agent/tcf/services/linenumbers_elf.c
@@ -199,15 +199,8 @@ int line_to_address(Context * ctx, char * file_name, int line, int column,
h = calc_file_name_hash(fnm);
while (file != NULL) {
Trap trap;
- if (file->debug_info_file_name != NULL && !file->debug_info_file) {
- ELF_File * debug = elf_open(file->debug_info_file_name);
- if (debug != NULL) {
- debug->debug_info_file = 1;
- file = debug;
- }
- }
if (set_trap(&trap)) {
- DWARFCache * cache = get_dwarf_cache(file);
+ DWARFCache * cache = get_dwarf_cache(get_dwarf_file(file));
ObjectInfo * info = cache->mCompUnits;
while (info != NULL) {
CompUnit * unit = info->mCompUnit;
diff --git a/agent/tcf/services/symbols.h b/agent/tcf/services/symbols.h
index ac9ce535..884699d2 100644
--- a/agent/tcf/services/symbols.h
+++ b/agent/tcf/services/symbols.h
@@ -67,6 +67,7 @@ typedef uint32_t SYM_FLAGS;
#define SYM_FLAG_EXTERNAL 0x08000
#define SYM_FLAG_VARARG 0x10000
#define SYM_FLAG_ARTIFICIAL 0x20000
+#define SYM_FLAG_TYPE_PARAMETER 0x40000
/* Symbol properties update policies */
#define UPDATE_ON_MEMORY_MAP_CHANGES 0
@@ -81,14 +82,14 @@ typedef void EnumerateSymbolsCallBack(void *, Symbol *);
* On error, returns -1 and sets errno.
* On success returns 0.
*/
-extern int find_symbol_by_name(Context * ctx, int frame, ContextAddress ip, char * name, Symbol ** sym);
+extern int find_symbol_by_name(Context * ctx, int frame, ContextAddress ip, const char * name, Symbol ** sym);
/*
* Find symbol information for given symbol name in given context and visibility scope.
* On error, returns -1 and sets errno.
* On success returns 0.
*/
-extern int find_symbol_in_scope(Context * ctx, int frame, ContextAddress ip, Symbol * scope, char * name, Symbol ** sym);
+extern int find_symbol_in_scope(Context * ctx, int frame, ContextAddress ip, Symbol * scope, const char * name, Symbol ** sym);
/*
* Find symbol information for given address in given context.
diff --git a/agent/tcf/services/symbols_elf.c b/agent/tcf/services/symbols_elf.c
index f4b01dad..d59fd97d 100644
--- a/agent/tcf/services/symbols_elf.c
+++ b/agent/tcf/services/symbols_elf.c
@@ -251,6 +251,7 @@ static void object2symbol(ObjectInfo * obj, Symbol ** res) {
case TAG_mutable_type:
case TAG_shared_type:
case TAG_typedef:
+ case TAG_template_type_param:
sym->sym_class = SYM_CLASS_TYPE;
break;
case TAG_global_variable:
@@ -312,6 +313,7 @@ static int is_modified_type(ObjectInfo * obj) {
case TAG_restrict_type:
case TAG_shared_type:
case TAG_typedef:
+ case TAG_template_type_param:
return 1;
}
}
@@ -484,7 +486,7 @@ static int find_in_dwarf(const char * name, Symbol ** sym) {
return 0;
}
-static int find_by_name_in_pub_names(DWARFCache * cache, PubNamesTable * tbl, char * name, Symbol ** sym) {
+static int find_by_name_in_pub_names(DWARFCache * cache, PubNamesTable * tbl, const char * name, Symbol ** sym) {
unsigned n = tbl->mHash[calc_symbol_name_hash(name)];
while (n != 0) {
U8_T id = tbl->mNext[n].mID;
@@ -516,7 +518,7 @@ static void create_symbol_names_hash(ELF_Section * tbl) {
}
}
-static int find_by_name_in_sym_table(DWARFCache * cache, char * name, Symbol ** res) {
+static int find_by_name_in_sym_table(DWARFCache * cache, const char * name, Symbol ** res) {
unsigned m = 0;
unsigned h = calc_symbol_name_hash(name);
unsigned cnt = 0;
@@ -582,9 +584,10 @@ static int find_by_name_in_sym_table(DWARFCache * cache, char * name, Symbol **
return cnt == 1;
}
-int find_symbol_by_name(Context * ctx, int frame, ContextAddress ip, char * name, Symbol ** res) {
+int find_symbol_by_name(Context * ctx, int frame, ContextAddress ip, const char * name, Symbol ** res) {
int error = 0;
int found = 0;
+ ELF_File * curr_file = NULL;
assert(ctx != NULL);
@@ -619,81 +622,88 @@ int find_symbol_by_name(Context * ctx, int frame, ContextAddress ip, char * name
if (error == 0 && !found && get_sym_context(ctx, frame, ip) < 0) error = errno;
- if (error == 0 && !found && sym_ip != 0) {
- Trap trap;
- if (set_trap(&trap)) {
- found = find_in_dwarf(name, res);
- clear_trap(&trap);
- }
- else {
- error = trap.error;
- }
- }
+ if (sym_ip != 0) {
- if (error == 0 && !found) {
- ELF_File * file = elf_list_first(sym_ctx, sym_ip, sym_ip ? sym_ip : ~(ContextAddress)0);
- if (file == NULL) error = errno;
- while (error == 0 && file != NULL) {
+ if (error == 0 && !found) {
+ /* Search the name in current compilation unit */
Trap trap;
if (set_trap(&trap)) {
- DWARFCache * cache = get_dwarf_cache(file);
- if (cache->mPubNames.mHash != NULL) {
- found = find_by_name_in_pub_names(cache, &cache->mPubNames, name, res);
- if (!found && cache->mPubTypes.mHash != NULL) {
- found = find_by_name_in_pub_names(cache, &cache->mPubTypes, name, res);
- }
- }
- if (!found) {
- found = find_by_name_in_sym_table(cache, name, res);
- }
+ found = find_in_dwarf(name, res);
clear_trap(&trap);
}
else {
error = trap.error;
- break;
}
- if (found) break;
- file = elf_list_next(sym_ctx);
- if (file == NULL) error = errno;
}
- elf_list_done(sym_ctx);
- }
- if (error == 0 && !found && sym_ip != 0) {
- Trap trap;
- if (set_trap(&trap)) {
- unsigned i = 0;
- while (base_types_aliases[i].name) {
- if (strcmp(name, base_types_aliases[i].name) == 0) {
- found = find_in_dwarf(base_types_aliases[i].alias, res);
- if (found) break;
+ if (error == 0 && !found) {
+ /* Search in pub names of the current file */
+ ELF_File * file = elf_list_first(sym_ctx, sym_ip, sym_ip);
+ if (file == NULL) error = errno;
+ while (error == 0 && file != NULL) {
+ Trap trap;
+ curr_file = file;
+ if (set_trap(&trap)) {
+ DWARFCache * cache = get_dwarf_cache(get_dwarf_file(file));
+ if (cache->mPubNames.mHash != NULL) {
+ found = find_by_name_in_pub_names(cache, &cache->mPubNames, name, res);
+ if (!found && cache->mPubTypes.mHash != NULL) {
+ found = find_by_name_in_pub_names(cache, &cache->mPubTypes, name, res);
+ }
+ }
+ if (!found) {
+ found = find_by_name_in_sym_table(cache, name, res);
+ }
+ clear_trap(&trap);
}
- i++;
+ else {
+ error = trap.error;
+ break;
+ }
+ if (found) break;
+ file = elf_list_next(sym_ctx);
+ if (file == NULL) error = errno;
}
- if (!found) {
- i = 0;
- while (constant_pseudo_symbols[i].name) {
- if (strcmp(name, constant_pseudo_symbols[i].name) == 0) {
- Symbol * type = NULL;
- found = find_in_dwarf(constant_pseudo_symbols[i].type, &type);
- if (found) {
- Symbol * sym = alloc_symbol();
- sym->ctx = context_get_group(ctx, CONTEXT_GROUP_PROCESS);
- sym->frame = STACK_NO_FRAME;
- sym->sym_class = SYM_CLASS_VALUE;
- sym->base = type;
- sym->length = i;
- *res = sym;
- break;
- }
+ elf_list_done(sym_ctx);
+ }
+
+ if (error == 0 && !found) {
+ /* Check if the name is one of well known C/C++ names */
+ Trap trap;
+ if (set_trap(&trap)) {
+ unsigned i = 0;
+ while (base_types_aliases[i].name) {
+ if (strcmp(name, base_types_aliases[i].name) == 0) {
+ found = find_in_dwarf(base_types_aliases[i].alias, res);
+ if (found) break;
}
i++;
}
+ if (!found) {
+ i = 0;
+ while (constant_pseudo_symbols[i].name) {
+ if (strcmp(name, constant_pseudo_symbols[i].name) == 0) {
+ Symbol * type = NULL;
+ found = find_in_dwarf(constant_pseudo_symbols[i].type, &type);
+ if (found) {
+ Symbol * sym = alloc_symbol();
+ sym->ctx = context_get_group(ctx, CONTEXT_GROUP_PROCESS);
+ sym->frame = STACK_NO_FRAME;
+ sym->sym_class = SYM_CLASS_VALUE;
+ sym->base = type;
+ sym->length = i;
+ *res = sym;
+ break;
+ }
+ }
+ i++;
+ }
+ }
+ clear_trap(&trap);
+ }
+ else {
+ error = trap.error;
}
- clear_trap(&trap);
- }
- else {
- error = trap.error;
}
}
@@ -714,36 +724,29 @@ int find_symbol_by_name(Context * ctx, int frame, ContextAddress ip, char * name
}
#endif
- if (error == 0 && !found && sym_ip == 0) {
- /* Search all compilation units */
+ if (error == 0 && !found) {
+ /* Search in pub names of all other files */
ELF_File * file = elf_list_first(sym_ctx, 0, ~(ContextAddress)0);
if (file == NULL) error = errno;
while (error == 0 && file != NULL) {
- Trap trap;
- if (set_trap(&trap)) {
- unsigned i;
- DWARFCache * cache = get_dwarf_cache(file);
- for (i = 0; i < cache->mAddrRangesCnt; i++) {
- UnitAddressRange * range = cache->mAddrRanges + i;
- CompUnit * unit = range->mUnit;
- ContextAddress rt_addr = elf_map_to_run_time_address(sym_ctx, file, unit->mTextSection, range->mAddr);
- if (rt_addr != 0) {
- *res = NULL;
- sym_ip = rt_addr;
- if (find_in_object_tree(unit->mObject->mChildren, rt_addr - range->mAddr, sym_ip, name, res)) found = 1;
- if (!found && unit->mBaseTypes != NULL) {
- if (find_in_object_tree(unit->mBaseTypes->mObject->mChildren, 0, 0, name, res)) found = 1;
+ if (file != curr_file) {
+ Trap trap;
+ if (set_trap(&trap)) {
+ DWARFCache * cache = get_dwarf_cache(get_dwarf_file(file));
+ if (cache->mPubNames.mHash != NULL) {
+ found = find_by_name_in_pub_names(cache, &cache->mPubNames, name, res);
+ if (!found && cache->mPubTypes.mHash != NULL) {
+ found = find_by_name_in_pub_names(cache, &cache->mPubTypes, name, res);
}
- if (found) break;
}
+ clear_trap(&trap);
}
- clear_trap(&trap);
- }
- else {
- error = trap.error;
- break;
+ else {
+ error = trap.error;
+ break;
+ }
+ if (found) break;
}
- if (found) break;
file = elf_list_next(sym_ctx);
if (file == NULL) error = errno;
}
@@ -762,7 +765,7 @@ int find_symbol_by_name(Context * ctx, int frame, ContextAddress ip, char * name
return 0;
}
-int find_symbol_in_scope(Context * ctx, int frame, ContextAddress ip, Symbol * scope, char * name, Symbol ** res) {
+int find_symbol_in_scope(Context * ctx, int frame, ContextAddress ip, Symbol * scope, const char * name, Symbol ** res) {
int error = 0;
int found = 0;
@@ -775,7 +778,7 @@ int find_symbol_in_scope(Context * ctx, int frame, ContextAddress ip, Symbol * s
while (error == 0 && file != NULL) {
Trap trap;
if (set_trap(&trap)) {
- DWARFCache * cache = get_dwarf_cache(file);
+ DWARFCache * cache = get_dwarf_cache(get_dwarf_file(file));
UnitAddressRange * range = find_comp_unit_addr_range(cache, sym_ip, sym_ip);
if (range != NULL) {
found = find_in_object_tree(range->mUnit->mObject->mChildren, 0, 0, name, res);
@@ -1460,6 +1463,7 @@ int get_symbol_type_class(const Symbol * sym, int * type_class) {
case TAG_inheritance:
case TAG_member:
case TAG_constant:
+ case TAG_template_type_param:
obj = obj->mType;
break;
default:
@@ -1586,6 +1590,23 @@ int get_symbol_size(const Symbol * sym, ContextAddress * size) {
if (ok) sz *= length;
}
}
+ if (!ok && (obj->mTag == TAG_structure_type || obj->mTag == TAG_class_type)) {
+ /* It is OK to return size 0 instead of error if the structure has no data members */
+ ObjectInfo * c = obj->mChildren;
+ sz = 0;
+ ok = 1;
+ while (ok && c != NULL) {
+ switch (c->mTag) {
+ case TAG_subprogram:
+ case TAG_typedef:
+ case TAG_template_type_param:
+ break;
+ default:
+ ok = 0;
+ }
+ c = c->mSibling;
+ }
+ }
if (!ok && ref && ref->mTag != TAG_member && ref->mTag != TAG_inheritance) {
Trap trap;
if (set_trap(&trap)) {
@@ -1901,8 +1922,6 @@ int get_symbol_value(const Symbol * sym, void ** value, size_t * size, int * big
if (obj != NULL) {
Trap trap;
PropertyValue v;
- static U1_T * bf = NULL;
- static size_t bf_size = 0;
if (set_trap(&trap)) {
read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, 0, obj, AT_const_value, &v);
if (v.mAddr != NULL) {
@@ -1915,10 +1934,7 @@ int get_symbol_value(const Symbol * sym, void ** value, size_t * size, int * big
else {
U8_T n = v.mValue;
size_t i = 0;
- if (bf_size < sizeof(v.mValue)) {
- bf_size = sizeof(v.mValue);
- bf = (U1_T *)loc_realloc(bf, bf_size);
- }
+ U1_T * bf = (U1_T *)tmp_alloc(sizeof(v.mValue));
for (i = 0; i < sizeof(v.mValue); i++) {
bf[v.mBigEndian ? sizeof(v.mValue) - i - 1 : i] = n & 0xffu;
n = n >> 8;
@@ -1938,16 +1954,17 @@ int get_symbol_value(const Symbol * sym, void ** value, size_t * size, int * big
assert(v.mForm == FORM_EXPR_VALUE);
if (v.mPieces != NULL) {
U4_T n = 0;
+ U1_T * bf = NULL;
+ size_t bf_size = 0;
U4_T bf_offs = 0;
while (n < v.mPieceCnt) {
U4_T i;
- U1_T pbf[32];
PropertyValuePiece * piece = v.mPieces + n++;
U4_T piece_size = (piece->mBitSize + 7) / 8;
- if (piece_size > sizeof(pbf)) exception(ERR_BUFFER_OVERFLOW);
+ U1_T * pbf = (U1_T *)tmp_alloc(piece_size);
if (bf_size < bf_offs / 8 + piece_size + 1) {
bf_size = bf_offs / 8 + piece_size + 1;
- bf = (U1_T *)loc_realloc(bf, bf_size);
+ bf = (U1_T *)tmp_realloc(bf, bf_size);
}
if (piece->mRegister) {
StackFrame * frame = NULL;
@@ -1986,15 +2003,13 @@ int get_symbol_value(const Symbol * sym, void ** value, size_t * size, int * big
ContextAddress sym_size = def->size;
unsigned val_offs = 0;
unsigned val_size = 0;
+ U1_T * bf = NULL;
if (get_symbol_size(sym, &sym_size) < 0) exception(errno);
- if (bf_size < sym_size) {
- bf_size = (size_t)sym_size;
- bf = (U1_T *)loc_realloc(bf, bf_size);
- }
if (get_frame_info(v.mContext, v.mFrame, &frame) < 0) exception(errno);
val_size = def->size < sym_size ? (unsigned)def->size : (unsigned)sym_size;
if (def->big_endian) val_offs = (unsigned)def->size - val_size;
+ bf = (U1_T *)tmp_alloc(val_size);
if (read_reg_bytes(frame, def, val_offs, val_size, bf) < 0) exception(errno);
*value = bf;
*size = val_size;
@@ -2205,6 +2220,10 @@ int get_symbol_flags(const Symbol * sym, SYM_FLAGS * flags) {
if (i == obj) *flags |= SYM_FLAG_TYPEDEF;
i = i->mType;
break;
+ case TAG_template_type_param:
+ if (i == obj) *flags |= SYM_FLAG_TYPE_PARAMETER;
+ i = i->mType;
+ break;
case TAG_reference_type:
case TAG_mod_reference:
*flags |= SYM_FLAG_REFERENCE;
diff --git a/agent/tcf/services/symbols_proxy.c b/agent/tcf/services/symbols_proxy.c
index 1b69899e..6c24caf2 100644
--- a/agent/tcf/services/symbols_proxy.c
+++ b/agent/tcf/services/symbols_proxy.c
@@ -448,7 +448,7 @@ static void validate_find(Channel * c, void * args, int error) {
if (trap.error) exception(trap.error);
}
-int find_symbol_by_name(Context * ctx, int frame, ContextAddress addr, char * name, Symbol ** sym) {
+int find_symbol_by_name(Context * ctx, int frame, ContextAddress addr, const char * name, Symbol ** sym) {
uint64_t ip = 0;
LINK * l = NULL;
SymbolsCache * syms = NULL;
@@ -544,7 +544,7 @@ int find_symbol_by_name(Context * ctx, int frame, ContextAddress addr, char * n
return 0;
}
-int find_symbol_in_scope(Context * ctx, int frame, ContextAddress addr, Symbol * scope, char * name, Symbol ** sym) {
+int find_symbol_in_scope(Context * ctx, int frame, ContextAddress addr, Symbol * scope, const char * name, Symbol ** sym) {
uint64_t ip = 0;
LINK * l = NULL;
SymbolsCache * syms = NULL;
diff --git a/agent/tcf/services/symbols_win32.c b/agent/tcf/services/symbols_win32.c
index 56632517..b6fb6633 100644
--- a/agent/tcf/services/symbols_win32.c
+++ b/agent/tcf/services/symbols_win32.c
@@ -951,7 +951,7 @@ static int set_pe_context(Context * ctx, int frame, ContextAddress ip, HANDLE pr
return 0;
}
-static int find_pe_symbol_by_name(Context * ctx, int frame, ContextAddress ip, char * name, Symbol * sym) {
+static int find_pe_symbol_by_name(Context * ctx, int frame, ContextAddress ip, const char * name, Symbol * sym) {
HANDLE process = get_context_handle(ctx->parent == NULL ? ctx : ctx->parent);
ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)];
SYMBOL_INFO * info = (SYMBOL_INFO *)buffer;
@@ -1013,7 +1013,7 @@ static int find_pe_symbol_by_addr(Context * ctx, int frame, ContextAddress addr,
return -1;
}
-static int find_basic_type_symbol(Context * ctx, char * name, Symbol * sym) {
+static int find_basic_type_symbol(Context * ctx, const char * name, Symbol * sym) {
const TypeInfo * p = basic_type_info;
while (p->name != NULL) {
if (strcmp(p->name, name) == 0) {
@@ -1028,7 +1028,7 @@ static int find_basic_type_symbol(Context * ctx, char * name, Symbol * sym) {
return -1;
}
-int find_symbol_by_name(Context * ctx, int frame, ContextAddress ip, char * name, Symbol ** sym) {
+int find_symbol_by_name(Context * ctx, int frame, ContextAddress ip, const char * name, Symbol ** sym) {
int found = 0;
*sym = alloc_symbol();
@@ -1063,7 +1063,7 @@ int find_symbol_by_name(Context * ctx, int frame, ContextAddress ip, char * name
return 0;
}
-int find_symbol_in_scope(Context * ctx, int frame, ContextAddress ip, Symbol * scope, char * name, Symbol ** sym) {
+int find_symbol_in_scope(Context * ctx, int frame, ContextAddress ip, Symbol * scope, const char * name, Symbol ** sym) {
errno = ERR_SYM_NOT_FOUND;
return -1;
}
diff --git a/agent/tcf/services/tcf_elf.c b/agent/tcf/services/tcf_elf.c
index aff0d08e..4df9d4b2 100644
--- a/agent/tcf/services/tcf_elf.c
+++ b/agent/tcf/services/tcf_elf.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -276,7 +276,11 @@ static char * get_debug_info_file_name(ELF_File * file, int * error) {
lnm = apply_path_map(NULL, NULL, lnm, PATH_MAP_TO_LOCAL);
#endif
if (stat(lnm, &buf) == 0) return loc_strdup(lnm);
- return NULL;
+ snprintf(fnm, sizeof(fnm), "%s.debug", file->name);
+#if SERVICE_PathMap
+ lnm = apply_path_map(NULL, NULL, lnm, PATH_MAP_TO_LOCAL);
+#endif
+ if (stat(lnm, &buf) == 0) return loc_strdup(lnm);
}
offs += desc_sz;
while (offs % 4 != 0) offs++;
@@ -306,7 +310,6 @@ static char * get_debug_info_file_name(ELF_File * file, int * error) {
lnm = apply_path_map(NULL, NULL, lnm, PATH_MAP_TO_LOCAL);
#endif
if (stat(lnm, &buf) == 0) return loc_strdup(lnm);
- return NULL;
}
}
}
@@ -602,7 +605,9 @@ static ELF_File * create_elf_cache(const char * file_name) {
}
}
}
- if (error == 0) {
+ /* TODO: need a better way to detect "debuginfo" file */
+ file->debug_info_file = strcmp(file_name + strlen(file_name) - 6, ".debug") == 0;
+ if (error == 0 && !file->debug_info_file) {
file->debug_info_file_name = get_debug_info_file_name(file, &error);
if (file->debug_info_file_name) trace(LOG_ELF, "Debug info file found %s", file->debug_info_file_name);
}
@@ -927,7 +932,6 @@ UnitAddressRange * elf_find_unit(Context * ctx, ContextAddress addr_min, Context
if (range == NULL && file->debug_info_file_name != NULL && !file->debug_info_file) {
ELF_File * debug = elf_open(file->debug_info_file_name);
if (debug == NULL) exception(errno);
- debug->debug_info_file = 1;
if (j < debug->pheader_cnt) {
p = debug->pheaders + j;
link_addr_min = offs_min - p->offset + p->address;
@@ -951,7 +955,7 @@ UnitAddressRange * elf_find_unit(Context * ctx, ContextAddress addr_min, Context
link_addr_max = addr_max - r->addr + sec->addr;
if (link_addr_min < sec->addr) link_addr_min = sec->addr;
if (link_addr_max >= sec->addr + sec->size) link_addr_max = sec->addr + sec->size;
- range = find_comp_unit_addr_range(get_dwarf_cache(file), link_addr_min, link_addr_max);
+ range = find_comp_unit_addr_range(get_dwarf_cache(get_dwarf_file(file)), link_addr_min, link_addr_max);
if (range != NULL && range_rt_addr != NULL) {
*range_rt_addr = range->mAddr - sec->addr + r->addr;
}
@@ -1037,15 +1041,17 @@ ContextAddress elf_map_to_link_time_address(Context * ctx, ContextAddress addr,
unsigned j;
if (f->pheader_cnt == 0 && f->type == ET_EXEC) {
*file = f;
- for (j = 1; j < f->section_cnt; j++) {
- ELF_Section * s = f->sections + j;
- if ((s->flags & SHF_ALLOC) == 0) continue;
- if (s->addr <= addr && s->addr + s->size > addr) {
- *sec = s;
- return addr;
+ if (sec != NULL) {
+ for (j = 1; j < f->section_cnt; j++) {
+ ELF_Section * s = f->sections + j;
+ if ((s->flags & SHF_ALLOC) == 0) continue;
+ if (s->addr <= addr && s->addr + s->size > addr) {
+ *sec = s;
+ return addr;
+ }
}
+ *sec = NULL;
}
- *sec = NULL;
return addr;
}
for (j = 0; j < f->pheader_cnt; j++) {
@@ -1060,27 +1066,29 @@ ContextAddress elf_map_to_link_time_address(Context * ctx, ContextAddress addr,
}
*file = f;
addr = (ContextAddress)(offs - p->offset + p->address);
- for (j = 1; j < f->section_cnt; j++) {
- ELF_Section * s = f->sections + j;
- if ((s->flags & SHF_ALLOC) == 0) continue;
- if (s->addr + s->size <= p->address) continue;
- if (s->addr >= p->address + p->mem_size) continue;
- if (s->addr <= addr && s->addr + s->size > addr) {
- *sec = s;
- return addr;
+ if (sec != NULL) {
+ for (j = 1; j < f->section_cnt; j++) {
+ ELF_Section * s = f->sections + j;
+ if ((s->flags & SHF_ALLOC) == 0) continue;
+ if (s->addr + s->size <= p->address) continue;
+ if (s->addr >= p->address + p->mem_size) continue;
+ if (s->addr <= addr && s->addr + s->size > addr) {
+ *sec = s;
+ return addr;
+ }
}
+ *sec = NULL;
}
- *sec = NULL;
return addr;
}
}
else {
unsigned j;
+ *file = f;
for (j = 1; j < f->section_cnt; j++) {
ELF_Section * s = f->sections + j;
if (strcmp(s->name, r->sect_name) == 0) {
- *file = f;
- *sec = s;
+ if (sec != NULL) *sec = s;
return (ContextAddress)(addr - r->addr + s->addr);
}
}
@@ -1089,122 +1097,6 @@ ContextAddress elf_map_to_link_time_address(Context * ctx, ContextAddress addr,
return 0;
}
-static int get_dynamic_tag(Context * ctx, ELF_File * file, int tag, ContextAddress * addr) {
- unsigned i, j;
-
- for (i = 1; i < file->section_cnt; i++) {
- ELF_Section * sec = file->sections + i;
- if (sec->size == 0) continue;
- if (sec->name == NULL) continue;
- if (strcmp(sec->name, ".dynamic") == 0) {
- ContextAddress sec_addr = elf_map_to_run_time_address(ctx, file, sec, (ContextAddress)sec->addr);
- if (elf_load(sec) < 0) return -1;
- if (file->elf64) {
- unsigned cnt = (unsigned)(sec->size / sizeof(Elf64_Dyn));
- for (j = 0; j < cnt; j++) {
- Elf64_Dyn dyn = *((Elf64_Dyn *)sec->data + j);
- if (file->byte_swap) SWAP(dyn.d_tag);
- if (dyn.d_tag == DT_NULL) break;
- if (dyn.d_tag == tag) {
- if (context_read_mem(ctx, sec_addr + j * sizeof(dyn), &dyn, sizeof(dyn)) < 0) return -1;
- if (file->byte_swap) {
- SWAP(dyn.d_tag);
- SWAP(dyn.d_un.d_ptr);
- }
- if (dyn.d_tag != tag) continue;
- if (addr != NULL) *addr = (ContextAddress)dyn.d_un.d_ptr;
- return 0;
- }
- }
- }
- else {
- unsigned cnt = (unsigned)(sec->size / sizeof(Elf32_Dyn));
- for (j = 0; j < cnt; j++) {
- Elf32_Dyn dyn = *((Elf32_Dyn *)sec->data + j);
- if (file->byte_swap) SWAP(dyn.d_tag);
- if (dyn.d_tag == DT_NULL) break;
- if (dyn.d_tag == tag) {
- if (context_read_mem(ctx, sec_addr + j * sizeof(dyn), &dyn, sizeof(dyn)) < 0) return -1;
- if (file->byte_swap) {
- SWAP(dyn.d_tag);
- SWAP(dyn.d_un.d_ptr);
- }
- if (dyn.d_tag != tag) continue;
- if (addr != NULL) *addr = (ContextAddress)dyn.d_un.d_ptr;
- return 0;
- }
- }
- }
- }
- }
- errno = ENOENT;
- return -1;
-}
-
-static int sym_name_cmp(const char * x, const char * y) {
- while (*x && *x == *y) {
- x++;
- y++;
- }
- if (*x == 0 && *y == 0) return 0;
- if (*x == '@' && *(x + 1) == '@' && *y == 0) return 0;
- if (*x < *y) return -1;
- return 1;
-}
-
-static int get_global_symbol_address(Context * ctx, ELF_File * file, const char * name, ContextAddress * addr) {
- unsigned i, j;
-
- for (i = 1; i < file->section_cnt; i++) {
- ELF_Section * sec = file->sections + i;
- if (sec->size == 0) continue;
- if (sec->type == SHT_SYMTAB) {
- ELF_Section * str = NULL;
- if (sec->link == 0 || sec->link >= file->section_cnt) {
- errno = EINVAL;
- return -1;
- }
- str = file->sections + sec->link;
- if (elf_load(sec) < 0) return -1;
- if (elf_load(str) < 0) return -1;
- if (file->elf64) {
- unsigned cnt = (unsigned)(sec->size / sizeof(Elf64_Sym));
- for (j = 0; j < cnt; j++) {
- Elf64_Sym sym = *((Elf64_Sym *)sec->data + j);
- if (ELF64_ST_BIND(sym.st_info) != STB_GLOBAL) continue;
- if (file->byte_swap) SWAP(sym.st_name);
- if (sym_name_cmp((char *)str->data + sym.st_name, name) != 0) continue;
- switch (ELF64_ST_TYPE(sym.st_info)) {
- case STT_OBJECT:
- case STT_FUNC:
- if (file->byte_swap) SWAP(sym.st_value);
- *addr = elf_map_to_run_time_address(ctx, file, NULL, (ContextAddress)sym.st_value);
- if (*addr != 0) return 0;
- }
- }
- }
- else {
- unsigned cnt = (unsigned)(sec->size / sizeof(Elf32_Sym));
- for (j = 0; j < cnt; j++) {
- Elf32_Sym sym = *((Elf32_Sym *)sec->data + j);
- if (ELF32_ST_BIND(sym.st_info) != STB_GLOBAL) continue;
- if (file->byte_swap) SWAP(sym.st_name);
- if (sym_name_cmp((char *)str->data + sym.st_name, name) != 0) continue;
- switch (ELF32_ST_TYPE(sym.st_info)) {
- case STT_OBJECT:
- case STT_FUNC:
- if (file->byte_swap) SWAP(sym.st_value);
- *addr = elf_map_to_run_time_address(ctx, file, NULL, (ContextAddress)sym.st_value);
- if (*addr != 0) return 0;
- }
- }
- }
- }
- }
- errno = ENOENT;
- return -1;
-}
-
int elf_read_memory_word(Context * ctx, ELF_File * file, ContextAddress addr, ContextAddress * word) {
size_t size = file->elf64 ? 8 : 4;
size_t i = 0;
@@ -1220,27 +1112,6 @@ int elf_read_memory_word(Context * ctx, ELF_File * file, ContextAddress addr, Co
return 0;
}
-ContextAddress elf_get_debug_structure_address(Context * ctx, ELF_File ** file_ptr) {
- ELF_File * file = NULL;
- ContextAddress addr = 0;
-
- for (file = elf_list_first(ctx, 0, ~(ContextAddress)0); file != NULL; file = elf_list_next(ctx)) {
- if (file->type != ET_EXEC) continue;
- if (file_ptr != NULL) *file_ptr = file;
-#ifdef DT_MIPS_RLD_MAP
- if (get_dynamic_tag(ctx, file, DT_MIPS_RLD_MAP, &addr) == 0) {
- if (elf_read_memory_word(ctx, file, addr, &addr) < 0) continue;
- break;
- }
-#endif
- if (get_dynamic_tag(ctx, file, DT_DEBUG, &addr) == 0) break;
- if (get_global_symbol_address(ctx, file, "_r_debug", &addr) == 0) break;
- }
- elf_list_done(ctx);
-
- return addr;
-}
-
#endif /* ENABLE_DebugContext */
diff --git a/agent/tcf/services/tcf_elf.h b/agent/tcf/services/tcf_elf.h
index 644a9ab7..1be76623 100644
--- a/agent/tcf/services/tcf_elf.h
+++ b/agent/tcf/services/tcf_elf.h
@@ -547,13 +547,6 @@ extern ContextAddress elf_map_to_link_time_address(Context * ctx, ContextAddress
*/
extern int elf_read_memory_word(Context * ctx, ELF_File * file, ContextAddress addr, ContextAddress * word);
-/*
- * Return run-time address of the debug structrure that is normally pointed by DT_DEBUG entry in ".dynamic" section.
- * "file" is assigned a file that contains DT_DEBUG entry.
- * Return 0 if the structure could not be found.
- */
-extern ContextAddress elf_get_debug_structure_address(Context * ctx, ELF_File ** file);
-
#endif
/* Return symbol name hash. The hash is used to build sym_names_hash table. */
diff --git a/agent/tcf/services/vm.c b/agent/tcf/services/vm.c
index cdb3b89e..58f21697 100644
--- a/agent/tcf/services/vm.c
+++ b/agent/tcf/services/vm.c
@@ -156,6 +156,13 @@ static void get_state(VMState * s) {
code_len = 0;
}
+static int is_end_of_loc_expr(void) {
+ return
+ code_pos >= code_len ||
+ code[code_pos] == OP_piece ||
+ code[code_pos] == OP_bit_piece;
+}
+
static void evaluate_expression(void) {
uint64_t data = 0;
@@ -166,7 +173,7 @@ static void evaluate_expression(void) {
if (state->stk_pos + 4 > state->stk_max) {
state->stk_max += 8;
- state->stk = (uint64_t *)loc_realloc(state->stk, sizeof(uint64_t) * state->stk_max);
+ state->stk = (uint64_t *)tmp_realloc(state->stk, sizeof(uint64_t) * state->stk_max);
}
switch (op) {
@@ -274,6 +281,7 @@ static void evaluate_expression(void) {
case OP_div:
check_e_stack(2);
state->stk_pos--;
+ if (state->stk[state->stk_pos] == 0) inv_dwarf("Division by zero in DWARF expression");
state->stk[state->stk_pos - 1] /= state->stk[state->stk_pos];
break;
case OP_minus:
@@ -284,6 +292,7 @@ static void evaluate_expression(void) {
case OP_mod:
check_e_stack(2);
state->stk_pos--;
+ if (state->stk[state->stk_pos] == 0) inv_dwarf("Division by zero in DWARF expression");
state->stk[state->stk_pos - 1] %= state->stk[state->stk_pos];
break;
case OP_mul:
@@ -330,11 +339,16 @@ static void evaluate_expression(void) {
check_e_stack(2);
data = state->stk[state->stk_pos - 2];
cnt = state->stk[state->stk_pos - 1];
- while (cnt > 0) {
- int s = (data & ((uint64_t)1 << 63)) != 0;
- data >>= 1;
- if (s) data |= (uint64_t)1 << 63;
- cnt--;
+ if (cnt >= 64) {
+ data = data & ((uint64_t)1 << 63) ? ~(uint64_t)0 : 0;
+ }
+ else {
+ while (cnt > 0) {
+ int s = (data & ((uint64_t)1 << 63)) != 0;
+ data >>= 1;
+ if (s) data |= (uint64_t)1 << 63;
+ cnt--;
+ }
}
state->stk[state->stk_pos - 2] = data;
state->stk_pos--;
@@ -458,7 +472,7 @@ static void evaluate_expression(void) {
case OP_reg31:
{
unsigned n = op - OP_reg0;
- if (code_pos < code_len && code[code_pos] != OP_piece) inv_dwarf("OP_reg must be last instruction");
+ if (!is_end_of_loc_expr()) inv_dwarf("OP_reg must be last instruction");
state->reg = get_reg_by_id(state->ctx, n, &state->reg_id_scope);
if (state->reg == NULL) exception(errno);
}
@@ -466,7 +480,7 @@ static void evaluate_expression(void) {
case OP_regx:
{
unsigned n = (unsigned)read_u4leb128();
- if (code_pos < code_len && code[code_pos] != OP_piece) inv_dwarf("OP_regx must be last instruction");
+ if (!is_end_of_loc_expr()) inv_dwarf("OP_regx must be last instruction");
state->reg = get_reg_by_id(state->ctx, n, &state->reg_id_scope);
if (state->reg == NULL) exception(errno);
}
@@ -474,7 +488,7 @@ static void evaluate_expression(void) {
case OP_reg:
{
unsigned n = (unsigned)read_ua();
- if (code_pos < code_len && code[code_pos] != OP_piece) inv_dwarf("OP_reg must be last instruction");
+ if (!is_end_of_loc_expr()) inv_dwarf("OP_reg must be last instruction");
state->reg = get_reg_by_id(state->ctx, n, &state->reg_id_scope);
if (state->reg == NULL) exception(errno);
}
@@ -571,7 +585,7 @@ static void evaluate_expression(void) {
state->value_addr = tmp_alloc(state->value_size);
memcpy(state->value_addr, code + code_pos, state->value_size);
code_pos += state->value_size;
- if (code_pos < code_len && code[code_pos] != OP_piece) inv_dwarf("OP_implicit_value must be last instruction");
+ if (!is_end_of_loc_expr()) inv_dwarf("OP_implicit_value must be last instruction");
break;
case OP_stack_value:
check_e_stack(1);
@@ -579,7 +593,7 @@ static void evaluate_expression(void) {
state->value_size = sizeof(uint64_t);
state->value_addr = tmp_alloc(state->value_size);
memcpy(state->value_addr, state->stk + state->stk_pos, state->value_size);
- if (code_pos < code_len && code[code_pos] != OP_piece) inv_dwarf("OP_stack_value must be last instruction");
+ if (!is_end_of_loc_expr()) inv_dwarf("OP_stack_value must be last instruction");
if (big_endian_host() != state->big_endian) {
size_t i, j, n = state->value_size >> 1;
char * p = (char *)state->value_addr;
diff --git a/server/server.vcproj b/server/server.vcproj
index f458c3fb..ed91d3f9 100644
--- a/server/server.vcproj
+++ b/server/server.vcproj
@@ -259,6 +259,14 @@
>
</File>
<File
+ RelativePath="..\agent\tcf\services\elf-loader.c"
+ >
+ </File>
+ <File
+ RelativePath="..\agent\tcf\services\elf-loader.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\tcf\services\filesystem.c"
>
</File>
diff --git a/tests/mem-leaks/agent.vcproj b/tests/mem-leaks/agent.vcproj
index 73c0546b..3127f612 100644
--- a/tests/mem-leaks/agent.vcproj
+++ b/tests/mem-leaks/agent.vcproj
@@ -41,7 +41,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories=".;..\..\agent;..\..\agent\tcf\system\Windows;..\..\agent\tcf\machine\i386"
+ AdditionalIncludeDirectories=".;..\..\agent;..\..\agent\system\Windows;..\..\agent\machine\i386"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@@ -116,7 +116,7 @@
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
- AdditionalIncludeDirectories=".;..\..\agent;..\..\agent\tcf\system\Windows;..\..\agent\tcf\machine\i386"
+ AdditionalIncludeDirectories=".;..\..\agent;..\..\agent\system\Windows;..\..\agent\machine\i386"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
@@ -612,27 +612,27 @@
Name="Windows"
>
<File
- RelativePath="..\..\agent\tcf\system\Windows\context-win32.c"
+ RelativePath="..\..\agent\system\Windows\tcf\context-win32.c"
>
</File>
<File
- RelativePath="..\..\agent\tcf\system\Windows\context-win32.h"
+ RelativePath="..\..\agent\system\Windows\tcf\context-win32.h"
>
</File>
<File
- RelativePath="..\..\agent\tcf\system\Windows\pthreads-win32.c"
+ RelativePath="..\..\agent\system\Windows\tcf\pthreads-win32.c"
>
</File>
<File
- RelativePath="..\..\agent\tcf\system\Windows\regset.h"
+ RelativePath="..\..\agent\system\Windows\tcf\regset.h"
>
</File>
<File
- RelativePath="..\..\agent\tcf\system\Windows\windbgcache.c"
+ RelativePath="..\..\agent\system\Windows\tcf\windbgcache.c"
>
</File>
<File
- RelativePath="..\..\agent\tcf\system\Windows\windbgcache.h"
+ RelativePath="..\..\agent\system\Windows\tcf\windbgcache.h"
>
</File>
</Filter>
diff --git a/tests/mem-leaks/tcf/services/memtrace.c b/tests/mem-leaks/tcf/services/memtrace.c
index 80a0f659..a4322b85 100644
--- a/tests/mem-leaks/tcf/services/memtrace.c
+++ b/tests/mem-leaks/tcf/services/memtrace.c
@@ -30,7 +30,7 @@
#include <tcf/services/linenumbers.h>
#include <tcf/services/memtrace.h>
#if defined(WIN32)
-# include <tcf/system/Windows/context-win32.h>
+# include <system/Windows/tcf/context-win32.h>
#endif
#define USE_DEBUG_REGS 0
@@ -43,7 +43,7 @@
#define FUNC_DESTROY 6
typedef struct EventPoint {
- char * name;
+ const char * name;
int heap_type;
int func_type;
} EventPoint;
@@ -127,8 +127,10 @@ static LINK mem_hash[MEM_HASH_SIZE];
static RegisterDefinition * reg_def_eax = NULL;
static RegisterDefinition * reg_def_esp = NULL;
static RegisterDefinition * reg_def_eip = NULL;
+#if defined(__x86_64__)
static RegisterDefinition * reg_def_rdi = NULL;
static RegisterDefinition * reg_def_rsi = NULL;
+#endif
#define link_mem2trace(x) ((StackTrace *)((char *)(x) - offsetof(StackTrace, link_all)))
#define link_mem2ret(x) ((ReturnPoint *)((char *)(x) - offsetof(ReturnPoint, link_mem)))
@@ -516,12 +518,14 @@ static int sort_func(const void * x, const void * y) {
static int print_text_pos_cnt = 0;
+#if SERVICE_LineNumbers
static void print_text_pos(CodeArea * area, void * args) {
if (print_text_pos_cnt == 0) {
printf(" %s %d\n", area->file, area->start_line);
}
print_text_pos_cnt++;
}
+#endif
#if !USE_DEBUG_REGS
static void rp_callback(Context * ctx, void * args) {
@@ -537,8 +541,10 @@ static void event_point(Context * ctx, void * args) {
StackFrame * info = NULL;
uint64_t esp = 0;
uint64_t eip = 0;
+#if defined(__x86_64__)
uint64_t rdi = 0;
uint64_t rsi = 0;
+#endif
ContextAddress buf[4];
MemorySpace * m = NULL;
static StackTrace trace;
@@ -691,11 +697,13 @@ static void event_point(Context * ctx, void * args) {
for (i = 0; i < 8 && i < cnt; i++) {
int j;
StackTrace * t = buf[i];
- printf(" curr %lld, total %lld, calls %d\n",
- (long long)t->size_current, (long long)t->size_total, t->call_cnt);
+ printf(" curr %" PRId64 ", total %" PRId64 ", calls %d\n",
+ (int64_t)t->size_current, (int64_t)t->size_total, t->call_cnt);
for (j = 0; j < t->frame_cnt; j++) {
print_text_pos_cnt = 0;
+#if SERVICE_LineNumbers
address_to_line(ctx, t->frames[j], t->frames[j] + 1, print_text_pos, NULL);
+#endif
if (print_text_pos_cnt == 0) {
printf(" 0x%" PRIX64 "\n", (uint64_t)t->frames[j]);
}
diff --git a/tests/test-dwarf/dwarf-test.vcproj b/tests/test-dwarf/dwarf-test.vcproj
index c4217bb1..aaddecaa 100644
--- a/tests/test-dwarf/dwarf-test.vcproj
+++ b/tests/test-dwarf/dwarf-test.vcproj
@@ -230,6 +230,10 @@
>
</File>
<File
+ RelativePath=".\tcf\framework\cpudefs-ext.h"
+ >
+ </File>
+ <File
RelativePath="..\..\agent\tcf\framework\cpudefs.c"
>
</File>
@@ -490,6 +494,14 @@
>
</File>
<File
+ RelativePath="..\..\agent\tcf\services\elf-loader.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\elf-loader.h"
+ >
+ </File>
+ <File
RelativePath="..\..\agent\tcf\services\expressions.c"
>
</File>
@@ -647,22 +659,6 @@
</File>
</Filter>
<Filter
- Name="machine"
- >
- <File
- RelativePath=".\tcf\machine\cpudefs-ext.h"
- >
- </File>
- <Filter
- Name="i386"
- >
- <File
- RelativePath="..\..\agent\tcf\machine\i386\elf-mdep.h"
- >
- </File>
- </Filter>
- </Filter>
- <Filter
Name="backend"
>
<File
@@ -678,7 +674,7 @@
Name="system"
>
<File
- RelativePath="..\..\agent\tcf\system\Windows\pthreads-win32.c"
+ RelativePath="..\..\agent\system\Windows\tcf\pthreads-win32.c"
>
</File>
</Filter>
diff --git a/tests/test-dwarf/tcf/backend/backend.c b/tests/test-dwarf/tcf/backend/backend.c
index 6c914a93..6094a3fc 100644
--- a/tests/test-dwarf/tcf/backend/backend.c
+++ b/tests/test-dwarf/tcf/backend/backend.c
@@ -208,12 +208,14 @@ static void loc_var_func(void * args, Symbol * sym) {
error("get_symbol_name");
}
if (get_symbol_address(sym, &addr) < 0) {
- int err = errno;
if ((get_symbol_register(sym, &ctx, &frame, &reg) < 0 || reg == NULL) &&
(get_symbol_value(sym, &value, &value_size, &value_big_endian) < 0 || value == NULL)) {
+ int err = errno;
+ if (strncmp(errno_to_str(err), "Object location or value info not available", 43) == 0) return;
if (strncmp(errno_to_str(err), "No object location info found", 29) == 0) return;
if (strncmp(errno_to_str(err), "Object is not available", 23) == 0) return;
if (strncmp(errno_to_str(err), "Object has no RT address", 24) == 0) return;
+ if (strncmp(errno_to_str(err), "Division by zero in DWARF", 25) == 0) return;
errno = err;
error("get_symbol_address");
}
@@ -226,7 +228,7 @@ static void loc_var_func(void * args, Symbol * sym) {
}
if (get_symbol_size(sym, &size) < 0) {
int ok = 0;
- if (name == NULL && type != NULL) {
+ if (type != NULL) {
char * type_name;
unsigned type_flags;
if (get_symbol_name(type, &type_name) < 0) {
@@ -235,7 +237,7 @@ static void loc_var_func(void * args, Symbol * sym) {
if (get_symbol_flags(type, &type_flags) < 0) {
error("get_symbol_flags");
}
- if (type_name != NULL && strcmp(type_name, "exception") == 0 && (type_flags & SYM_FLAG_CLASS_TYPE)) {
+ if (name == NULL && type_name != NULL && strcmp(type_name, "exception") == 0 && (type_flags & SYM_FLAG_CLASS_TYPE)) {
/* GCC does not tell size of std::exception class */
ok = 1;
}
@@ -314,6 +316,8 @@ static void next_pc(void) {
mem_region_pos++;
pc = 0;
print_time(time_start, test_cnt);
+ post_event_with_delay(test, NULL, 1000000);
+ test_posted = 1;
return;
}
@@ -326,6 +330,8 @@ static void next_pc(void) {
mem_region_pos++;
pc = 0;
print_time(time_start, test_cnt);
+ post_event_with_delay(test, NULL, 1000000);
+ test_posted = 1;
return;
}
}
@@ -415,7 +421,7 @@ static void next_pc(void) {
time_start = time_now;
loaded = 0;
}
- else if (test_cnt >= 100000) {
+ else if (test_cnt >= 1000) {
print_time(time_start, test_cnt);
clock_gettime(CLOCK_REALTIME, &time_start);
test_posted = 1;
@@ -442,7 +448,7 @@ static void next_file(void) {
clock_gettime(CLOCK_REALTIME, &time_start);
- f = elf_open(elf_file_name);;
+ f = elf_open(elf_file_name);
if (f == NULL) {
printf("Cannot open ELF: %s\n", errno_to_str(errno));
exit(1);
@@ -520,7 +526,7 @@ static void next_file(void) {
RegisterDefinition * r = reg_defs + j;
r->big_endian = f->big_endian;
r->dwarf_id = (int16_t)(j == 0 ? -1 : j - 1);
- r->eh_frame_id = -1;
+ r->eh_frame_id = r->dwarf_id;
r->name = reg_names[j];
snprintf(reg_names[j], sizeof(reg_names[j]), "R%d", j);
r->offset = reg_size;
@@ -547,15 +553,7 @@ static void test(void * args) {
}
}
-static void on_elf_file_closed(ELF_File * f) {
- if (!test_posted) {
- test_posted = 1;
- post_event(test, NULL);
- }
-}
-
-void init_contexts_sys_dep(void) {
- const char * dir_name = "files";
+static void add_dir(const char * dir_name) {
DIR * dir = opendir(dir_name);
if (dir == NULL) {
printf("Cannot open '%s' directory\n", dir_name);
@@ -567,17 +565,29 @@ void init_contexts_sys_dep(void) {
char path[FILE_PATH_SIZE];
struct stat st;
if (e == NULL) break;
+ if (strcmp(e->d_name, ".") == 0) continue;
+ if (strcmp(e->d_name, "..") == 0) continue;
+ if (strcmp(e->d_name + strlen(e->d_name) - 6, ".debug") == 0) continue;
snprintf(path, sizeof(path), "%s/%s", dir_name, e->d_name);
- if (stat(path, &st) == 0 && !S_ISDIR(st.st_mode)) {
- if (files_cnt >= files_max) {
- files_max += 8;
- files = (char **)loc_realloc(files, files_max * sizeof(char *));
+ if (stat(path, &st) == 0) {
+ if (S_ISDIR(st.st_mode)) {
+ add_dir(path);
+ }
+ else {
+ if (files_cnt >= files_max) {
+ files_max += 8;
+ files = (char **)loc_realloc(files, files_max * sizeof(char *));
+ }
+ files[files_cnt++] = loc_strdup(path);
}
- files[files_cnt++] = loc_strdup(path);
}
}
closedir(dir);
- elf_add_close_listener(on_elf_file_closed);
+}
+
+void init_contexts_sys_dep(void) {
+ const char * dir_name = "files";
+ add_dir(dir_name);
test_posted = 1;
post_event(test, NULL);
}

Back to the top