TCF Server: fixed symbols server support of stepping over inlined functions
diff --git a/agent/tcf/services/linenumbers.c b/agent/tcf/services/linenumbers.c
index 2208d06..b8bf0fa 100644
--- a/agent/tcf/services/linenumbers.c
+++ b/agent/tcf/services/linenumbers.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2013 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2015 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.
@@ -22,7 +22,7 @@
#include <tcf/config.h>
-#if SERVICE_LineNumbers
+#if ENABLE_DebugContext
#include <errno.h>
#include <assert.h>
@@ -36,33 +36,32 @@
#include <tcf/framework/trace.h>
#include <tcf/services/linenumbers.h>
-#define MAX_AREA_CNT 0x1000
+static void read_code_area_props(InputStream * inp, const char * name, void * args) {
+ CodeArea * area = (CodeArea *)args;
+ if (strcmp(name, "SLine") == 0) area->start_line = json_read_long(inp);
+ else if (strcmp(name, "SCol") == 0) area->start_column = json_read_long(inp);
+ else if (strcmp(name, "SAddr") == 0) area->start_address = (ContextAddress)json_read_uint64(inp);
+ else if (strcmp(name, "ELine") == 0) area->end_line = json_read_long(inp);
+ else if (strcmp(name, "ECol") == 0) area->end_column = json_read_long(inp);
+ else if (strcmp(name, "EAddr") == 0) area->end_address = (ContextAddress)json_read_uint64(inp);
+ else if (strcmp(name, "NAddr") == 0) area->next_address = (ContextAddress)json_read_uint64(inp);
+ else if (strcmp(name, "File") == 0) area->file = json_read_alloc_string(inp);
+ else if (strcmp(name, "Dir") == 0) area->directory = json_read_alloc_string(inp);
+ else if (strcmp(name, "ISA") == 0) area->isa = json_read_long(inp);
+ else if (strcmp(name, "IsStmt") == 0) area->is_statement = json_read_boolean(inp);
+ else if (strcmp(name, "BasicBlock") == 0) area->basic_block = json_read_boolean(inp);
+ else if (strcmp(name, "PrologueEnd") == 0) area->prologue_end = json_read_boolean(inp);
+ else if (strcmp(name, "EpilogueBegin") == 0) area->epilogue_begin = json_read_boolean(inp);
+ else if (strcmp(name, "OpIndex") == 0) area->op_index = json_read_long(inp);
+ else if (strcmp(name, "Discriminator") == 0) area->discriminator = json_read_long(inp);
+}
-typedef struct MapToSourceArgs {
- char token[256];
- char id[256];
- ContextAddress addr0;
- ContextAddress addr1;
-} MapToSourceArgs;
+void read_code_area(InputStream * inp, CodeArea * area) {
+ memset(area, 0, sizeof(CodeArea));
+ json_read_struct(inp, read_code_area_props, area);
+}
-typedef struct MapToMemoryArgs {
- char token[256];
- char id[256];
- char * file;
- int line;
- int column;
-} MapToMemoryArgs;
-
-static int code_area_cnt = 0;
-static int code_area_max = 0;
-static CodeArea * code_area_buf = NULL;
-
-static const char * LINENUMBERS = "LineNumbers";
-
-static void write_line_info(OutputStream * out, int cnt) {
- CodeArea * area = code_area_buf + cnt;
- CodeArea * prev = cnt == 0 ? NULL : code_area_buf + cnt - 1;
-
+void write_code_area(OutputStream * out, CodeArea * area, CodeArea * prev) {
write_stream(out, '{');
json_write_string(out, "SAddr");
write_stream(out, ':');
@@ -160,6 +159,38 @@
write_stream(out, '}');
}
+#if SERVICE_LineNumbers
+
+#define MAX_AREA_CNT 0x1000
+
+typedef struct MapToSourceArgs {
+ char token[256];
+ char id[256];
+ ContextAddress addr0;
+ ContextAddress addr1;
+} MapToSourceArgs;
+
+typedef struct MapToMemoryArgs {
+ char token[256];
+ char id[256];
+ char * file;
+ int line;
+ int column;
+} MapToMemoryArgs;
+
+static int code_area_cnt = 0;
+static int code_area_max = 0;
+static CodeArea * code_area_buf = NULL;
+
+static const char * LINENUMBERS = "LineNumbers";
+
+static void write_line_info(OutputStream * out, int cnt) {
+ CodeArea * area = code_area_buf + cnt;
+ CodeArea * prev = cnt == 0 ? NULL : code_area_buf + cnt - 1;
+ write_code_area(out, area, prev);
+}
+
+
static void add_code_area(CodeArea * area, void * args) {
if (code_area_cnt >= code_area_max) {
if (code_area_max >= MAX_AREA_CNT) exception(ERR_BUFFER_OVERFLOW);
@@ -287,3 +318,4 @@
}
#endif /* SERVICE_LineNumbers */
+#endif /* ENABLE_DebugContext */
diff --git a/agent/tcf/services/linenumbers.h b/agent/tcf/services/linenumbers.h
index 1a76c85..788ce15 100644
--- a/agent/tcf/services/linenumbers.h
+++ b/agent/tcf/services/linenumbers.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2014 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2015 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.
@@ -24,6 +24,19 @@
#include <tcf/framework/protocol.h>
#include <tcf/framework/context.h>
+#include <tcf/framework/cpudefs.h>
+
+#if ENABLE_DebugContext
+
+/*
+ * Utility function: read code area data from JSON stream.
+ */
+extern void read_code_area(InputStream * inp, CodeArea * area);
+
+/*
+ * Utility function: write code area data into JSON stream.
+ */
+extern void write_code_area(OutputStream * out, CodeArea * area, CodeArea * prev);
#if ENABLE_LineNumbers
@@ -46,5 +59,6 @@
extern void ini_line_numbers_lib(void);
#endif /* ENABLE_LineNumbers */
+#endif /* ENABLE_DebugContext */
#endif /* D_linenumbers */
diff --git a/agent/tcf/services/linenumbers_proxy.c b/agent/tcf/services/linenumbers_proxy.c
index f376067..c2115de 100644
--- a/agent/tcf/services/linenumbers_proxy.c
+++ b/agent/tcf/services/linenumbers_proxy.c
@@ -155,26 +155,6 @@
return (h + ((uintptr_t)ctx >> 4) + (unsigned)line + (unsigned)column) % HASH_SIZE;
}
-static void read_code_area_props(InputStream * inp, const char * name, void * args) {
- CodeArea * area = (CodeArea *)args;
- if (strcmp(name, "SLine") == 0) area->start_line = json_read_long(inp);
- else if (strcmp(name, "SCol") == 0) area->start_column = json_read_long(inp);
- else if (strcmp(name, "SAddr") == 0) area->start_address = (ContextAddress)json_read_uint64(inp);
- else if (strcmp(name, "ELine") == 0) area->end_line = json_read_long(inp);
- else if (strcmp(name, "ECol") == 0) area->end_column = json_read_long(inp);
- else if (strcmp(name, "EAddr") == 0) area->end_address = (ContextAddress)json_read_uint64(inp);
- else if (strcmp(name, "NAddr") == 0) area->next_address = (ContextAddress)json_read_uint64(inp);
- else if (strcmp(name, "File") == 0) area->file = json_read_alloc_string(inp);
- else if (strcmp(name, "Dir") == 0) area->directory = json_read_alloc_string(inp);
- else if (strcmp(name, "ISA") == 0) area->isa = json_read_long(inp);
- else if (strcmp(name, "IsStmt") == 0) area->is_statement = json_read_boolean(inp);
- else if (strcmp(name, "BasicBlock") == 0) area->basic_block = json_read_boolean(inp);
- else if (strcmp(name, "PrologueEnd") == 0) area->prologue_end = json_read_boolean(inp);
- else if (strcmp(name, "EpilogueBegin") == 0) area->epilogue_begin = json_read_boolean(inp);
- else if (strcmp(name, "OpIndex") == 0) area->op_index = json_read_long(inp);
- else if (strcmp(name, "Discriminator") == 0) area->discriminator = json_read_long(inp);
-}
-
static void read_code_area_array(InputStream * inp, void * args) {
CodeArea * area = NULL;
if (code_area_cnt >= code_area_max) {
@@ -182,8 +162,7 @@
code_area_buf = (CodeArea *)loc_realloc(code_area_buf, sizeof(CodeArea) * code_area_max);
}
area = code_area_buf + code_area_cnt++;
- memset(area, 0, sizeof(CodeArea));
- json_read_struct(inp, read_code_area_props, area);
+ read_code_area(inp, area);
}
static void validate_cache_entry(Channel * c, void * args, int error) {
diff --git a/agent/tcf/services/stacktrace.c b/agent/tcf/services/stacktrace.c
index b3fb8a1..5aff535 100644
--- a/agent/tcf/services/stacktrace.c
+++ b/agent/tcf/services/stacktrace.c
@@ -34,9 +34,10 @@
#include <tcf/framework/cache.h>
#include <tcf/framework/exceptions.h>
#include <tcf/services/registers.h>
-#include <tcf/services/stacktrace.h>
#include <tcf/services/symbols.h>
+#include <tcf/services/linenumbers.h>
#include <tcf/services/memorymap.h>
+#include <tcf/services/stacktrace.h>
#define MAX_FRAMES 1000
@@ -95,7 +96,7 @@
*down->area = info->subs[down->inlined]->area;
if (down->area->directory) down->area->directory = loc_strdup(down->area->directory);
if (down->area->file) down->area->file = loc_strdup(down->area->file);
- frame->func_id = loc_strdup(symbol2id(info->subs[down->inlined]->sym));
+ frame->func_id = loc_strdup(info->subs[down->inlined]->func_id);
}
else {
int i;
@@ -339,57 +340,10 @@
}
if (d->info->area != NULL) {
- CodeArea * area = d->info->area;
write_stream(out, ',');
json_write_string(out, "CodeArea");
write_stream(out, ':');
- write_stream(out, '{');
- json_write_string(out, "SAddr");
- write_stream(out, ':');
- json_write_uint64(out, area->start_address);
- if (area->start_line > 0) {
- write_stream(out, ',');
- json_write_string(out, "SLine");
- write_stream(out, ':');
- json_write_ulong(out, area->start_line);
- if (area->start_column > 0) {
- write_stream(out, ',');
- json_write_string(out, "SCol");
- write_stream(out, ':');
- json_write_ulong(out, area->start_column);
- }
- }
- if (area->end_address != 0) {
- write_stream(out, ',');
- json_write_string(out, "EAddr");
- write_stream(out, ':');
- json_write_uint64(out, area->end_address);
- }
- if (area->end_line > 0) {
- write_stream(out, ',');
- json_write_string(out, "ELine");
- write_stream(out, ':');
- json_write_ulong(out, area->end_line);
- if (area->end_column > 0) {
- write_stream(out, ',');
- json_write_string(out, "ECol");
- write_stream(out, ':');
- json_write_ulong(out, area->end_column);
- }
- }
- if (area->file != NULL) {
- write_stream(out, ',');
- json_write_string(out, "File");
- write_stream(out, ':');
- json_write_string(out, area->file);
- }
- if (area->directory != NULL) {
- write_stream(out, ',');
- json_write_string(out, "Dir");
- write_stream(out, ':');
- json_write_string(out, area->directory);
- }
- write_stream(out, '}');
+ write_code_area(out, d->info->area, NULL);
}
if (d->ip_error == 0) {
diff --git a/agent/tcf/services/symbols.c b/agent/tcf/services/symbols.c
index a4c7c32..df7b978 100644
--- a/agent/tcf/services/symbols.c
+++ b/agent/tcf/services/symbols.c
@@ -26,6 +26,7 @@
#include <tcf/framework/cache.h>
#include <tcf/services/stacktrace.h>
#include <tcf/services/memorymap.h>
+#include <tcf/services/linenumbers.h>
#include <tcf/services/symbols.h>
#include <tcf/services/vm.h>
@@ -782,6 +783,28 @@
}
}
+static void write_inlined_subroutine_info(OutputStream * out, StackFrameInlinedSubroutine * info) {
+ unsigned cnt = 0;
+
+ write_stream(out, '{');
+
+ if (info->func_id != NULL) {
+ if (cnt++ > 0) write_stream(out, ',');
+ json_write_string(out, "ID");
+ write_stream(out, ':');
+ json_write_string(out, info->func_id);
+ }
+
+#if ENABLE_LineNumbers
+ if (cnt++ > 0) write_stream(out, ',');
+ json_write_string(out, "Area");
+ write_stream(out, ':');
+ write_code_area(out, &info->area, NULL);
+#endif /* ENABLE_LineNumbers */
+
+ write_stream(out, '}');
+}
+
typedef struct CommandGetLocationInfo {
char token[256];
char id[256];
@@ -881,9 +904,10 @@
char token[256];
char id[256];
ContextAddress addr;
+ int props;
} CommandFindFrameInfo;
-static void command_find_frame_info_cache_client(void * x) {
+static void command_find_frame_props_cache_client(void * x) {
CommandFindFrameInfo * args = (CommandFindFrameInfo *)x;
Channel * c = cache_channel();
Context * ctx = NULL;
@@ -900,30 +924,87 @@
write_stringz(&c->out, args->token);
write_errno(&c->out, err);
- json_write_uint64(&c->out, info ? info->addr : 0);
- write_stream(&c->out, 0);
- json_write_uint64(&c->out, info ? info->size : 0);
- write_stream(&c->out, 0);
-
- if (info == NULL || info->fp == NULL) write_string(&c->out, "null");
- else write_commands(&c->out, ctx, info->fp->cmds, info->fp->cmds_cnt);
- write_stream(&c->out, 0);
-
- if (info != NULL && info->regs != NULL) {
- int i;
+ if (args->props) {
+ unsigned cnt = 0;
write_stream(&c->out, '{');
- for (i = 0; i < info->reg_cnt; i++) {
- if (i > 0) write_stream(&c->out, ',');
- json_write_string(&c->out, register2id(ctx, STACK_NO_FRAME, info->regs[i]->reg));
+
+ if (info != NULL && info->size) {
+ json_write_string(&c->out, "CodeAddr");
write_stream(&c->out, ':');
- write_commands(&c->out, ctx, info->regs[i]->cmds, info->regs[i]->cmds_cnt);
+ json_write_uint64(&c->out, info->addr);
+ write_stream(&c->out, ',');
+ json_write_string(&c->out, "CodeSize");
+ write_stream(&c->out, ':');
+ json_write_uint64(&c->out, info->size);
+ cnt++;
}
+
+ if (info != NULL && info->fp != NULL) {
+ if (cnt++ > 0) write_stream(&c->out, ',');
+ json_write_string(&c->out, "FP");
+ write_stream(&c->out, ':');
+ write_commands(&c->out, ctx, info->fp->cmds, info->fp->cmds_cnt);
+ }
+
+ if (info != NULL && info->regs != NULL) {
+ int i;
+ if (cnt++ > 0) write_stream(&c->out, ',');
+ json_write_string(&c->out, "Regs");
+ write_stream(&c->out, ':');
+ write_stream(&c->out, '{');
+ for (i = 0; i < info->reg_cnt; i++) {
+ if (i > 0) write_stream(&c->out, ',');
+ json_write_string(&c->out, register2id(ctx, STACK_NO_FRAME, info->regs[i]->reg));
+ write_stream(&c->out, ':');
+ write_commands(&c->out, ctx, info->regs[i]->cmds, info->regs[i]->cmds_cnt);
+ }
+ write_stream(&c->out, '}');
+ }
+
+ if (info != NULL && info->subs != NULL) {
+ int i;
+ if (cnt++ > 0) write_stream(&c->out, ',');
+ json_write_string(&c->out, "Inlined");
+ write_stream(&c->out, ':');
+ write_stream(&c->out, '[');
+ for (i = 0; i < info->sub_cnt; i++) {
+ if (i > 0) write_stream(&c->out, ',');
+ write_inlined_subroutine_info(&c->out, info->subs[i]);
+ }
+ write_stream(&c->out, ']');
+ }
+
write_stream(&c->out, '}');
+ write_stream(&c->out, 0);
}
else {
- write_string(&c->out, "null");
+ /* Deprecated, use findFrameProps */
+
+ json_write_uint64(&c->out, info ? info->addr : 0);
+ write_stream(&c->out, 0);
+ json_write_uint64(&c->out, info ? info->size : 0);
+ write_stream(&c->out, 0);
+
+ if (info == NULL || info->fp == NULL) write_string(&c->out, "null");
+ else write_commands(&c->out, ctx, info->fp->cmds, info->fp->cmds_cnt);
+ write_stream(&c->out, 0);
+
+ if (info != NULL && info->regs != NULL) {
+ int i;
+ write_stream(&c->out, '{');
+ for (i = 0; i < info->reg_cnt; i++) {
+ if (i > 0) write_stream(&c->out, ',');
+ json_write_string(&c->out, register2id(ctx, STACK_NO_FRAME, info->regs[i]->reg));
+ write_stream(&c->out, ':');
+ write_commands(&c->out, ctx, info->regs[i]->cmds, info->regs[i]->cmds_cnt);
+ }
+ write_stream(&c->out, '}');
+ }
+ else {
+ write_string(&c->out, "null");
+ }
+ write_stream(&c->out, 0);
}
- write_stream(&c->out, 0);
write_stream(&c->out, MARKER_EOM);
}
@@ -936,9 +1017,24 @@
args.addr = (ContextAddress)json_read_uint64(&c->inp);
json_test_char(&c->inp, MARKER_EOA);
json_test_char(&c->inp, MARKER_EOM);
+ args.props = 0;
strlcpy(args.token, token, sizeof(args.token));
- cache_enter(command_find_frame_info_cache_client, c, &args, sizeof(args));
+ cache_enter(command_find_frame_props_cache_client, c, &args, sizeof(args));
+}
+
+static void command_find_frame_props(char * token, Channel * c) {
+ CommandFindFrameInfo args;
+
+ json_read_string(&c->inp, args.id, sizeof(args.id));
+ json_test_char(&c->inp, MARKER_EOA);
+ args.addr = (ContextAddress)json_read_uint64(&c->inp);
+ json_test_char(&c->inp, MARKER_EOA);
+ json_test_char(&c->inp, MARKER_EOM);
+ args.props = 1;
+
+ strlcpy(args.token, token, sizeof(args.token));
+ cache_enter(command_find_frame_props_cache_client, c, &args, sizeof(args));
}
typedef struct CommandSymFileInfo {
@@ -1126,7 +1222,8 @@
add_command_handler(proto, SYMBOLS, "list", command_list);
add_command_handler(proto, SYMBOLS, "getArrayType", command_get_array_type);
add_command_handler(proto, SYMBOLS, "getLocationInfo", command_get_location_info);
- add_command_handler(proto, SYMBOLS, "findFrameInfo", command_find_frame_info);
+ add_command_handler(proto, SYMBOLS, "findFrameInfo", command_find_frame_info); /* Deprecated, use findFrameProps */
+ add_command_handler(proto, SYMBOLS, "findFrameProps", command_find_frame_props);
add_command_handler(proto, SYMBOLS, "getSymFileInfo", command_get_sym_file_info);
add_command_handler(proto, SYMBOLS, "getAddressInfo", command_get_address_info);
}
diff --git a/agent/tcf/services/symbols.h b/agent/tcf/services/symbols.h
index 7f519de..63ff076 100644
--- a/agent/tcf/services/symbols.h
+++ b/agent/tcf/services/symbols.h
@@ -131,7 +131,7 @@
} StackFrameRegisterLocation;
typedef struct StackFrameInlinedSubroutine {
- Symbol * sym;
+ const char * func_id;
CodeArea area;
} StackFrameInlinedSubroutine;
diff --git a/agent/tcf/services/symbols_elf.c b/agent/tcf/services/symbols_elf.c
index d6e510d..d879e5e 100644
--- a/agent/tcf/services/symbols_elf.c
+++ b/agent/tcf/services/symbols_elf.c
@@ -2324,7 +2324,7 @@
}
}
object2symbol(NULL, o, &sym);
- sub->sym = sym;
+ sub->func_id = tmp_strdup(symbol2id(sym));
sub->area = area;
sub->area.start_address = addr0;
sub->area.end_address = addr1;
@@ -2334,15 +2334,6 @@
buf->subs, sizeof(StackFrameInlinedSubroutine *) * buf_sub_max);
}
buf->subs[buf->sub_cnt++] = sub;
- if (buf->addr < addr0) {
- assert(buf->addr + buf->size > addr0);
- buf->size = buf->addr + buf->size - addr0;
- buf->addr = addr0;
- }
- if (buf->addr + buf->size > addr1) {
- assert(addr1 > buf->addr);
- buf->size = addr1 - buf->addr;
- }
}
static void search_inlined_subroutine(Context * ctx, ObjectInfo * obj, UnitAddress * addr, StackTracingInfo * buf) {
@@ -2359,9 +2350,6 @@
case TAG_catch_block:
case TAG_subroutine:
case TAG_subprogram:
- if (!check_in_range(o, addr)) break;
- search_inlined_subroutine(ctx, o, addr, buf);
- break;
case TAG_inlined_subroutine:
if (o->mFlags & DOIF_ranges) {
DWARFCache * cache = get_dwarf_cache(addr->file);
@@ -2382,14 +2370,28 @@
else {
if (x_sec == NULL) x_sec = unit->mTextSection;
if (y_sec == NULL) y_sec = unit->mTextSection;
- if (x_sec == addr->section && y_sec == addr->section && addr->lt_addr >= base + x && addr->lt_addr < base + y) {
- ELF_File * file = unit->mFile;
- ContextAddress addr0 = elf_map_to_run_time_address(ctx, file, addr->section, base + x);
- ContextAddress addr1 = elf_map_to_run_time_address(ctx, file, addr->section, base + y);
+ if (x_sec == addr->section && y_sec == addr->section && x < y) {
+ ContextAddress addr0 = base + x - addr->lt_addr + addr->rt_addr;
+ ContextAddress addr1 = base + y - addr->lt_addr + addr->rt_addr;
if (addr0 <= addr->rt_addr && addr1 > addr->rt_addr) {
- add_inlined_subroutine(o, unit, addr0, addr1, buf);
+ if (buf->addr < addr0) {
+ assert(buf->addr + buf->size > addr0);
+ buf->size = buf->addr + buf->size - addr0;
+ buf->addr = addr0;
+ }
+ if (buf->addr + buf->size > addr1) {
+ assert(addr1 > buf->addr);
+ buf->size = addr1 - buf->addr;
+ }
+ if (o->mTag == TAG_inlined_subroutine) add_inlined_subroutine(o, unit, addr0, addr1, buf);
search_inlined_subroutine(ctx, o, addr, buf);
- break;
+ }
+ else if (addr1 <= addr->rt_addr && addr1 > buf->addr) {
+ buf->size = buf->addr + buf->size - addr1;
+ buf->addr = addr1;
+ }
+ else if (addr0 > addr->rt_addr && addr0 < buf->addr + buf->size) {
+ buf->size = addr0 - buf->addr;
}
}
}
@@ -2397,16 +2399,29 @@
dio_ExitSection();
}
}
- else if ((o->mFlags & DOIF_low_pc) && o->u.mCode.mHighPC.mAddr > o->u.mCode.mLowPC &&
- addr->lt_addr >= o->u.mCode.mLowPC && addr->lt_addr < o->u.mCode.mHighPC.mAddr &&
- o->u.mCode.mSection == addr->section) {
- ELF_File * file = addr->unit->mFile;
- ContextAddress addr0 = elf_map_to_run_time_address(ctx, file, addr->section, o->u.mCode.mLowPC);
- ContextAddress addr1 = elf_map_to_run_time_address(ctx, file, addr->section, o->u.mCode.mHighPC.mAddr);
+ else if ((o->mFlags & DOIF_low_pc) && o->u.mCode.mHighPC.mAddr > o->u.mCode.mLowPC && o->u.mCode.mSection == addr->section) {
+ ContextAddress addr0 = o->u.mCode.mLowPC - addr->lt_addr + addr->rt_addr;
+ ContextAddress addr1 = o->u.mCode.mHighPC.mAddr - addr->lt_addr + addr->rt_addr;
if (addr0 <= addr->rt_addr && addr1 > addr->rt_addr) {
- add_inlined_subroutine(o, addr->unit, addr0, addr1, buf);
+ if (buf->addr < addr0) {
+ assert(buf->addr + buf->size > addr0);
+ buf->size = buf->addr + buf->size - addr0;
+ buf->addr = addr0;
+ }
+ if (buf->addr + buf->size > addr1) {
+ assert(addr1 > buf->addr);
+ buf->size = addr1 - buf->addr;
+ }
+ if (o->mTag == TAG_inlined_subroutine) add_inlined_subroutine(o, addr->unit, addr0, addr1, buf);
search_inlined_subroutine(ctx, o, addr, buf);
}
+ else if (addr1 <= addr->rt_addr && addr1 > buf->addr) {
+ buf->size = buf->addr + buf->size - addr1;
+ buf->addr = addr1;
+ }
+ else if (addr0 > addr->rt_addr && addr0 < buf->addr + buf->size) {
+ buf->size = addr0 - buf->addr;
+ }
}
break;
}
diff --git a/agent/tcf/services/symbols_proxy.c b/agent/tcf/services/symbols_proxy.c
index d843e33..e4765ce 100644
--- a/agent/tcf/services/symbols_proxy.c
+++ b/agent/tcf/services/symbols_proxy.c
@@ -31,6 +31,7 @@
#include <tcf/framework/exceptions.h>
#include <tcf/services/stacktrace.h>
#include <tcf/services/memorymap.h>
+#include <tcf/services/linenumbers.h>
#include <tcf/services/symbols.h>
#include <tcf/services/vm.h>
#if ENABLE_SymbolsMux
@@ -64,6 +65,8 @@
LINK link_address[HASH_SIZE];
LINK link_location[HASH_SIZE];
int service_available;
+ int no_find_frame_info;
+ int no_find_frame_props;
} SymbolsCache;
/* Symbol properties cache */
@@ -146,6 +149,7 @@
Context * ctx;
uint64_t ip;
StackTracingInfo sti;
+ int command_props;
int disposed;
} StackFrameCache;
@@ -477,6 +481,14 @@
context_unlock(c->ctx);
for (i = 0; i < c->sti.reg_cnt; i++) free_sft_sequence(c->sti.regs[i]);
free_sft_sequence(c->sti.fp);
+ for (i = 0; i < c->sti.sub_cnt; i++) {
+ StackFrameInlinedSubroutine * info = c->sti.subs[i];
+ loc_free(info->area.directory);
+ loc_free(info->area.file);
+ loc_free(info->func_id);
+ loc_free(info);
+ }
+ loc_free(c->sti.subs);
loc_free(c->sti.regs);
loc_free(c);
}
@@ -1511,6 +1523,10 @@
static unsigned trace_regs_max = 0;
static StackFrameRegisterLocation ** trace_regs = NULL;
+static unsigned trace_subs_cnt = 0;
+static unsigned trace_subs_max = 0;
+static StackFrameInlinedSubroutine ** trace_subs = NULL;
+
static unsigned discriminant_cnt = 0;
static unsigned discriminant_max = 0;
static DiscriminantRange * discriminant_lst = NULL;
@@ -1768,6 +1784,62 @@
}
}
+static void read_inlined_subroutine_props(InputStream * inp, const char * name, void * args) {
+ StackFrameInlinedSubroutine * s = (StackFrameInlinedSubroutine *)args;
+ if (strcmp(name, "ID") == 0) s->func_id = json_read_alloc_string(inp);
+ else if (strcmp(name, "Area") == 0) read_code_area(inp, &s->area);
+ else json_skip_object(inp);
+}
+
+static void read_inlined_subroutine(InputStream * inp, void * args) {
+ if (trace_subs_cnt >= trace_subs_max) {
+ trace_subs_max += 16;
+ trace_subs = (StackFrameInlinedSubroutine **)loc_realloc(trace_subs, trace_subs_max * sizeof(StackFrameInlinedSubroutine *));
+ }
+ trace_subs[trace_subs_cnt] = (StackFrameInlinedSubroutine *)loc_alloc_zero(sizeof(StackFrameInlinedSubroutine));
+ json_read_struct(inp, read_inlined_subroutine_props, trace_subs[trace_subs_cnt++]);
+}
+
+static void read_stack_frame_fp(InputStream * inp, StackFrameCache * f) {
+ location_cmds.cnt = 0;
+ if (json_read_array(inp, read_location_command, NULL)) {
+ f->sti.fp = (StackFrameRegisterLocation *)loc_alloc(sizeof(StackFrameRegisterLocation) +
+ (location_cmds.cnt - 1) * sizeof(LocationExpressionCommand));
+ f->sti.fp->reg = NULL;
+ f->sti.fp->cmds_cnt = location_cmds.cnt;
+ f->sti.fp->cmds_max = location_cmds.cnt;
+ memcpy(f->sti.fp->cmds, location_cmds.cmds, location_cmds.cnt * sizeof(LocationExpressionCommand));
+ }
+}
+
+static void read_stack_frame_regs(InputStream * inp, StackFrameCache * f) {
+ trace_regs_cnt = 0;
+ if (json_read_struct(inp, read_stack_trace_register, NULL)) {
+ f->sti.reg_cnt = trace_regs_cnt;
+ f->sti.regs = (StackFrameRegisterLocation **)loc_alloc(trace_regs_cnt * sizeof(StackFrameRegisterLocation *));
+ memcpy(f->sti.regs, trace_regs, trace_regs_cnt * sizeof(StackFrameRegisterLocation *));
+ }
+}
+
+static void read_stack_frame_inlined(InputStream * inp, StackFrameCache * f) {
+ trace_subs_cnt = 0;
+ if (json_read_array(inp, read_inlined_subroutine, NULL)) {
+ f->sti.sub_cnt = trace_subs_cnt;
+ f->sti.subs = (StackFrameInlinedSubroutine **)loc_alloc(trace_subs_cnt * sizeof(StackFrameInlinedSubroutine *));
+ memcpy(f->sti.subs, trace_subs, trace_subs_cnt * sizeof(StackFrameInlinedSubroutine *));
+ }
+}
+
+static void read_stack_frame_props(InputStream * inp, const char * name, void * args) {
+ StackFrameCache * f = (StackFrameCache *)args;
+ if (strcmp(name, "CodeAddr") == 0) f->sti.addr = (ContextAddress)json_read_uint64(inp);
+ else if (strcmp(name, "CodeSize") == 0) f->sti.size = (ContextAddress)json_read_uint64(inp);
+ else if (strcmp(name, "FP") == 0) read_stack_frame_fp(inp, f);
+ else if (strcmp(name, "Regs") == 0) read_stack_frame_regs(inp, f);
+ else if (strcmp(name, "Inlined") == 0) read_stack_frame_inlined(inp, f);
+ else json_skip_object(inp);
+}
+
static void validate_frame(Channel * c, void * args, int error) {
Trap trap;
StackFrameCache * f = (StackFrameCache *)args;
@@ -1777,49 +1849,38 @@
if (set_trap(&trap)) {
f->pending = NULL;
if (!error) {
- uint64_t addr, size;
id2register_error = 0;
error = read_errno(&c->inp);
- addr = json_read_uint64(&c->inp);
- json_test_char(&c->inp, MARKER_EOA);
- size = json_read_uint64(&c->inp);
- json_test_char(&c->inp, MARKER_EOA);
- if (error || size == 0) {
- f->sti.addr = f->ip & ~(uint64_t)3;
- f->sti.size = 4;
+ if (f->command_props) {
+ json_read_struct(&c->inp, read_stack_frame_props, f);
+ json_test_char(&c->inp, MARKER_EOA);
}
else {
- assert(addr <= f->ip);
- assert(addr + size > f->ip);
- f->sti.addr = (ContextAddress)addr;
- f->sti.size = (ContextAddress)size;
+ /* Deprecated, use findFrameProps */
+ f->sti.addr = (ContextAddress)json_read_uint64(&c->inp);
+ json_test_char(&c->inp, MARKER_EOA);
+ f->sti.size = (ContextAddress)json_read_uint64(&c->inp);
+ json_test_char(&c->inp, MARKER_EOA);
+ read_stack_frame_fp(&c->inp, f);
+ json_test_char(&c->inp, MARKER_EOA);
+ read_stack_frame_regs(&c->inp, f);
+ json_test_char(&c->inp, MARKER_EOA);
}
- location_cmds.cnt = 0;
- if (json_read_array(&c->inp, read_location_command, NULL)) {
- f->sti.fp = (StackFrameRegisterLocation *)loc_alloc(sizeof(StackFrameRegisterLocation) +
- (location_cmds.cnt - 1) * sizeof(LocationExpressionCommand));
- f->sti.fp->reg = NULL;
- f->sti.fp->cmds_cnt = location_cmds.cnt;
- f->sti.fp->cmds_max = location_cmds.cnt;
- memcpy(f->sti.fp->cmds, location_cmds.cmds, location_cmds.cnt * sizeof(LocationExpressionCommand));
- }
- json_test_char(&c->inp, MARKER_EOA);
- trace_regs_cnt = 0;
- if (json_read_struct(&c->inp, read_stack_trace_register, NULL)) {
- f->sti.reg_cnt = trace_regs_cnt;
- f->sti.regs = (StackFrameRegisterLocation **)loc_alloc(trace_regs_cnt * sizeof(StackFrameRegisterLocation *));
- memcpy(f->sti.regs, trace_regs, trace_regs_cnt * sizeof(StackFrameRegisterLocation *));
- }
- json_test_char(&c->inp, MARKER_EOA);
json_test_char(&c->inp, MARKER_EOM);
if (!error && id2register_error) error = id2register_error;
}
+ if (error || f->sti.size == 0) {
+ f->sti.addr = (ContextAddress)f->ip;
+ f->sti.size = 1;
+ }
+ assert(f->sti.addr <= f->ip);
+ assert(f->sti.addr + f->sti.size > f->ip);
clear_trap(&trap);
}
else {
error = trap.error;
}
- if (get_error_code(error) != ERR_INV_COMMAND) f->error = get_error_report(error);
+ f->error = get_error_report(error);
cache_notify_later(&f->cache);
if (f->disposed) free_stack_frame_cache(f);
}
@@ -1853,9 +1914,23 @@
assert(f == NULL || f->pending == NULL);
+ if (f != NULL && f->error != NULL && get_error_code(set_error_report_errno(f->error)) == ERR_INV_COMMAND) {
+ if (f->command_props) {
+ syms->no_find_frame_props = 1;
+ }
+ else {
+ syms->no_find_frame_info = 1;
+ }
+ free_stack_frame_cache(f);
+ f = NULL;
+ }
+
if (f == NULL && !syms->service_available) {
/* nothing */
}
+ else if (f == NULL && syms->no_find_frame_info && syms->no_find_frame_props) {
+ /* nothing */
+ }
else if (f == NULL) {
Channel * c = get_channel(syms);
f = (StackFrameCache *)loc_alloc_zero(sizeof(StackFrameCache));
@@ -1864,7 +1939,15 @@
context_lock(f->ctx = ctx);
f->magic = MAGIC_FRAME;
f->ip = ip;
- f->pending = protocol_send_command(c, SYMBOLS, "findFrameInfo", validate_frame, f);
+ if (syms->no_find_frame_props) {
+ /* Deprecated, use findFrameProps */
+ f->pending = protocol_send_command(c, SYMBOLS, "findFrameInfo", validate_frame, f);
+ f->command_props = 0;
+ }
+ else {
+ f->pending = protocol_send_command(c, SYMBOLS, "findFrameProps", validate_frame, f);
+ f->command_props = 1;
+ }
json_write_string(&c->out, f->ctx->id);
write_stream(&c->out, 0);
json_write_uint64(&c->out, ip);