Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEugene Tarassov2013-02-07 19:28:58 -0500
committerEugene Tarassov2013-02-07 19:28:58 -0500
commit5f3f9858652e3933900fc60eb703e230348826dc (patch)
tree6727f226e6393eef77828ed61d084665e8f4a52d
parent6502e502ad220bf518e308be10d2bd290fff3ab5 (diff)
downloadorg.eclipse.tcf.agent-5f3f9858652e3933900fc60eb703e230348826dc.tar.gz
org.eclipse.tcf.agent-5f3f9858652e3933900fc60eb703e230348826dc.tar.xz
org.eclipse.tcf.agent-5f3f9858652e3933900fc60eb703e230348826dc.zip
TCF Agent: initial implementation of the Disassembly service
-rwxr-xr-xagent/agent.vcproj8
-rwxr-xr-xagent/agent.vcxproj4
-rwxr-xr-xagent/agent.vcxproj.filters12
-rw-r--r--agent/system/Darwin/tcf/context-darwin.c20
-rw-r--r--agent/system/FreeBSD/tcf/context-freebsd.c20
-rw-r--r--agent/system/GNU/Linux/tcf/context-linux.c20
-rw-r--r--agent/system/Windows/tcf/context-win32.c26
-rw-r--r--agent/tcf/config.h10
-rw-r--r--agent/tcf/framework/context.h18
-rw-r--r--agent/tcf/main/services.c4
-rw-r--r--agent/tcf/services/disassembly.c422
-rw-r--r--agent/tcf/services/disassembly.h35
-rw-r--r--agent/tcf/services/dwarfframe.c2
-rw-r--r--agent/tcf/services/symbols_win32.c6
-rw-r--r--server/tcf/config.h2
15 files changed, 597 insertions, 12 deletions
diff --git a/agent/agent.vcproj b/agent/agent.vcproj
index f49c1be6..bed094b6 100755
--- a/agent/agent.vcproj
+++ b/agent/agent.vcproj
@@ -652,6 +652,14 @@
>
</File>
<File
+ RelativePath=".\tcf\services\disassembly.c"
+ >
+ </File>
+ <File
+ RelativePath=".\tcf\services\disassembly.h"
+ >
+ </File>
+ <File
RelativePath=".\tcf\services\discovery.c"
>
</File>
diff --git a/agent/agent.vcxproj b/agent/agent.vcxproj
index 9671ff24..b497a203 100755
--- a/agent/agent.vcxproj
+++ b/agent/agent.vcxproj
@@ -272,8 +272,10 @@
<ClCompile Include="tcf\services\breakpoints.c" />
<ClCompile Include="tcf\services\contextquery.c" />
<ClCompile Include="tcf\services\diagnostics.c" />
+ <ClCompile Include="tcf\services\disassembly.c" />
<ClCompile Include="tcf\services\discovery.c" />
<ClCompile Include="tcf\services\discovery_udp.c" />
+ <ClCompile Include="tcf\services\dprintf.c" />
<ClCompile Include="tcf\services\dwarfcache.c" />
<ClCompile Include="tcf\services\dwarfecomp.c" />
<ClCompile Include="tcf\services\dwarfexpr.c" />
@@ -419,8 +421,10 @@
<ClInclude Include="tcf\services\breakpoints.h" />
<ClInclude Include="tcf\services\contextquery.h" />
<ClInclude Include="tcf\services\diagnostics.h" />
+ <ClInclude Include="tcf\services\disassembly.h" />
<ClInclude Include="tcf\services\discovery.h" />
<ClInclude Include="tcf\services\discovery_udp.h" />
+ <ClInclude Include="tcf\services\dprintf.h" />
<ClInclude Include="tcf\services\dwarf.h" />
<ClInclude Include="tcf\services\dwarfcache.h" />
<ClInclude Include="tcf\services\dwarfecomp.h" />
diff --git a/agent/agent.vcxproj.filters b/agent/agent.vcxproj.filters
index 6827b49b..a17fc310 100755
--- a/agent/agent.vcxproj.filters
+++ b/agent/agent.vcxproj.filters
@@ -303,6 +303,12 @@
<ClCompile Include="tcf\services\symbols_mux.c">
<Filter>services</Filter>
</ClCompile>
+ <ClCompile Include="tcf\services\disassembly.c">
+ <Filter>services</Filter>
+ </ClCompile>
+ <ClCompile Include="tcf\services\dprintf.c">
+ <Filter>services</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="tcf\framework\asyncreq.h">
@@ -561,5 +567,11 @@
<Filter>machine\i686</Filter>
</ClInclude>
<ClInclude Include="tcf\config.h" />
+ <ClInclude Include="tcf\services\disassembly.h">
+ <Filter>services</Filter>
+ </ClInclude>
+ <ClInclude Include="tcf\services\dprintf.h">
+ <Filter>services</Filter>
+ </ClInclude>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/agent/system/Darwin/tcf/context-darwin.c b/agent/system/Darwin/tcf/context-darwin.c
index 0f5c2620..b3b13cf0 100644
--- a/agent/system/Darwin/tcf/context-darwin.c
+++ b/agent/system/Darwin/tcf/context-darwin.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2013 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.
@@ -38,6 +38,7 @@
#include <tcf/framework/myalloc.h>
#include <tcf/framework/waitpid.h>
#include <tcf/framework/signames.h>
+#include <tcf/services/symbols.h>
#include <tcf/services/breakpoints.h>
#include <system/Darwin/tcf/regset.h>
@@ -463,6 +464,23 @@ int context_get_memory_map(Context * ctx, MemoryMap * map) {
return 0;
}
+#if ENABLE_ContextISA
+int context_get_isa(Context * ctx, ContextAddress addr, ContextISA * isa) {
+ memset(isa, 0, sizeof(ContextISA));
+#if defined(__i386__)
+ isa->def = "386";
+#elif defined(__x86_64__)
+ isa->def = "X86_64";
+#else
+ isa->def = NULL;
+#endif
+#if SERVICE_Symbols
+ if (get_context_isa(ctx, addr, &isa->isa, &isa->addr, &isa->size) < 0) return -1;
+#endif
+ return 0;
+}
+#endif
+
static Context * find_pending(pid_t pid) {
LINK * l = pending_list.next;
while (l != &pending_list) {
diff --git a/agent/system/FreeBSD/tcf/context-freebsd.c b/agent/system/FreeBSD/tcf/context-freebsd.c
index b5f4226d..b778459d 100644
--- a/agent/system/FreeBSD/tcf/context-freebsd.c
+++ b/agent/system/FreeBSD/tcf/context-freebsd.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2013 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.
@@ -36,6 +36,7 @@
#include <tcf/framework/myalloc.h>
#include <tcf/framework/waitpid.h>
#include <tcf/framework/signames.h>
+#include <tcf/services/symbols.h>
#include <tcf/services/breakpoints.h>
#include <system/FreeBSD/tcf/regset.h>
@@ -457,6 +458,23 @@ int context_get_memory_map(Context * ctx, MemoryMap * map) {
return 0;
}
+#if ENABLE_ContextISA
+int context_get_isa(Context * ctx, ContextAddress addr, ContextISA * isa) {
+ memset(isa, 0, sizeof(ContextISA));
+#if defined(__i386__)
+ isa->def = "386";
+#elif defined(__x86_64__)
+ isa->def = "X86_64";
+#else
+ isa->def = NULL;
+#endif
+#if SERVICE_Symbols
+ if (get_context_isa(ctx, addr, &isa->isa, &isa->addr, &isa->size) < 0) return -1;
+#endif
+ return 0;
+}
+#endif
+
static Context * find_pending(pid_t pid) {
LINK * l = pending_list.next;
while (l != &pending_list) {
diff --git a/agent/system/GNU/Linux/tcf/context-linux.c b/agent/system/GNU/Linux/tcf/context-linux.c
index 1d5a9f1d..e9bc9b8f 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, 2012 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2013 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.
@@ -41,6 +41,7 @@
#include <tcf/framework/myalloc.h>
#include <tcf/framework/waitpid.h>
#include <tcf/framework/signames.h>
+#include <tcf/services/symbols.h>
#include <tcf/services/contextquery.h>
#include <tcf/services/breakpoints.h>
#include <tcf/services/expressions.h>
@@ -913,6 +914,23 @@ int context_get_memory_map(Context * ctx, MemoryMap * map) {
return 0;
}
+#if ENABLE_ContextISA
+int context_get_isa(Context * ctx, ContextAddress addr, ContextISA * isa) {
+ memset(isa, 0, sizeof(ContextISA));
+#if defined(__i386__)
+ isa->def = "386";
+#elif defined(__x86_64__)
+ isa->def = "X86_64";
+#else
+ isa->def = NULL;
+#endif
+#if SERVICE_Symbols
+ if (get_context_isa(ctx, addr, &isa->isa, &isa->addr, &isa->size) < 0) return -1;
+#endif
+ return 0;
+}
+#endif
+
static Context * find_pending_attach(pid_t pid) {
LINK * l = attach_list.next;
while (l != &attach_list) {
diff --git a/agent/system/Windows/tcf/context-win32.c b/agent/system/Windows/tcf/context-win32.c
index 9e905706..93d30951 100644
--- a/agent/system/Windows/tcf/context-win32.c
+++ b/agent/system/Windows/tcf/context-win32.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2013 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.
@@ -34,6 +34,7 @@
#include <tcf/framework/myalloc.h>
#include <tcf/framework/waitpid.h>
#include <tcf/framework/signames.h>
+#include <tcf/services/symbols.h>
#include <tcf/services/breakpoints.h>
#include <tcf/services/memorymap.h>
#include <tcf/services/runctrl.h>
@@ -1398,6 +1399,29 @@ int context_get_breakpoint_status(ContextBreakpoint * bp, const char *** names,
}
#endif
+#if ENABLE_ContextISA
+int context_get_isa(Context * ctx, ContextAddress addr, ContextISA * isa) {
+ ContextExtensionWin32 * ext = EXT(ctx->mem);
+ memset(isa, 0, sizeof(ContextISA));
+ if (ext->debug_state->wow64) {
+ isa->def = "386";
+ }
+ else {
+#if defined(_M_IX86)
+ isa->def = "386";
+#elif defined(_M_AMD64)
+ isa->def = "X86_64";
+#else
+ isa->def = NULL;
+#endif
+ }
+#if SERVICE_Symbols
+ if (get_context_isa(ctx, addr, &isa->isa, &isa->addr, &isa->size) < 0) return -1;
+#endif
+ return 0;
+}
+#endif
+
HANDLE get_context_handle(Context * ctx) {
ContextExtensionWin32 * ext = EXT(ctx);
return ext->handle;
diff --git a/agent/tcf/config.h b/agent/tcf/config.h
index 78e07e4f..e1a584e2 100644
--- a/agent/tcf/config.h
+++ b/agent/tcf/config.h
@@ -115,6 +115,9 @@
#if !defined(SERVICE_DPrintf)
#define SERVICE_DPrintf (SERVICE_Expressions && SERVICE_Streams)
#endif
+#if !defined(SERVICE_Disassembly)
+#define SERVICE_Disassembly (SERVICE_Memory)
+#endif
#if !defined(ENABLE_Plugins)
# if TARGET_UNIX && defined(PATH_Plugins)
@@ -158,7 +161,8 @@
#endif
#if !defined(ENABLE_DebugContext)
-# define ENABLE_DebugContext (ENABLE_ContextProxy || SERVICE_RunControl || SERVICE_Breakpoints || SERVICE_Memory || SERVICE_Registers || SERVICE_StackTrace)
+# define ENABLE_DebugContext (ENABLE_ContextProxy || SERVICE_RunControl || SERVICE_Breakpoints || \
+ SERVICE_Memory || SERVICE_Registers || SERVICE_StackTrace || SERVICE_Disassembly)
#endif
#if !defined(ENABLE_SymbolsProxy)
@@ -281,4 +285,8 @@
# define ENABLE_ExternalStackcrawl 0
#endif
+#if !defined(ENABLE_ContextISA)
+# define ENABLE_ContextISA SERVICE_Disassembly
+#endif
+
#endif /* D_config */
diff --git a/agent/tcf/framework/context.h b/agent/tcf/framework/context.h
index c0531973..b0fa06d2 100644
--- a/agent/tcf/framework/context.h
+++ b/agent/tcf/framework/context.h
@@ -544,6 +544,24 @@ extern int context_get_breakpoint_capabilities(Context * ctx, const char *** nam
extern int context_get_breakpoint_status(ContextBreakpoint * bp, const char *** names, const char *** values, int * cnt);
#endif
+#if ENABLE_ContextISA
+typedef struct {
+ ContextAddress addr;
+ ContextAddress size;
+ ContextAddress alignment;
+ ContextAddress max_instruction_size;
+ const char * isa;
+ const char * def;
+} ContextISA;
+
+/*
+ * Get context Instruction Set Architecture information.
+ * Return -1 and set errno if cannot access the status.
+ * Return 0 on success.
+ */
+extern int context_get_isa(Context * ctx, ContextAddress addr, ContextISA * isa);
+#endif
+
/*
* Functions that notify listeners of various context event.
* These function are called by context implementation.
diff --git a/agent/tcf/main/services.c b/agent/tcf/main/services.c
index a593a25a..720e982c 100644
--- a/agent/tcf/main/services.c
+++ b/agent/tcf/main/services.c
@@ -41,6 +41,7 @@
#include <tcf/services/tcf_elf.h>
#include <tcf/services/terminals.h>
#include <tcf/services/dprintf.h>
+#include <tcf/services/disassembly.h>
#include <tcf/main/services.h>
#include <tcf/main/services-ext.h>
@@ -104,6 +105,9 @@ void ini_services(Protocol * proto, TCFBroadcastGroup * bcg) {
#if SERVICE_DPrintf
ini_dprintf_service(proto);
#endif
+#if SERVICE_Disassembly
+ ini_disassembly_service(proto);
+#endif
#if ENABLE_DebugContext
ini_contexts();
#endif
diff --git a/agent/tcf/services/disassembly.c b/agent/tcf/services/disassembly.c
new file mode 100644
index 00000000..3c63cb61
--- /dev/null
+++ b/agent/tcf/services/disassembly.c
@@ -0,0 +1,422 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Xilinx, 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:
+ * Xilinx - initial API and implementation
+ *******************************************************************************/
+
+#include <tcf/config.h>
+
+#if SERVICE_Disassembly
+
+#include <stdio.h>
+#include <assert.h>
+#include <tcf/framework/json.h>
+#include <tcf/framework/context.h>
+#include <tcf/framework/exceptions.h>
+#include <tcf/framework/myalloc.h>
+#include <tcf/services/runctrl.h>
+#include <tcf/services/symbols.h>
+#include <tcf/services/linenumbers.h>
+#include <tcf/services/memorymap.h>
+#include <tcf/services/tcf_elf.h>
+#include <tcf/services/disassembly.h>
+
+#define MAX_INSTRUCTION_SIZE 8
+#define DEFAULT_ALIGMENT 16
+
+typedef struct {
+ const char * isa;
+ Disassembler * disassembler;
+} DisassemblerInfo;
+
+typedef struct {
+ DisassemblerInfo * disassemblers;
+ unsigned disassemblers_cnt;
+ unsigned disassemblers_max;
+} ContextExtensionDS;
+
+static const char * DISASSEMBLY = "Disassembly";
+static size_t context_extension_offset = 0;
+
+#define EXT(ctx) (ctx ? ((ContextExtensionDS *)((char *)(ctx) + context_extension_offset)) : NULL)
+
+void add_disassembler(Context * ctx, const char * isa, Disassembler disassembler) {
+ DisassemblerInfo * i = NULL;
+ ContextExtensionDS * ext = EXT(ctx);
+ assert(ctx == context_get_group(ctx, CONTEXT_GROUP_CPU));
+ if (ext->disassemblers_cnt >= ext->disassemblers_max) {
+ ext->disassemblers_max += 8;
+ ext->disassemblers = (DisassemblerInfo *)loc_realloc(ext->disassemblers,
+ sizeof(DisassemblerInfo) * ext->disassemblers_max);
+ }
+ i = ext->disassemblers + ext->disassemblers_cnt++;
+ i->isa = loc_strdup(isa);
+ i->disassembler = disassembler;
+}
+
+static Disassembler * find_disassembler(Context * ctx, const char * isa) {
+ if (isa != NULL) {
+ unsigned i = 0;
+ ContextExtensionDS * ext = EXT(ctx);
+ while (i < ext->disassemblers_cnt) {
+ if (strcmp(ext->disassemblers[i].isa, isa) == 0)
+ return ext->disassemblers[i].disassembler;
+ i++;
+ }
+ }
+ return NULL;
+}
+
+static void command_get_capabilities(char * token, Channel * c) {
+ int error = 0;
+ char id[256];
+ Context * ctx = NULL;
+ ContextExtensionDS * ext = NULL;
+ unsigned i, j;
+
+ json_read_string(&c->inp, id, sizeof(id));
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
+
+ ctx = id2ctx(id);
+
+ if (ctx == NULL) error = ERR_INV_CONTEXT;
+ else if (ctx->exited) error = ERR_ALREADY_EXITED;
+
+ ctx = context_get_group(ctx, CONTEXT_GROUP_CPU);
+ ext = EXT(ctx);
+
+ write_stringz(&c->out, "R");
+ write_stringz(&c->out, token);
+ write_errno(&c->out, error);
+ write_stream(&c->out, '[');
+ for (i = 0, j = 0; i < ext->disassemblers_cnt; i++) {
+ if (j > 0) write_stream(&c->out, ',');
+ write_stream(&c->out, '{');
+ json_write_string(&c->out, "ISA");
+ write_stream(&c->out, ':');
+ json_write_string(&c->out, ext->disassemblers[i].isa);
+ write_stream(&c->out, '}');
+ j++;
+ }
+ write_stream(&c->out, ']');
+ write_stream(&c->out, 0);
+ write_stream(&c->out, MARKER_EOM);
+}
+
+static void get_isa(Context * ctx, ContextAddress addr, ContextISA * isa) {
+ if (context_get_isa(ctx, addr, isa) < 0) {
+ memset(isa, 0, sizeof(ContextISA));
+ }
+#if SERVICE_MemoryMap
+ if (isa->size == 0) {
+ unsigned i, j;
+ MemoryMap * client_map = NULL;
+ MemoryMap * target_map = NULL;
+ if (memory_map_get(ctx, &client_map, &target_map) == 0) {
+ isa->addr = addr;
+ isa->size = ~(ContextAddress)0;
+ for (j = 0; j < 2; j++) {
+ MemoryMap * map = j ? target_map : client_map;
+ for (i = 0; i < map->region_cnt; i++) {
+ MemoryRegion * r = map->regions + i;
+ ContextAddress x = r->addr;
+ ContextAddress y = r->addr + r->size;
+ if (x > addr && x < addr + isa->size) isa->size = x - addr;
+ if (y > addr && y < addr + isa->size) isa->size = y - addr;
+ }
+ }
+ }
+ }
+#endif
+}
+
+static void disassemble_block(Context * ctx, OutputStream * out, uint8_t * mem_buf,
+ ContextAddress buf_addr, ContextAddress buf_size,
+ ContextAddress mem_size, ContextISA * isa) {
+ ContextAddress offs = 0;
+ Disassembler * disassembler = NULL;
+ Context * cpu = context_get_group(ctx, CONTEXT_GROUP_CPU);
+ int disassembler_ok = 0;
+
+ write_stream(out, '[');
+ while (offs < buf_size && offs < mem_size) {
+ ContextAddress addr = buf_addr + offs;
+ ContextAddress size = mem_size - offs;
+ DisassemblyResult * dr = NULL;
+ if (addr < isa->addr || addr >= isa->addr + isa->size) {
+ get_isa(ctx, addr, isa);
+ disassembler_ok = 0;
+ }
+ if (!disassembler_ok) {
+ disassembler = find_disassembler(cpu, isa->isa);
+ if (disassembler == NULL) disassembler = find_disassembler(cpu, isa->def);
+ disassembler_ok = 1;
+ }
+ if (disassembler) dr = disassembler(mem_buf + (size_t)offs, addr, size);
+ if (dr == NULL) {
+ static char buf[32];
+ static DisassemblyResult dd;
+ memset(&dd, 0, sizeof(dd));
+ if (isa->alignment >= 4 && (addr & 0x3) == 0 && offs <= mem_size + 4) {
+ unsigned i;
+ uint32_t v = 0;
+ for (i = 0; i < 4; i++) v |= (uint32_t)mem_buf[offs + i] << (i * 8);
+ snprintf(buf, sizeof(buf), ".word 0x%08x", v);
+ dd.size = 4;
+ }
+ else {
+ snprintf(buf, sizeof(buf), ".byte 0x%02x", mem_buf[offs]);
+ dd.size = 1;
+ }
+ dd.text = buf;
+ dr = &dd;
+ }
+ if (offs > 0) write_stream(out, ',');
+ write_stream(out, '{');
+ json_write_string(out, "Address");
+ write_stream(out, ':');
+ json_write_uint64(out, addr);
+ write_stream(out, ',');
+ json_write_string(out, "Size");
+ write_stream(out, ':');
+ json_write_uint64(out, dr->size);
+ write_stream(out, ',');
+ json_write_string(out, "Instruction");
+ write_stream(out, ':');
+ write_stream(out, '[');
+ write_stream(out, '{');
+ json_write_string(out, "Type");
+ write_stream(out, ':');
+ json_write_string(out, "String");
+ write_stream(out, ',');
+ json_write_string(out, "Text");
+ write_stream(out, ':');
+ json_write_string(out, dr->text);
+ write_stream(out, '}');
+ write_stream(out, ']');
+ write_stream(out, '}');
+ offs += dr->size;
+ }
+ write_stream(out, ']');
+}
+
+typedef struct {
+ Channel * c;
+ char token[256];
+ char id[256];
+ ContextAddress addr;
+ ContextAddress size;
+} DisassembleCmdArgs;
+
+#if SERVICE_LineNumbers
+static void address_to_line_cb(CodeArea * area, void * args) {
+ CodeArea ** p = (CodeArea **)args;
+ if (*p == NULL || (*p)->start_address < area->start_address) {
+ *p = (CodeArea *)tmp_alloc(sizeof(CodeArea));
+ **p = *area;
+ }
+}
+#endif
+
+static void safe_event_disassemble(void * x) {
+ DisassembleCmdArgs * args = (DisassembleCmdArgs *)x;
+
+ if (!is_channel_closed(args->c)) {
+ int error = 0;
+ Context * ctx = NULL;
+ uint8_t * mem_buf = NULL;
+ ContextAddress buf_addr = 0;
+ ContextAddress buf_size = 0;
+ size_t mem_size = 0;
+ ByteArrayOutputStream buf;
+ OutputStream * buf_out = create_byte_array_output_stream(&buf);
+ OutputStream * out = &args->c->out;
+ char * data = NULL;
+ size_t size = 0;
+ ContextISA isa;
+
+ memset(&isa, 0, sizeof(isa));
+ ctx = id2ctx(args->id);
+
+ if (ctx == NULL) error = ERR_INV_CONTEXT;
+ else if (ctx->exited) error = ERR_ALREADY_EXITED;
+
+ if (!error) {
+ ContextAddress sym_addr = 0;
+ ContextAddress sym_size = 0;
+ int sym_addr_ok = 0;
+ int sym_size_ok = 0;
+#if SERVICE_Symbols
+ {
+ Symbol * sym = NULL;
+ if (find_symbol_by_addr(ctx, STACK_NO_FRAME, args->addr, &sym) == 0) {
+ if (get_symbol_address(sym, &sym_addr) == 0) sym_addr_ok = 1;
+ if (get_symbol_size(sym, &sym_size) == 0) sym_size_ok = 1;
+ }
+ if (sym_addr_ok && sym_addr <= args->addr) {
+ if (args->addr - sym_addr >= 0x1000) {
+ sym_addr_ok = 0;
+ sym_size_ok = 0;
+ }
+ else if (sym_size_ok && sym_addr + sym_size > args->addr + args->size) {
+ sym_size = args->addr + args->size - sym_addr;
+ }
+ }
+ }
+#endif
+#if SERVICE_LineNumbers
+ if (!sym_addr_ok || !sym_size_ok) {
+ CodeArea * area = NULL;
+ address_to_line(ctx, args->addr, args->addr + 1, address_to_line_cb, &area);
+ if (area != NULL) {
+ sym_addr = area->start_address;
+ sym_size = area->end_address - area->start_address;
+ sym_addr_ok = 1;
+ sym_size_ok = 1;
+ }
+ }
+#endif
+ if (sym_addr_ok && sym_size_ok && sym_addr <= args->addr && sym_addr + sym_size > args->addr) {
+ buf_addr = sym_addr;
+ buf_size = sym_size;
+ mem_size = (size_t)sym_size;
+ }
+ else if (sym_addr_ok && sym_addr < args->addr) {
+ get_isa(ctx, sym_addr, &isa);
+ buf_addr = sym_addr;
+ buf_size = args->addr + args->size - sym_addr;
+ if (isa.max_instruction_size > 0) {
+ mem_size = (size_t)(buf_size + isa.max_instruction_size);
+ }
+ else {
+ mem_size = (size_t)(buf_size + MAX_INSTRUCTION_SIZE);
+ }
+ }
+ else {
+ /* Use default address alignment */
+ get_isa(ctx, args->addr, &isa);
+ if (isa.alignment > 0) {
+ buf_addr = args->addr & ~(ContextAddress)(isa.alignment - 1);
+ }
+ else {
+ buf_addr = args->addr & ~(ContextAddress)(DEFAULT_ALIGMENT - 1);
+ }
+ buf_size = args->addr + args->size - buf_addr;
+ if (isa.max_instruction_size > 0) {
+ mem_size = (size_t)(buf_size + isa.max_instruction_size);
+ }
+ else {
+ mem_size = (size_t)(buf_size + MAX_INSTRUCTION_SIZE);
+ }
+ }
+ mem_buf = (uint8_t *)loc_alloc(mem_size);
+ if (context_read_mem(ctx, buf_addr, mem_buf, mem_size) < 0) error = errno;
+ if (error) {
+ MemoryErrorInfo info;
+ if (context_get_mem_error_info(&info) < 0 || info.size_valid == 0) {
+ mem_size = 0;
+ }
+ else {
+ mem_size = info.size_valid;
+ error = 0;
+ }
+ }
+ }
+
+ if (!error) disassemble_block(ctx, buf_out, mem_buf, buf_addr, buf_size, mem_size, &isa);
+
+ get_byte_array_output_stream_data(&buf, &data, &size);
+
+ write_stringz(out, "R");
+ write_stringz(out, args->token);
+ write_errno(out, error);
+ if (size > 0) {
+ size_t i = 0;
+ while (i < size) write_stream(out, data[i++]);
+ }
+ else {
+ write_string(out, "null");
+ }
+ write_stream(out, 0);
+ write_stream(out, MARKER_EOM);
+ loc_free(data);
+ loc_free(mem_buf);
+ }
+ channel_unlock(args->c);
+ loc_free(args);
+}
+
+static void read_disassembly_params(InputStream * inp, const char * name, void * x) {
+ /* TODO: disassembly params */
+ json_skip_object(inp);
+}
+
+static void command_disassemble(char * token, Channel * c) {
+ int error = 0;
+ Context * ctx = NULL;
+ DisassembleCmdArgs * args = (DisassembleCmdArgs *)loc_alloc_zero(sizeof(DisassembleCmdArgs));
+ json_read_string(&c->inp, args->id, sizeof(args->id));
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ args->addr = (ContextAddress)json_read_uint64(&c->inp);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ args->size = (ContextAddress)json_read_uint64(&c->inp);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ json_read_struct(&c->inp, read_disassembly_params, args);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
+
+ ctx = id2ctx(args->id);
+ if (ctx == NULL) error = ERR_INV_CONTEXT;
+ else if (ctx->exited) error = ERR_ALREADY_EXITED;
+ else if (context_get_group(ctx, CONTEXT_GROUP_PROCESS)->mem_access == 0) error = ERR_INV_CONTEXT;
+
+ if (error != 0) {
+ write_stringz(&c->out, "R");
+ write_stringz(&c->out, token);
+ write_errno(&c->out, error);
+ write_stringz(&c->out, "null");
+ write_stream(&c->out, MARKER_EOM);
+ loc_free(args);
+ }
+ else {
+ channel_lock(args->c = c);
+ strlcpy(args->token, token, sizeof(args->token));
+ post_safe_event(ctx, safe_event_disassemble, args);
+ }
+}
+
+static void event_context_disposed(Context * ctx, void * args) {
+ unsigned i;
+ ContextExtensionDS * ext = EXT(ctx);
+ for (i = 0; i < ext->disassemblers_cnt; i++) {
+ loc_free(ext->disassemblers[i].isa);
+ }
+ loc_free(ext->disassemblers);
+}
+
+void ini_disassembly_service(Protocol * proto) {
+ static ContextEventListener listener = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ event_context_disposed
+ };
+ add_context_event_listener(&listener, NULL);
+ context_extension_offset = context_extension(sizeof(ContextExtensionDS));
+ add_command_handler(proto, DISASSEMBLY, "getCapabilities", command_get_capabilities);
+ add_command_handler(proto, DISASSEMBLY, "disassemble", command_disassemble);
+}
+
+#endif /* SERVICE_Disassembly */
diff --git a/agent/tcf/services/disassembly.h b/agent/tcf/services/disassembly.h
new file mode 100644
index 00000000..1a206690
--- /dev/null
+++ b/agent/tcf/services/disassembly.h
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Xilinx, 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:
+ * Xilinx - initial API and implementation
+ *******************************************************************************/
+
+#ifndef D_disassembly
+#define D_disassembly
+
+#include <tcf/config.h>
+#include <tcf/framework/cpudefs.h>
+#include <tcf/framework/protocol.h>
+
+typedef struct {
+ const char * text;
+ ContextAddress size;
+ int incomplete;
+} DisassemblyResult;
+
+typedef DisassemblyResult * Disassembler(uint8_t * /* code */, ContextAddress /* addr */, ContextAddress /* size */);
+
+extern void add_disassembler(Context * ctx, const char * isa, Disassembler disassembler);
+
+extern void ini_disassembly_service(Protocol * proto);
+
+#endif /* D_disassembly */
diff --git a/agent/tcf/services/dwarfframe.c b/agent/tcf/services/dwarfframe.c
index 43751cb8..595b02ff 100644
--- a/agent/tcf/services/dwarfframe.c
+++ b/agent/tcf/services/dwarfframe.c
@@ -1094,7 +1094,7 @@ static void read_frame_info_section(Context * ctx, ELF_Section * text_section,
unsigned l, h;
ELF_Section * section = index->mSection;
ELF_File * file = section->file;
- U2_T sec_idx = 0;
+ U4_T sec_idx = 0;
if (text_section != NULL && text_section->file != file) {
unsigned i;
diff --git a/agent/tcf/services/symbols_win32.c b/agent/tcf/services/symbols_win32.c
index 3461b9f5..af464e07 100644
--- a/agent/tcf/services/symbols_win32.c
+++ b/agent/tcf/services/symbols_win32.c
@@ -1072,13 +1072,7 @@ ContextAddress is_plt_section(Context * ctx, ContextAddress addr) {
int get_context_isa(Context * ctx, ContextAddress addr, const char ** isa,
ContextAddress * range_addr, ContextAddress * range_size) {
-#if defined(_M_IX86)
- *isa = "386";
-#elif defined(_M_AMD64)
- *isa = "X86_64";
-#else
*isa = NULL;
-#endif
*range_addr = addr;
*range_size = 1;
return 0;
diff --git a/server/tcf/config.h b/server/tcf/config.h
index 5f87d444..dd7a3ede 100644
--- a/server/tcf/config.h
+++ b/server/tcf/config.h
@@ -48,6 +48,7 @@
#define SERVICE_SysMonitor 0
#define SERVICE_Expressions 0
#define SERVICE_DPrintf 0
+#define SERVICE_Disassembly 0
#if !defined(SERVICE_Streams)
#define SERVICE_Streams 0
#endif
@@ -143,5 +144,6 @@
#define ENABLE_ExternalStackcrawl 0
#define ENABLE_SymbolsMux 0
#define ENABLE_LineNumbersMux 0
+#define ENABLE_ContextISA 0
#endif /* D_config */

Back to the top