diff options
author | eutarass | 2011-09-12 21:38:37 +0000 |
---|---|---|
committer | eutarass | 2011-09-12 21:38:37 +0000 |
commit | 42b76b7aabb36ce114f74186527157e035e3c91c (patch) | |
tree | 558bed3d50c47e062b55da9f30df58273a3c1f61 | |
parent | b81c6fd3fa909779abf1e3ba9923481c8a402f66 (diff) | |
download | org.eclipse.tcf.agent-42b76b7aabb36ce114f74186527157e035e3c91c.tar.gz org.eclipse.tcf.agent-42b76b7aabb36ce114f74186527157e035e3c91c.tar.xz org.eclipse.tcf.agent-42b76b7aabb36ce114f74186527157e035e3c91c.zip |
TCF Agent: implemented translation of breakpoint file names.
-rw-r--r-- | server/services/context-proxy.c | 4 | ||||
-rw-r--r-- | services/breakpoints.c | 23 | ||||
-rw-r--r-- | services/linenumbers.c | 2 | ||||
-rw-r--r-- | services/linenumbers.h | 2 | ||||
-rw-r--r-- | services/linenumbers_elf.c | 18 | ||||
-rw-r--r-- | services/linenumbers_win32.c | 3 | ||||
-rw-r--r-- | services/pathmap.c | 52 | ||||
-rw-r--r-- | services/pathmap.h | 27 | ||||
-rw-r--r-- | services/tcf_elf.c | 16 |
9 files changed, 114 insertions, 33 deletions
diff --git a/server/services/context-proxy.c b/server/services/context-proxy.c index ae4a2158..850eb5d5 100644 --- a/server/services/context-proxy.c +++ b/server/services/context-proxy.c @@ -994,8 +994,8 @@ static void read_memory_map_item(InputStream * inp, void * args) { memset(m, 0, sizeof(MemoryRegion)); if (json_read_struct(inp, read_memory_region_property, m) && m->file_name != NULL) { struct stat buf; - char * fnm = path_map_to_local(c, m->file_name); - if (fnm != NULL) { + char * fnm = apply_path_map(c, m->file_name, PATH_MAP_TO_LOCAL); + if (fnm != m->file_name) { loc_free(m->file_name); m->file_name = loc_strdup(fnm); } diff --git a/services/breakpoints.c b/services/breakpoints.c index f96a8ee3..8d46a2dd 100644 --- a/services/breakpoints.c +++ b/services/breakpoints.c @@ -44,6 +44,7 @@ #include <services/linenumbers.h> #include <services/stacktrace.h> #include <services/memorymap.h> +#include <services/pathmap.h> typedef struct BreakpointRef BreakpointRef; typedef struct BreakpointAttribute BreakpointAttribute; @@ -1048,7 +1049,7 @@ static void evaluate_text_location(void * x) { bp_ip = 0; assert(cache_enter_cnt > 0); - if (line_to_address(args->ctx, bp->file, bp->line, bp->column, plant_breakpoint_address_iterator, args) < 0) { + if (line_to_address(args->ctx, cache_channel(), bp->file, bp->line, bp->column, plant_breakpoint_address_iterator, args) < 0) { address_expression_error(args->ctx, bp, errno); } if (bp_ip != 0) plant_at_address_expression(args->ctx, bp_ip, args->bp); @@ -2404,6 +2405,18 @@ static void event_code_unmapped(Context * ctx, ContextAddress addr, ContextAddre } #endif +#if SERVICE_PathMap +static void event_path_map_changed(Channel * c, void * args) { + unsigned hash = (unsigned)(uintptr_t)c / 16 % INP2BR_HASH_SIZE; + LINK * l = inp2br[hash].next; + while (l != &inp2br[hash]) { + BreakpointRef * br = link_inp2br(l); + l = l->next; + if (br->channel == c && br->bp->file != NULL) replant_breakpoint(br->bp); + } +} +#endif + static void channel_close_listener(Channel * c) { delete_breakpoint_refs(c); } @@ -2434,6 +2447,14 @@ void ini_breakpoints_service(Protocol * proto, TCFBroadcastGroup * bcg) { add_memory_map_event_listener(&listener, NULL); } #endif +#if SERVICE_PathMap + { + static PathMapEventListener listener = { + event_path_map_changed, + }; + add_path_map_event_listener(&listener, NULL); + } +#endif list_init(&breakpoints); list_init(&instructions); list_init(&evaluations_posted); diff --git a/services/linenumbers.c b/services/linenumbers.c index 7ed0d8e1..5bdfdd11 100644 --- a/services/linenumbers.c +++ b/services/linenumbers.c @@ -215,7 +215,7 @@ static void map_to_memory_cache_client(void * x) { code_area_cnt = 0; - if (err == 0 && line_to_address(ctx, args->file, + if (err == 0 && line_to_address(ctx, cache_channel(), args->file, args->line, args->column, add_code_area, NULL) < 0) err = errno; cache_exit(); diff --git a/services/linenumbers.h b/services/linenumbers.h index 3e43c970..c891f902 100644 --- a/services/linenumbers.h +++ b/services/linenumbers.h @@ -45,7 +45,7 @@ typedef struct CodeArea { typedef void LineNumbersCallBack(CodeArea *, void *); -extern int line_to_address(Context * ctx, char * file, int line, int column, LineNumbersCallBack * client, void * args); +extern int line_to_address(Context * ctx, Channel * chnl, char * file, int line, int column, LineNumbersCallBack * client, void * args); extern int address_to_line(Context * ctx, ContextAddress addr0, ContextAddress addr1, LineNumbersCallBack * client, void * args); diff --git a/services/linenumbers_elf.c b/services/linenumbers_elf.c index 039076f2..e67a861c 100644 --- a/services/linenumbers_elf.c +++ b/services/linenumbers_elf.c @@ -40,6 +40,7 @@ #include <services/dwarf.h> #include <services/dwarfcache.h> #include <services/stacktrace.h> +#include <services/pathmap.h> static int is_absolute_path(char * fnm) { if (fnm[0] == '/') return 1; @@ -73,12 +74,15 @@ static void canonic_path(char * fnm, char * buf, size_t buf_size) { } } } + if (i == 0 && ch >= 'a' && ch <= 'z' && *fnm == ':') { + ch = ch - 'a' + 'A'; + } buf[i++] = ch; } buf[i++] = 0; } -static int compare_path(char * file, char * pwd, char * dir, char * name) { +static int compare_path(Channel * chnl, char * file, char * pwd, char * dir, char * name) { int i, j; char buf[FILE_PATH_SIZE]; @@ -103,7 +107,12 @@ static int compare_path(char * file, char * pwd, char * dir, char * name) { else { canonic_path(name, buf, sizeof(buf)); } - +#if SERVICE_PathMap + { + char * cnm = apply_path_map(chnl, buf, PATH_MAP_TO_CLIENT); + if (cnm != buf) canonic_path(cnm, buf, sizeof(buf)); + } +#endif i = strlen(file); j = strlen(buf); return i <= j && strcmp(file, buf + j - i) == 0; @@ -204,7 +213,8 @@ static void unit_line_to_address(Context * ctx, CompUnit * unit, unsigned file, } } -int line_to_address(Context * ctx, char * file_name, int line, int column, LineNumbersCallBack * client, void * args) { +int line_to_address(Context * ctx, Channel * chnl, char * file_name, int line, int column, + LineNumbersCallBack * client, void * args) { int err = 0; if (ctx == NULL) err = ERR_INV_CONTEXT; @@ -232,7 +242,7 @@ int line_to_address(Context * ctx, char * file_name, int line, int column, LineN if (cache->mFileInfoHash) { FileInfo * f = cache->mFileInfoHash[h % cache->mFileInfoHashSize]; while (f != NULL) { - if (f->mNameHash == h && compare_path(fnm, f->mCompUnit->mDir, f->mDir, f->mName)) { + if (f->mNameHash == h && compare_path(chnl, fnm, f->mCompUnit->mDir, f->mDir, f->mName)) { CompUnit * unit = f->mCompUnit; unsigned j = f - unit->mFiles; unit_line_to_address(ctx, unit, j, line, column, client, args); diff --git a/services/linenumbers_win32.c b/services/linenumbers_win32.c index 892ea824..fdaf74c1 100644 --- a/services/linenumbers_win32.c +++ b/services/linenumbers_win32.c @@ -34,7 +34,8 @@ #include <system/Windows/windbgcache.h> #include <system/Windows/context-win32.h> -int line_to_address(Context * ctx, char * file, int line, int column, LineNumbersCallBack * callback, void * user_args) { +int line_to_address(Context * ctx, Channel * chnl, char * file, int line, int column, + LineNumbersCallBack * callback, void * user_args) { int err = 0; if (ctx == NULL) err = ERR_INV_CONTEXT; diff --git a/services/pathmap.c b/services/pathmap.c index e4af7d08..c973f4c3 100644 --- a/services/pathmap.c +++ b/services/pathmap.c @@ -30,6 +30,11 @@ #include <framework/myalloc.h> #include <services/pathmap.h> +typedef struct Listener { + PathMapEventListener * listener; + void * args; +} Listener; + typedef struct PathMapRuleAttr { char * name; char * value; @@ -58,6 +63,30 @@ static int ini_done = 0; static LINK maps; static char host_name[256]; +static Listener * listeners = NULL; +static unsigned listener_cnt = 0; +static unsigned listener_max = 0; + +static void path_map_event_mapping_changed(Channel * c) { + unsigned i; + for (i = 0; i < listener_cnt; i++) { + Listener * l = listeners + i; + if (l->listener->mapping_changed == NULL) continue; + l->listener->mapping_changed(c, l->args); + } +} + +void add_path_map_event_listener(PathMapEventListener * listener, void * client_data) { + Listener * l = NULL; + if (listener_cnt >= listener_max) { + listener_max += 8; + listeners = (Listener *)loc_realloc(listeners, listener_max * sizeof(Listener)); + } + l = listeners + listener_cnt++; + l->listener = listener; + l->args = client_data; +} + static PathMap * find_map(Channel * c) { LINK * l; for (l = maps.next; l != &maps; l = l->next) { @@ -80,7 +109,7 @@ static int is_my_host(char * host) { return strcasecmp(host, host_name) == 0; } -static char * map_to_local(PathMap * m, char * fnm) { +static char * map_file_name(PathMap * m, char * fnm, int mode) { unsigned i, j, k; static char buf[FILE_PATH_SIZE]; @@ -101,35 +130,39 @@ static char * map_to_local(PathMap * m, char * fnm) { if (src == NULL || src[0] == 0) continue; if (dst == NULL || dst[0] == 0) continue; if (prot != NULL && prot[0] != 0 && strcasecmp(prot, "file")) continue; - if (!is_my_host(host)) continue; + switch (mode) { + case PATH_MAP_TO_LOCAL: + if (host && !is_my_host(host)) continue; + break; + } k = strlen(src); if (strncmp(src, fnm, k)) continue; if (fnm[k] != 0 && fnm[k] != '/' && fnm[k] != '\\') continue; j = strlen(dst) - 1; if (fnm[k] != 0 && (dst[j] == '/' || dst[j] == '\\')) k++; snprintf(buf, sizeof(buf), "%s%s", dst, fnm + k); - if (stat(buf, &st) == 0) return buf; + if (mode != PATH_MAP_TO_LOCAL || stat(buf, &st) == 0) return buf; } - return NULL; + return fnm; } -char * path_map_to_local(Channel * c, char * fnm) { +char * apply_path_map(Channel * c, char * fnm, int mode) { if (c == NULL) { LINK * l = maps.next; while (l != &maps) { PathMap * m = maps2map(l); - char * lnm = map_to_local(m, fnm); - if (lnm != NULL) return lnm; + char * lnm = map_file_name(m, fnm, mode); + if (lnm != fnm) return lnm; l = l->next; } } else { PathMap * m = find_map(c); if (m == NULL) return NULL; - return map_to_local(m, fnm); + return map_file_name(m, fnm, mode); } - return NULL; + return fnm; } static void write_rule(OutputStream * out, PathMapRule * r) { @@ -202,6 +235,7 @@ void set_path_map(Channel * c, InputStream * inp) { m->rules_cnt = 0; } json_read_array(inp, read_rule, m); + path_map_event_mapping_changed(c); } static void command_get(char * token, Channel * c) { diff --git a/services/pathmap.h b/services/pathmap.h index 94e40d37..d931a7c1 100644 --- a/services/pathmap.h +++ b/services/pathmap.h @@ -24,18 +24,37 @@ #include <config.h> #include <framework/protocol.h> +#if SERVICE_PathMap + +#define PATH_MAP_TO_CLIENT 1 +#define PATH_MAP_TO_LOCAL 2 +#define PATH_MAP_TO_TARGET 3 + +/* + * Path map listener. + */ +typedef struct PathMapEventListener { + void (*mapping_changed)(Channel * c, void * client_data); +} PathMapEventListener; + /* - * Translate debug file name to local name using file path mapping table of given channel. - * Return pointer to static buffer that contains translated file name, - * or null if mapping not found. + * Translate debug file name to local or target file name using file path mapping table of given channel. + * Return pointer to static buffer that contains translated file name. */ -extern char * path_map_to_local(Channel * channel, char * file_name); +extern char * apply_path_map(Channel * channel, char * file_name, int mode); /* * Read new path map from the given input stream. */ extern void set_path_map(Channel * c, InputStream * inp); +/* + * Add path map listener. + */ +extern void add_path_map_event_listener(PathMapEventListener * listener, void * client_data); + extern void ini_path_map_service(Protocol * proto); +#endif /* SERVICE_PathMap */ + #endif /* D_pathmap */ diff --git a/services/tcf_elf.c b/services/tcf_elf.c index 68cf9c53..2c5e7bce 100644 --- a/services/tcf_elf.c +++ b/services/tcf_elf.c @@ -251,6 +251,7 @@ static char * get_debug_info_file_name(ELF_File * file, int * error) { while (offs % 4 != 0) offs++; if (type == 3 && strcmp(name, "GNU") == 0) { char fnm[FILE_PATH_SIZE]; + char * lnm = fnm; struct stat buf; char id[64]; size_t id_size = 0; @@ -265,13 +266,10 @@ static char * get_debug_info_file_name(ELF_File * file, int * error) { id[id_size++] = 0; trace(LOG_ELF, "Found GNU build ID %s", id); snprintf(fnm, sizeof(fnm), "/usr/lib/debug/.build-id/%.2s/%s.debug", id, id + 2); - if (stat(fnm, &buf) == 0) return loc_strdup(fnm); #if SERVICE_PathMap - { - char * lnm = path_map_to_local(NULL, fnm); - if (lnm != NULL) return loc_strdup(lnm); - } + lnm = apply_path_map(NULL, lnm, PATH_MAP_TO_LOCAL); #endif + if (stat(lnm, &buf) == 0) return loc_strdup(lnm); return NULL; } offs += desc_sz; @@ -286,6 +284,7 @@ static char * get_debug_info_file_name(ELF_File * file, int * error) { else { /* TODO: check debug info CRC */ char fnm[FILE_PATH_SIZE]; + char * lnm = fnm; struct stat buf; char * name = (char *)sec->data; int l = strlen(file->name); @@ -297,13 +296,10 @@ static char * get_debug_info_file_name(ELF_File * file, int * error) { snprintf(fnm, sizeof(fnm), "%.*s.debug/%s", l, file->name, name); if (stat(fnm, &buf) == 0) return loc_strdup(fnm); snprintf(fnm, sizeof(fnm), "/usr/lib/debug%.*s%s", l, file->name, name); - if (stat(fnm, &buf) == 0) return loc_strdup(fnm); #if SERVICE_PathMap - { - char * lnm = path_map_to_local(NULL, fnm); - if (lnm != NULL) return loc_strdup(lnm); - } + lnm = apply_path_map(NULL, lnm, PATH_MAP_TO_LOCAL); #endif + if (stat(lnm, &buf) == 0) return loc_strdup(lnm); return NULL; } } |