Skip to main content
aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authoreutarass2011-05-24 19:23:13 +0000
committereutarass2011-05-24 19:23:13 +0000
commit4bf5533cf4f76b039263259d7bf2fd95edad350a (patch)
treee18f62fa302dcee72d8c13051c4d08e2cefcef41 /tests
parent7b2ecf727c8b7fc8d8ff3874f46734309c15b319 (diff)
downloadorg.eclipse.tcf-4bf5533cf4f76b039263259d7bf2fd95edad350a.tar.gz
org.eclipse.tcf-4bf5533cf4f76b039263259d7bf2fd95edad350a.tar.xz
org.eclipse.tcf-4bf5533cf4f76b039263259d7bf2fd95edad350a.zip
Implemented memory leak tests.
Diffstat (limited to 'tests')
-rw-r--r--tests/mem-leaks/Makefile29
-rw-r--r--tests/mem-leaks/agent.sln20
-rw-r--r--tests/mem-leaks/agent.vcproj647
-rw-r--r--tests/mem-leaks/config.h20
-rw-r--r--tests/mem-leaks/main/services-ext.h25
-rw-r--r--tests/mem-leaks/services/memtrace.c732
-rw-r--r--tests/mem-leaks/services/memtrace.h27
7 files changed, 1500 insertions, 0 deletions
diff --git a/tests/mem-leaks/Makefile b/tests/mem-leaks/Makefile
new file mode 100644
index 000000000..97ff6681c
--- /dev/null
+++ b/tests/mem-leaks/Makefile
@@ -0,0 +1,29 @@
+TCF_AGENT_DIR=../../../tcf/trunk/agent
+
+include $(TCF_AGENT_DIR)/Makefile.inc
+
+CFLAGS := $(foreach dir,$(SRCDIRS),-I$(dir)) $(CFLAGS)
+HFILES := $(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.h)) $(HFILES)
+CFILES := $(sort $(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.c)) $(CFILES))
+
+EXECS = $(BINDIR)/agent$(EXTEXE)
+
+all: $(EXECS)
+
+$(BINDIR)/libtcf$(EXTLIB) : $(OFILES)
+ $(AR) -rc $@ $^
+ $(RANLIB)
+
+$(BINDIR)/agent$(EXTEXE): $(BINDIR)/main/main$(EXTOBJ) $(BINDIR)/libtcf$(EXTLIB)
+ $(CC) $(CFLAGS) -o $@ $(BINDIR)/main/main$(EXTOBJ) $(BINDIR)/libtcf$(EXTLIB) $(LIBS)
+
+$(BINDIR)/%$(EXTOBJ): %.c $(HFILES) Makefile
+ @mkdir -p $(dir $@)
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+$(BINDIR)/%$(EXTOBJ): $(TCF_AGENT_DIR)/%.c $(HFILES) Makefile
+ @mkdir -p $(dir $@)
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+clean:
+ rm -rf $(BINDIR)
diff --git a/tests/mem-leaks/agent.sln b/tests/mem-leaks/agent.sln
new file mode 100644
index 000000000..0701c5ad8
--- /dev/null
+++ b/tests/mem-leaks/agent.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual C++ Express 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "agent", "agent.vcproj", "{DAB1E508-ECE7-4C2B-B6D6-870ACC72CAF0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {DAB1E508-ECE7-4C2B-B6D6-870ACC72CAF0}.Debug|Win32.ActiveCfg = Debug|Win32
+ {DAB1E508-ECE7-4C2B-B6D6-870ACC72CAF0}.Debug|Win32.Build.0 = Debug|Win32
+ {DAB1E508-ECE7-4C2B-B6D6-870ACC72CAF0}.Release|Win32.ActiveCfg = Release|Win32
+ {DAB1E508-ECE7-4C2B-B6D6-870ACC72CAF0}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/tests/mem-leaks/agent.vcproj b/tests/mem-leaks/agent.vcproj
new file mode 100644
index 000000000..2ea5557f1
--- /dev/null
+++ b/tests/mem-leaks/agent.vcproj
@@ -0,0 +1,647 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="agent"
+ ProjectGUID="{DAB1E508-ECE7-4C2B-B6D6-870ACC72CAF0}"
+ RootNamespace="agent"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)\obj\MSVC\$(ConfigurationName)"
+ IntermediateDirectory="$(SolutionDir)\obj\MSVC\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=".;C:\tcf\trunk\agent;C:\tcf\trunk\agent\system\Windows;C:\tcf\trunk\agent\machine\i386"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="WS2_32.lib Iphlpapi.lib version.lib"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)\obj\MSVC\$(ConfigurationName)"
+ IntermediateDirectory="$(SolutionDir)\obj\MSVC\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories=".;C:\tcf\trunk\agent;C:\tcf\trunk\agent\system\Windows;C:\tcf\trunk\agent\machine\i386"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="WS2_32.lib Iphlpapi.lib version.lib"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="main"
+ >
+ <File
+ RelativePath="..\..\agent\main\cmdline.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\main\cmdline.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\main\main.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\main\server.c"
+ >
+ </File>
+ <File
+ RelativePath=".\main\services-ext.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\main\services.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\main\test.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\main\test.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="services"
+ >
+ <File
+ RelativePath="..\..\agent\services\breakpoints.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\breakpoints.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\diagnostics.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\diagnostics.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\discovery.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\discovery.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\discovery_udp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\discovery_udp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\expressions.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\expressions.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\filesystem.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\filesystem.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\linenumbers.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\linenumbers.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\linenumbers_elf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\linenumbers_proxy.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\linenumbers_win32.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\memorymap.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\memorymap.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\memoryservice.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\memoryservice.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\pathmap.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\pathmap.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\processes.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\processes.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\registers.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\registers.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\runctrl.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\runctrl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\stacktrace.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\stacktrace.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\streamsservice.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\streamsservice.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\symbols.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\symbols.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\symbols_alloc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\symbols_elf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\symbols_proxy.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\symbols_win32.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\sysmon.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\sysmon.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\terminals.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\services\terminals.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="framework"
+ >
+ <File
+ RelativePath="..\..\agent\framework\asyncreq.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\asyncreq.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\base64.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\base64.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\cache.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\cache.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\channel.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\channel.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\channel_pipe.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\channel_pipe.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\channel_tcp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\channel_tcp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\context.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\context.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\cpudefs.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\cpudefs.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\errors.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\errors.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\events.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\events.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\exceptions.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\exceptions.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\inputbuf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\inputbuf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\ip_ifc.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\ip_ifc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\json.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\json.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\link.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\mdep.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\mdep.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\myalloc.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\myalloc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\outputbuf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\outputbuf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\peer.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\peer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\plugins.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\plugins.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\protocol.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\protocol.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\proxy.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\proxy.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\signames.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\signames.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\streams.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\streams.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\tcf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\trace.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\trace.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\waitpid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\framework\waitpid.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="trace"
+ >
+ <File
+ RelativePath=".\services\memtrace.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\memtrace.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="system"
+ >
+ <Filter
+ Name="Windows"
+ >
+ <File
+ RelativePath="..\..\agent\system\Windows\context-win32.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\system\Windows\context-win32.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\system\Windows\pthreads-win32.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\system\Windows\regset.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\system\Windows\windbgcache.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\system\Windows\windbgcache.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <File
+ RelativePath=".\config.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/tests/mem-leaks/config.h b/tests/mem-leaks/config.h
new file mode 100644
index 000000000..d7cfe64cb
--- /dev/null
+++ b/tests/mem-leaks/config.h
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * 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.
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+
+#ifndef D_config
+
+#define USE_HW_BPS 0
+#include "../../agent/config.h"
+
+#endif /* D_config */ \ No newline at end of file
diff --git a/tests/mem-leaks/main/services-ext.h b/tests/mem-leaks/main/services-ext.h
new file mode 100644
index 000000000..69fdaf90c
--- /dev/null
+++ b/tests/mem-leaks/main/services-ext.h
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 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.
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+
+/*
+ * Services initialization code extension point.
+ * If the agent is built with additional user-defined services,
+ * a customized version of services-ext.h file can be added to compiler headers search paths.
+ */
+
+#include <services/memtrace.h>
+
+static void ini_ext_services(Protocol * proto, TCFBroadcastGroup * bcg) {
+ ini_mem_trace_service(proto);
+}
diff --git a/tests/mem-leaks/services/memtrace.c b/tests/mem-leaks/services/memtrace.c
new file mode 100644
index 000000000..688f04f20
--- /dev/null
+++ b/tests/mem-leaks/services/memtrace.c
@@ -0,0 +1,732 @@
+/*******************************************************************************
+ * 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.
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+
+/*
+ * Memory Trace service.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <assert.h>
+#include <framework/link.h>
+#include <framework/myalloc.h>
+#include <framework/protocol.h>
+#include <framework/context.h>
+#include <services/breakpoints.h>
+#include <services/stacktrace.h>
+#include <services/linenumbers.h>
+#include <services/memtrace.h>
+#include <system/Windows/context-win32.h>
+
+#define FUNC_CREATE 1
+#define FUNC_ALLOC 2
+#define FUNC_REALLOC 3
+#define FUNC_EXPAND 4
+#define FUNC_FREE 5
+#define FUNC_DESTROY 6
+
+typedef struct EventPoint {
+ char * name;
+ int heap_type;
+ int func_type;
+} EventPoint;
+
+static EventPoint points[] = {
+ { "_malloc", 1, FUNC_ALLOC },
+ { "_realloc", 1, FUNC_REALLOC },
+ { "_expand", 1, FUNC_EXPAND },
+ { "_free", 1, FUNC_FREE },
+
+ { "malloc", 1, FUNC_ALLOC },
+ { "realloc", 1, FUNC_REALLOC },
+ { "free", 1, FUNC_FREE },
+
+ { "_malloc_dbg", 2, FUNC_ALLOC },
+ { "_realloc_dbg", 2, FUNC_REALLOC },
+ { "_expand_dbg", 2, FUNC_EXPAND },
+ { "_free_dbg", 2, FUNC_FREE },
+
+ { "HeapCreate", 3, FUNC_CREATE },
+ { "HeapAlloc", 3, FUNC_ALLOC },
+ { "HeapReAlloc", 3, FUNC_REALLOC },
+ { "HeapFree", 3, FUNC_FREE },
+ { "HeapDestroy", 3, FUNC_DESTROY },
+ { NULL, 0, 0 }
+};
+
+#define STK_TRACE_SIZE 8
+#define STK_HASH_SIZE 511
+#define MEM_HASH_SIZE 111
+
+typedef struct StackTrace {
+ LINK link_all;
+ Context * mem;
+ int heap_type;
+ int func_type;
+ int frame_cnt;
+ ContextAddress frames[STK_TRACE_SIZE];
+
+ int call_cnt;
+ uint64_t size_total;
+ uint64_t size_current;
+} StackTrace;
+/* TODO: 'frames' must be represented as module plus offset to support DLL loading/unloading */
+
+typedef struct MemBlock {
+ int heap_type;
+ ContextAddress addr;
+ ContextAddress size;
+ StackTrace * trace;
+ struct MemBlock * l;
+ struct MemBlock * r;
+ int bal;
+} MemBlock;
+
+typedef struct MemorySpace {
+ LINK link_all;
+ LINK link_rtn;
+ LINK stk_hash[STK_HASH_SIZE];
+ Context * mem;
+ MemBlock * table;
+ time_t report_time;
+} MemorySpace;
+
+typedef struct ReturnPoint {
+ LINK link_mem;
+ Context * ctx;
+ MemorySpace * mem;
+ StackTrace * trace;
+ ContextAddress addr;
+ ContextAddress args[2];
+} ReturnPoint;
+
+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;
+
+#define link_mem2trace(x) ((StackTrace *)((char *)(x) - offsetof(StackTrace, link_all)))
+#define link_mem2ret(x) ((ReturnPoint *)((char *)(x) - offsetof(ReturnPoint, link_mem)))
+#define link_all2mem(x) ((MemorySpace *)((char *)(x) - offsetof(MemorySpace, link_all)))
+
+static unsigned calc_trace_hash(StackTrace * t) {
+ int i;
+ unsigned h = ((uintptr_t)t->mem >> 4) + t->heap_type + t->func_type;
+ for (i = 0; i < t->frame_cnt; i++) {
+ h += (unsigned)t->frames[i];
+ }
+ return h % STK_HASH_SIZE;
+}
+
+static unsigned calc_mem_hash(Context * ctx) {
+ return (unsigned)ctx->mem % MEM_HASH_SIZE;
+}
+
+static MemorySpace * get_mem_space(Context * ctx, int alloc) {
+ MemorySpace * m = NULL;
+ unsigned h = calc_mem_hash(ctx);
+ LINK * l = mem_hash[h].next;
+ while (l != mem_hash + h) {
+ MemorySpace * x = link_all2mem(l);
+ l = l->next;
+ if (x->mem == ctx->mem) {
+ m = x;
+ break;
+ }
+ }
+ if (m == NULL && alloc) {
+ int i;
+ m = (MemorySpace *)loc_alloc_zero(sizeof(MemorySpace));
+ m->mem = ctx->mem;
+ list_init(&m->link_rtn);
+ for (i = 0; i < STK_HASH_SIZE; i++) list_init(m->stk_hash + i);
+ list_add_first(&m->link_all, mem_hash + h);
+ }
+ return m;
+}
+
+static void free_mem_block(MemBlock * x) {
+ if (x->l) free_mem_block(x->l);
+ if (x->r) free_mem_block(x->r);
+ loc_free(x);
+}
+
+static void free_mem_space(MemorySpace * m) {
+ int i;
+
+ assert(list_is_empty(&m->link_rtn));
+ list_remove(&m->link_all);
+ for (i = 0; i < STK_HASH_SIZE; i++) {
+ LINK * l = m->stk_hash[i].next;
+ while (l != m->stk_hash + i) {
+ StackTrace * x = link_mem2trace(l);
+ l = l->next;
+ assert(x->mem == m->mem);
+ list_remove(&x->link_all);
+ loc_free(x);
+ }
+ }
+ if (m->table) free_mem_block(m->table);
+ loc_free(m);
+}
+
+static void free_return_point(ReturnPoint * r) {
+ int error = 0;
+ CONTEXT regs;
+
+ memset(&regs, 0, sizeof(regs));
+ regs.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+ if (GetThreadContext(get_context_handle(r->ctx), &regs) == 0) error = set_win32_errno(GetLastError());
+ if (!error) {
+ regs.Dr7 &= ~0x03030003;
+ if (SetThreadContext(get_context_handle(r->ctx), &regs) == 0) error = set_win32_errno(GetLastError());
+ }
+ if (error) {
+ printf("free_return_point: %s\n", errno_to_str(error));
+ }
+
+ context_unlock(r->ctx);
+ list_remove(&r->link_mem);
+ loc_free(r);
+}
+
+static void app_bal(MemBlock * x, MemBlock ** p, int * h) {
+ MemBlock * p1, * p2;
+ if (*p == NULL) {
+ *p = x;
+ x->l = NULL;
+ x->r = NULL;
+ *h = 1;
+ x->bal = 0;
+ return;
+ }
+ if ((*p)->addr > x->addr) {
+ app_bal(x, &(*p)->l, h);
+ if (*h) {
+ switch((*p)->bal) {
+ case +1: (*p)->bal = 0; (*h) = 0; break;
+ case 0: (*p)->bal =-1; break;
+ case -1:
+ p1 = (*p)->l;
+ if (p1->bal == -1) {
+ (*p)->l = p1->r; p1->r = (*p);
+ (*p)->bal = 0; (*p) = p1;
+ }
+ else {
+ p2 = p1->r; p1->r = p2->l;
+ p2->l = p1; (*p)->l = p2->r; p2->r = (*p);
+ if (p2->bal == -1) (*p)->bal = +1; else (*p)->bal = 0;
+ if (p2->bal == +1) p1->bal = -1; else p1->bal = 0;
+ (*p) = p2;
+ }
+ (*p)->bal = 0;
+ (*h) = 0;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ }
+ else if ((*p)->addr < x->addr) {
+ app_bal(x, &(*p)->r, h);
+ if (*h) {
+ switch ((*p)->bal) {
+ case -1: (*p)->bal = 0; (*h) = 0; break;
+ case 0: (*p)->bal =+1; break;
+ case +1:
+ p1 = (*p)->r;
+ if (p1->bal == +1) {
+ (*p)->r = p1->l; p1->l = *p;
+ (*p)->bal = 0; *p = p1;
+ }
+ else {
+ p2 = p1->l; p1->l = p2->r;
+ p2->r = p1; (*p)->r = p2->l; p2->l = *p;
+ if (p2->bal == +1) (*p)->bal = -1; else (*p)->bal = 0;
+ if (p2->bal == -1) p1->bal = +1; else p1->bal = 0;
+ (*p) = p2;
+ }
+ (*p)->bal = 0;
+ (*h) = 0;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ }
+}
+
+static MemBlock * rem_lost = NULL;
+
+/*
+ * remove entry x from table p
+ * h == 1 tree length decreased
+ */
+static void rem_bal(MemBlock * x, MemBlock ** p, int * h) {
+ MemBlock * p1 = NULL;
+ MemBlock * p2 = NULL;
+ assert(*p != NULL);
+ assert(x != NULL);
+ if ((*p)->addr > x->addr) {
+ if ((*p)->l == NULL) return;
+ rem_bal(x, &(*p)->l, h);
+ if (*h) {
+ switch((*p)->bal) {
+ case -1: /* left was longer */
+ (*p)->bal = 0; break;
+ case 0:
+ (*p)->bal = +1; (*h) = 0; break;
+ case +1: /* right was longer */
+ p1 = (*p)->r;
+ assert(p1 != NULL);
+ if (p1->bal == +1) {
+ assert(p1->r != NULL);
+ (*p)->r = p1->l;
+ p1->l = *p;
+ (*p)->bal = 0;
+ *p = p1;
+ (*p)->bal = 0;
+ (*h) = 1;
+ }
+ else if (p1->bal == 0 && p1->l->bal == -1) {
+ (*p)->r = p1->l;
+ p1->l = *p;
+ (*p)->bal = +1;
+ *p = p1;
+ (*p)->bal = -1;
+ (*h) = 0;
+ }
+ else {
+ int i = p1->bal;
+ p2 = p1->l;
+ p1->l = p2->r;
+ p2->r = p1;
+ (*p)->r = p2->l;
+ p2->l = *p;
+ (*p)->bal = (p2->bal == +1 ? -1 : 0);
+ p1->bal = (i < 0 && p2->bal >= 0 ? 0 : +1);
+ p2->bal = (i < 0 ? 0 : +1);
+ (*p) = p2;
+ (*h) = i < 0;
+ }
+ break;
+ default:
+ assert(0);
+ }
+ }
+ }
+ else if ((*p)->addr < x->addr) {
+ if ((*p)->r == NULL) return;
+ rem_bal(x, &(*p)->r, h);
+ if (*h) {
+ switch ((*p)->bal) {
+ case +1:
+ (*p)->bal = 0; break;
+ case 0:
+ (*p)->bal =-1; (*h) = 0; break;
+ case -1:
+ p1 = (*p)->l;
+ assert(p1 != NULL);
+ if (p1->bal == -1) {
+ (*p)->l = p1->r;
+ p1->r = *p;
+ (*p)->bal = 0;
+ (*p) = p1;
+ (*p)->bal = 0;
+ (*h) = 1;
+ }
+ else if (p1->bal == 0 && p1->r->bal == +1) {
+ (*p)->l = p1->r;
+ p1->r = *p;
+ (*p)->bal = -1;
+ (*p) = p1;
+ (*p)->bal = +1;
+ (*h) = 0;
+ }
+ else {
+ int i = p1->bal;
+ p2 = p1->r;
+ p1->r = p2->l;
+ p2->l = p1;
+ (*p)->l = p2->r;
+ p2->r = (*p);
+ (*p)->bal = (p2->bal == -1 ? +1 : 0);
+ p1->bal = (i > 0 && p2->bal <= 0 ? 0 : -1);
+ p2->bal = (i > 0 ? 0 : -1);
+ (*p) = p2;
+ (*h) = i > 0;
+ }
+ break;
+ default:
+ assert(0);
+ }
+ }
+ }
+ else if ((*p)->l == NULL) { /* found it, no left link... */
+ *p = (*p)->r; /* unlink right */
+ *h = 1; /* set flag */
+ }
+ else if ((*p)->bal < 0) {
+ rem_lost = (*p)->r; /* save right side in rem_lost */
+ *p = (*p)->l; /* unlink left */
+ *h = 1; /* set flag */
+ }
+ else {
+ assert((*p)->r != NULL);
+ rem_lost = (*p)->l; /* save left side in rem_lost */
+ *p = (*p)->r; /* unlink right */
+ *h = 1; /* set flag */
+ }
+}
+
+static void add_mem_block(MemorySpace * m, MemBlock * x) {
+ int h = 0;
+ app_bal(x, &m->table, &h);
+}
+
+static void append_tree(MemorySpace * m, MemBlock * x) {
+ if (x->l) append_tree(m, x->l);
+ if (x->r) append_tree(m, x->r);
+ add_mem_block(m, x);
+}
+
+static void rem_mem_block(MemorySpace * m, MemBlock * x) {
+ int h = 0;
+ rem_lost = NULL;
+ rem_bal(x, &m->table, &h);
+ if (rem_lost) append_tree(m, rem_lost);
+}
+
+static MemBlock * find_mem_block(MemorySpace * m, ContextAddress p, ContextAddress e) {
+ MemBlock * x = m->table;
+ while (x != NULL) {
+ if (x->addr <= e && x->addr + x->size >= p) return x;
+ x = x->addr < p ? x->r : x->l;
+ }
+ return NULL;
+}
+
+static ReturnPoint * find_pending_return_point(Context * ctx) {
+ LINK * l;
+ MemorySpace * m = NULL;
+
+ m = get_mem_space(ctx, 0);
+ if (m == NULL) return NULL;
+ l = m->link_rtn.next;
+ while (l != &m->link_rtn) {
+ ReturnPoint * r = link_mem2ret(l);
+ l = l->next;
+ if (r->ctx == ctx) return r;
+ }
+ return NULL;
+}
+
+static ContextAddress read_reg(Context * ctx, RegisterDefinition * r) {
+ size_t i;
+ ContextAddress n = 0;
+ uint8_t buf[8];
+ assert(r->size <= sizeof(buf));
+ if (context_read_reg(ctx, r, 0, r->size, buf) < 0) return 0;
+ for (i = 0; i < r->size; i++) {
+ n = n << 8;
+ n |= buf[r->big_endian ? i : r->size - i - 1];
+ }
+ return n;
+}
+
+static void return_point(Context * ctx, ReturnPoint * r) {
+ MemBlock * b = NULL;
+ ContextAddress eax = read_reg(ctx, reg_def_eax);
+
+ switch (r->trace->func_type) {
+ case FUNC_ALLOC:
+ if (eax != 0) {
+ b = (MemBlock *)loc_alloc_zero(sizeof(MemBlock));
+ b->heap_type = r->trace->heap_type;
+ b->addr = eax;
+ b->size = r->args[0];
+ b->trace = r->trace;
+ b->trace->size_current += b->size;
+ b->trace->size_total += b->size;
+ add_mem_block(r->mem, b);
+ }
+ break;
+ case FUNC_REALLOC:
+ case FUNC_EXPAND:
+ if (eax != 0) {
+ b = find_mem_block(r->mem, r->args[0], r->args[0] + 1);
+ if (b != NULL) {
+ rem_mem_block(r->mem, b);
+ b->trace->size_current -= b->size;
+ }
+ else {
+ b = (MemBlock *)loc_alloc_zero(sizeof(MemBlock));
+ }
+ b->heap_type = r->trace->heap_type;
+ b->addr = eax;
+ b->size = r->args[1];
+ b->trace = r->trace;
+ b->trace->size_current += b->size;
+ b->trace->size_total += b->size;
+ add_mem_block(r->mem, b);
+ }
+ break;
+ }
+ free_return_point(r);
+}
+
+static int sort_func(const void * x, const void * y) {
+ StackTrace * tx = *(StackTrace **)x;
+ StackTrace * ty = *(StackTrace **)y;
+ if (tx->size_current > ty->size_current) return -1;
+ if (tx->size_current < ty->size_current) return +1;
+ return 0;
+}
+
+static int print_text_pos_cnt = 0;
+
+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++;
+}
+
+static void event_point(Context * ctx, void * args) {
+ EventPoint * p = (EventPoint *)args;
+ int top_frame = STACK_NO_FRAME;
+ StackFrame * info = NULL;
+ uint64_t esp = 0;
+ uint64_t eip = 0;
+ ContextAddress buf[4];
+ MemorySpace * m = NULL;
+ static StackTrace trace;
+ StackTrace * t = NULL;
+ int error = 0;
+
+ if (find_pending_return_point(ctx) != NULL) return;
+
+ if (p->heap_type == 3) {
+ printf("%s\n", p->name);
+ return;
+ }
+
+ if ((top_frame = get_top_frame(ctx)) < 0) error = errno;
+ if (!error && get_frame_info(ctx, top_frame, &info) < 0) error = errno;
+ if (!error && read_reg_value(info, reg_def_esp, &esp) < 0) error = errno;
+ if (!error && read_reg_value(info, reg_def_eip, &eip) < 0) error = errno;
+ if (!error && context_read_mem(ctx, (ContextAddress)esp, buf, sizeof(buf)) < 0) error = errno;
+ memset(&trace, 0, sizeof(trace));
+ if (!error) {
+ trace.mem = ctx->mem;
+ trace.heap_type = p->heap_type;
+ trace.func_type = p->func_type;
+ trace.frame_cnt = 0;
+ while (trace.frame_cnt < STK_TRACE_SIZE && trace.frame_cnt < top_frame) {
+ if (get_frame_info(ctx, top_frame - trace.frame_cnt - 1, &info) < 0) {
+ error = errno;
+ break;
+ }
+ if (read_reg_value(info, reg_def_eip, &eip) < 0) {
+ error = errno;
+ break;
+ }
+ trace.frames[trace.frame_cnt++] = (ContextAddress)eip;
+ }
+ }
+ if (!error) {
+ LINK * l;
+ unsigned h = calc_trace_hash(&trace);
+ m = get_mem_space(ctx, 1);
+ for (l = m->stk_hash[h].next; l != m->stk_hash + h; l = l->next) {
+ int i;
+ StackTrace * x = (StackTrace *)link_mem2trace(l);
+ if (x->mem != trace.mem) continue;
+ if (x->heap_type != trace.heap_type) continue;
+ if (x->func_type != trace.func_type) continue;
+ if (x->frame_cnt != trace.frame_cnt) continue;
+ for (i = 0; i < trace.frame_cnt; i++) {
+ if (x->frames[i] != trace.frames[i]) break;
+ }
+ if (i == trace.frame_cnt) {
+ t = x;
+ break;
+ }
+ }
+ if (t == NULL) {
+ *(t = (StackTrace *)loc_alloc(sizeof(StackTrace))) = trace;
+ list_add_first(&t->link_all, m->stk_hash + h);
+ }
+ t->call_cnt++;
+ }
+ if (!error) {
+ if (p->func_type == FUNC_FREE) {
+ MemBlock * b = find_mem_block(m, buf[1], buf[1] + 1);
+ if (b != NULL) {
+ rem_mem_block(m, b);
+ b->trace->size_current -= b->size;
+ loc_free(b);
+ }
+ }
+ else if (p->func_type == FUNC_DESTROY) {
+ }
+ else {
+ CONTEXT regs;
+ ReturnPoint * r = (ReturnPoint *)loc_alloc_zero(sizeof(ReturnPoint));
+
+ r->trace = t;
+ r->ctx = ctx;
+ r->mem = m;
+ r->addr = buf[0];
+ r->args[0] = buf[1];
+ r->args[1] = buf[2];
+ list_add_first(&r->link_mem, &m->link_rtn);
+ context_lock(r->ctx);
+
+ memset(&regs, 0, sizeof(regs));
+ regs.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+ if (GetThreadContext(get_context_handle(ctx), &regs) == 0) error = set_win32_errno(GetLastError());
+ if (!error && (regs.Dr7 & 0x03) != 0) error = set_errno(ERR_OTHER, "HW breakpoint not available");
+ if (!error) {
+ regs.Dr0 = r->addr;
+ regs.Dr7 &= ~0x03030003;
+ regs.Dr7 |= 0x00000001;
+ if (SetThreadContext(get_context_handle(ctx), &regs) == 0) error = set_win32_errno(GetLastError());
+ }
+ if (error) free_return_point(r);
+ }
+ }
+ if (error) {
+ printf("%s: %s\n", p->name, errno_to_str(error));
+ }
+ if (m != NULL && m->report_time + 30 < time(NULL)) {
+ int i;
+ int cnt = 0;
+ m->report_time = time(NULL);
+ for (i = 0; i < STK_HASH_SIZE; i++) {
+ LINK * l = m->stk_hash[i].next;
+ while (l != m->stk_hash + i) {
+ l = l->next;
+ cnt++;
+ }
+ }
+ if (cnt > 0) {
+ int pos = 0;
+ StackTrace ** buf = (StackTrace **)loc_alloc(sizeof(StackTrace *) * cnt);
+ for (i = 0; i < STK_HASH_SIZE; i++) {
+ LINK * l = m->stk_hash[i].next;
+ while (l != m->stk_hash + i) {
+ buf[pos++] = link_mem2trace(l);
+ l = l->next;
+ }
+ }
+ assert(pos == cnt);
+ qsort(buf, cnt, sizeof(StackTrace *), sort_func);
+ printf("\nPID %d, total traces %d\n", m->mem, cnt);
+ 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);
+ for (j = 0; j < t->frame_cnt; j++) {
+ print_text_pos_cnt = 0;
+ address_to_line(ctx, t->frames[j], t->frames[j] + 1, print_text_pos, NULL);
+ if (print_text_pos_cnt == 0) {
+ printf(" 0x%08x\n", t->frames[j]);
+ }
+ }
+ }
+ loc_free(buf);
+ }
+ }
+}
+
+static void event_context_created(Context * ctx, void * args) {
+ if (ctx->parent != NULL && ctx->parent->mem == ctx->mem) return;
+
+}
+
+static int contex_exception_handler(Context * ctx, EXCEPTION_DEBUG_INFO * info) {
+ if (info->ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP) {
+ MemorySpace * m = get_mem_space(ctx, 0);
+ if (m != NULL) {
+ LINK * l = m->link_rtn.next;
+ while (l != &m->link_rtn) {
+ ReturnPoint * r = link_mem2ret(l);
+ l = l->next;
+ if (r->ctx == ctx) {
+ ContextAddress addr = read_reg(ctx, reg_def_eip);
+ if (r->addr == addr) {
+ return_point(ctx, r);
+ return 1;
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static void event_context_stopped(Context * ctx, void * args) {
+}
+
+static void event_context_exited(Context * ctx, void * args) {
+ MemorySpace * m = get_mem_space(ctx, 0);
+ if (m != NULL) {
+ LINK * l = m->link_rtn.next;
+ while (l != &m->link_rtn) {
+ ReturnPoint * r = link_mem2ret(l);
+ l = l->next;
+ if (r->ctx == ctx) {
+ free_return_point(r);
+ break;
+ }
+ }
+ if (ctx->parent == NULL || ctx->parent->mem != ctx->mem) {
+ free_mem_space(m);
+ }
+ }
+}
+
+void ini_mem_trace_service(Protocol * proto) {
+ int i;
+ EventPoint * p = points;
+ RegisterDefinition * r = get_reg_definitions(NULL);
+
+ static ContextEventListener listener = {
+ event_context_created,
+ event_context_exited,
+ event_context_stopped,
+ NULL,
+ NULL
+ };
+
+ while (p->name) {
+ create_eventpoint(p->name, NULL, event_point, p);
+ p++;
+ }
+
+ for (i = 0; i < MEM_HASH_SIZE; i++) list_init(mem_hash + i);
+
+ while (r->name != NULL) {
+ if (strcmp(r->name, "eax") == 0) reg_def_eax = r;
+ if (strcmp(r->name, "esp") == 0) reg_def_esp = r;
+ if (strcmp(r->name, "eip") == 0) reg_def_eip = r;
+ r++;
+ }
+
+ add_context_event_listener(&listener, NULL);
+ add_context_exception_handler(contex_exception_handler);
+}
diff --git a/tests/mem-leaks/services/memtrace.h b/tests/mem-leaks/services/memtrace.h
new file mode 100644
index 000000000..c6552cdc5
--- /dev/null
+++ b/tests/mem-leaks/services/memtrace.h
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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.
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+
+/*
+ * Memory Trace service.
+ */
+
+#ifndef D_memtrace
+#define D_memtrace
+
+#include <config.h>
+#include <framework/protocol.h>
+
+extern void ini_mem_trace_service(Protocol * proto);
+
+#endif /* D_memtrace */

Back to the top