summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenoit Perrin2012-09-27 11:13:10 (EDT)
committer Eugene Tarassov2012-10-02 11:36:19 (EDT)
commit9a8b647992de129297eb2e3c41d3726889f167a2 (patch)
tree31b05a51dba8e36200e46a8decaa00be122a820d
parentccfe5f44972503042d9498dd6f572bdb59cabbff (diff)
downloadorg.eclipse.tcf.agent-9a8b647992de129297eb2e3c41d3726889f167a2.zip
org.eclipse.tcf.agent-9a8b647992de129297eb2e3c41d3726889f167a2.tar.gz
org.eclipse.tcf.agent-9a8b647992de129297eb2e3c41d3726889f167a2.tar.bz2
Add support of the enumeration of ELF symbols.
-rw-r--r--agent/tcf/services/symbols_elf.c197
-rw-r--r--agent/tcf/services/symbols_elf.h54
2 files changed, 224 insertions, 27 deletions
diff --git a/agent/tcf/services/symbols_elf.c b/agent/tcf/services/symbols_elf.c
index 7816f2c..2612e4f 100644
--- a/agent/tcf/services/symbols_elf.c
+++ b/agent/tcf/services/symbols_elf.c
@@ -46,6 +46,7 @@
#include <tcf/services/stacktrace.h>
#include <tcf/services/funccall.h>
#include <tcf/services/symbols.h>
+#include <tcf/services/symbols_elf.h>
#include <tcf/services/vm.h>
#if ENABLE_RCBP_TEST
# include <tcf/main/test.h>
@@ -219,6 +220,37 @@ static int syminfo2address(Context * ctx, ELF_SymbolInfo * info, ContextAddress
return -1;
}
+static int syminfo2symbol (ELF_SymbolInfo * sym_info, Symbol ** symbol) {
+ Symbol * sym = alloc_symbol();
+
+ sym->frame = STACK_NO_FRAME;
+ sym->ctx = context_get_group(sym_ctx, CONTEXT_GROUP_SYMBOLS);
+ sym->tbl = sym_info->sym_section;
+ sym->index = sym_info->sym_index;
+
+ switch (sym_info->type) {
+ case STT_NOTYPE:
+ /* Check if the NOTYPE symbol is for a section allocated in memory */
+ if (sym_info->section == NULL || (sym_info->section->flags & SHF_ALLOC) == 0) {
+ sym->sym_class = SYM_CLASS_VALUE;
+ break;
+ }
+ /* fall through */
+ case STT_FUNC:
+ case STT_GNU_IFUNC:
+ sym->sym_class = SYM_CLASS_FUNCTION;
+ break;
+ case STT_OBJECT:
+ sym->sym_class = SYM_CLASS_REFERENCE;
+ break;
+ default:
+ sym->sym_class = SYM_CLASS_VALUE;
+ break;
+ }
+ *symbol = sym;
+ return 0;
+}
+
/* Return 1 if evaluation of symbol properties requires a stack frame.
* Return 0 otherwise.
* In case of a doubt, should return 1. */
@@ -629,6 +661,12 @@ static void add_obj_to_find_symbol_buf(ObjectInfo * obj, unsigned level) {
sym->level = level;
}
+static void add_elf_to_find_symbol_buf(ELF_SymbolInfo * elf_sym) {
+ Symbol * sym = NULL;
+ syminfo2symbol(elf_sym, &sym);
+ add_to_find_symbol_buf(sym);
+}
+
static void sort_find_symbol_buf(void) {
/* Sort find_symbol_list:
* 1. inner scope before parent scope
@@ -927,33 +965,8 @@ static void find_by_name_in_sym_table(ELF_File * file, const char * name, int gl
}
}
}
- {
- Symbol * sym = alloc_symbol();
- sym->frame = STACK_NO_FRAME;
- sym->ctx = prs;
- sym->tbl = tbl;
- sym->index = n;
- switch (sym_info.type) {
- case STT_NOTYPE:
- /* Check if the NOTYPE symbol is for a section allocated in memory */
- if (sym_info.section == NULL || (sym_info.section->flags & SHF_ALLOC) == 0) {
- sym->sym_class = SYM_CLASS_VALUE;
- break;
- }
- /* fall through */
- case STT_FUNC:
- case STT_GNU_IFUNC:
- sym->sym_class = SYM_CLASS_FUNCTION;
- break;
- case STT_OBJECT:
- sym->sym_class = SYM_CLASS_REFERENCE;
- break;
- default:
- sym->sym_class = SYM_CLASS_VALUE;
- break;
- }
- add_to_find_symbol_buf(sym);
- }
+
+ add_elf_to_find_symbol_buf(&sym_info);
}
n = tbl->sym_names_next[n];
}
@@ -3241,4 +3254,134 @@ int get_funccall_info(const Symbol * func,
return -1;
}
+/* -------------------------------------------------------------------------- */
+
+struct EnumerateSymbols {
+ int64_t mtime;
+ ino_t ino;
+ dev_t dev;
+ uint32_t batch_idx;
+ uint32_t sec_idx;
+ char file_name[FILE_PATH_SIZE];
+ char ctxId[256];
+};
+
+static int enumerate_symbol_table (ELF_Section * sec, EnumerateSymbols * enum_syms, EnumerateBatchSymbolsCallBack * call_back, void * args) {
+ uint32_t sym_idx;
+ int cont = 1;
+ int has_more = 0;
+
+ for (sym_idx = enum_syms->batch_idx; cont == 1 && sym_idx < sec->sym_count; sym_idx++) {
+ ELF_SymbolInfo sym_info;
+ Symbol * sym;
+
+ unpack_elf_symbol_info(sec, sym_idx, &sym_info);
+
+ if (syminfo2symbol (&sym_info, &sym) < 0) exception (errno);
+
+ cont = call_back (args, sym);
+ }
+ enum_syms->batch_idx = sym_idx;
+ if (sym_idx < sec->sym_count && cont != -1) has_more = 1;
+ return has_more;
+}
+
+int elf_enumerate_symbols (Context * ctx, const char * file_name, EnumerateSymbols ** enum_syms, EnumerateBatchSymbolsCallBack * call_back, void * args) {
+ Trap trap;
+ ELF_File * file;
+ unsigned sec_idx;
+ int has_more = 0;
+
+ if (!set_trap(&trap)) {
+ loc_free (*enum_syms);
+ *enum_syms = NULL;
+ return -1;
+ }
+
+ if (ctx == NULL && file_name == NULL) {
+ assert (*enum_syms != NULL);
+
+ file = elf_open ((*enum_syms)->file_name);
+ if (file == NULL) exception (errno);
+
+ /*
+ * Check that the file is identical to the initial file and the context
+ * still exists.
+ */
+
+ if (file->ino != (*enum_syms)->ino || file->dev != (*enum_syms)->dev || file->mtime != (*enum_syms)->mtime) {
+ str_exception(ERR_OTHER, "The elf symbol file has changed");
+ }
+ else {
+ ctx = id2ctx((*enum_syms)->ctxId);
+ if (ctx == NULL) exception (ERR_INV_CONTEXT);
+ else if (ctx->exited) exception (ERR_ALREADY_EXITED);
+ }
+ sec_idx = (*enum_syms)->sec_idx;
+ }
+ else {
+ unsigned symtab_idx = 0;
+ unsigned dynsym_idx = 0;
+ unsigned ix;
+
+ assert (file_name != NULL && enum_syms != NULL && *enum_syms == NULL);
+
+ file = elf_open (file_name);
+ if (file == NULL) exception (errno);
+
+ if (file->sections == NULL) str_exception(ERR_OTHER, "The file does not have sections");
+
+ /* Look for the symbol table sections */
+
+ for (ix = 0; ix < file->section_cnt && symtab_idx == 0 && dynsym_idx == 0; ix++) {
+ ELF_Section * sec = file->sections + ix;
+ if (sec->type == SHT_SYMTAB) symtab_idx = ix;
+ else if (sec->type == SHT_DYNSYM) dynsym_idx = ix;
+ }
+
+ if (symtab_idx == 0 && dynsym_idx == 0) str_exception(ERR_OTHER, "The file does not have a symbol table");
+
+ /* Set priority to the symbol table */
+
+ if (symtab_idx != 0) sec_idx = symtab_idx;
+ else sec_idx = dynsym_idx;
+
+ *enum_syms = loc_alloc_zero (sizeof (EnumerateSymbols));
+ strlcpy ((*enum_syms)->file_name, file_name, sizeof ((*enum_syms)->file_name));
+ if (strlen (file_name) != strlen ((*enum_syms)->file_name)) str_exception (ERR_OTHER, "File pathname too long");
+
+ strlcpy ((*enum_syms)->ctxId, ctx->id, sizeof ((*enum_syms)->ctxId));
+ (*enum_syms)->dev = file->dev;
+ (*enum_syms)->ino = file->ino;
+ (*enum_syms)->mtime = file->mtime;
+ (*enum_syms)->sec_idx = sec_idx;
+ }
+
+ if (get_sym_context(ctx, STACK_NO_FRAME, 0) < 0) exception(errno);
+
+ has_more = enumerate_symbol_table(file->sections + sec_idx, *enum_syms, call_back, args);
+
+ clear_trap(&trap);
+
+ if (has_more == 0) {
+ loc_free (*enum_syms);
+ *enum_syms = NULL;
+ }
+
+ return has_more;
+}
+
+int elf_symbol_info (Symbol * sym, ELF_SymbolInfo * elf_sym) {
+ Trap trap;
+
+ assert (sym != NULL && sym->magic == SYMBOL_MAGIC && sym->tbl != NULL);
+
+ if (!set_trap(&trap)) return -1;
+
+ unpack_elf_symbol_info(sym->tbl, sym->index, elf_sym);
+
+ clear_trap(&trap);
+ return 0;
+}
+
#endif /* SERVICE_Symbols && ENABLE_ELF */
diff --git a/agent/tcf/services/symbols_elf.h b/agent/tcf/services/symbols_elf.h
new file mode 100644
index 0000000..96843e6
--- /dev/null
+++ b/agent/tcf/services/symbols_elf.h
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2012 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 specific ELF symbol's API
+ */
+#ifndef D_symbols_elf
+#define D_symbols_elf
+
+#include <tcf/config.h>
+
+#if SERVICE_Symbols && !ENABLE_SymbolsProxy && ENABLE_ELF
+
+#include <tcf/framework/context.h>
+#include <tcf/services/symbols.h>
+#include <tcf/services/tcf_elf.h>
+
+typedef struct EnumerateSymbols EnumerateSymbols;
+typedef int EnumerateBatchSymbolsCallBack(void *, Symbol *);
+
+/*
+ * Enumerate ELF symbols of a specific file for a given context.
+ * The API supports enumeration by batchs of symbols. If the callback returns
+ * 0, the function returns, ending a batch. Subsequent calls with a NULL
+ * context and file_name is used to enumerate the next batch of symbols. If
+ * the callback return -1, the enumeration ends.
+ * On error returns -1 and sets errno.
+ * On success returns 0 if there isn't more symbols, or a positive value if
+ * there are other symbols to retrieve.
+ */
+extern int elf_enumerate_symbols (Context * ctx, const char * file_name, EnumerateSymbols ** enum_syms, EnumerateBatchSymbolsCallBack * call_back, void * args);
+
+/*
+ * Get the ELF symbol info from a TCF symbol.
+ * On error returns -1 and sets errno.
+ * On success returns 0.
+ */
+extern int elf_symbol_info (Symbol * sym, ELF_SymbolInfo * elf_sym);
+
+#endif /* SERVICE_Symbols && !ENABLE_SymbolsProxy && ENABLE_ELF */
+
+#endif /* D_symbols_elf */