diff options
author | Eugene Tarassov | 2011-11-14 21:50:54 +0000 |
---|---|---|
committer | Eugene Tarassov | 2011-11-14 21:50:54 +0000 |
commit | f8787883efb88ea0a955eedce357a893f3a58cc0 (patch) | |
tree | 5eb1c850960a2033beee8edceaba61b934c9cebe | |
parent | 3e513d6057e50f027f97ab86f5a21e13b1569691 (diff) | |
download | org.eclipse.tcf.agent-f8787883efb88ea0a955eedce357a893f3a58cc0.tar.gz org.eclipse.tcf.agent-f8787883efb88ea0a955eedce357a893f3a58cc0.tar.xz org.eclipse.tcf.agent-f8787883efb88ea0a955eedce357a893f3a58cc0.zip |
TCF Tests: agent tests "mem-leaks" and "test-dwarf" are moved into the agent repository.
-rw-r--r-- | .gitignore | 18 | ||||
-rw-r--r-- | tests/mem-leaks/Makefile | 30 | ||||
-rw-r--r-- | tests/mem-leaks/agent.sln | 20 | ||||
-rw-r--r-- | tests/mem-leaks/agent.vcproj | 647 | ||||
-rw-r--r-- | tests/mem-leaks/tcf/config.h | 21 | ||||
-rw-r--r-- | tests/mem-leaks/tcf/main/services-ext.h | 26 | ||||
-rw-r--r-- | tests/mem-leaks/tcf/services/memtrace.c | 799 | ||||
-rw-r--r-- | tests/mem-leaks/tcf/services/memtrace.h | 28 | ||||
-rw-r--r-- | tests/test-dwarf/Makefile | 30 | ||||
-rw-r--r-- | tests/test-dwarf/dwarf-test.sln | 20 | ||||
-rw-r--r-- | tests/test-dwarf/dwarf-test.vcproj | 692 | ||||
-rw-r--r-- | tests/test-dwarf/tcf/backend/backend.c | 565 | ||||
-rw-r--r-- | tests/test-dwarf/tcf/backend/backend.h | 31 | ||||
-rw-r--r-- | tests/test-dwarf/tcf/config.h | 98 | ||||
-rw-r--r-- | tests/test-dwarf/tcf/machine/cpudefs-ext.h | 114 |
15 files changed, 3139 insertions, 0 deletions
@@ -20,9 +20,27 @@ agent/cmake/gcc-debug # server/ server/obj server/*.ncb +server/*.opt
+server/*.plt
server/*.suo server/*.user # examples/daytime/
examples/daytime/obj
+# tests/mem-leaks/
+tests/mem-leaks/obj
+tests/mem-leaks/*.ncb
+tests/mem-leaks/*.opt
+tests/mem-leaks/*.plt
+tests/mem-leaks/*.suo
+tests/mem-leaks/*.user
+
+# tests/test-dwarf/
+tests/test-dwarf/obj
+tests/test-dwarf/*.ncb
+tests/test-dwarf/*.opt
+tests/test-dwarf/*.plt
+tests/test-dwarf/*.suo
+tests/test-dwarf/*.user
+
diff --git a/tests/mem-leaks/Makefile b/tests/mem-leaks/Makefile new file mode 100644 index 00000000..91bc280d --- /dev/null +++ b/tests/mem-leaks/Makefile @@ -0,0 +1,30 @@ +TCF_AGENT_DIR=../../agent + +include $(TCF_AGENT_DIR)/Makefile.inc + +override CFLAGS += $(foreach dir,$(INCDIRS),-I$(dir)) $(OPTS) + +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)/tcf/main/main$(EXTOBJ) $(BINDIR)/libtcf$(EXTLIB) + $(CC) $(CFLAGS) -o $@ $(BINDIR)/tcf/main/main$(EXTOBJ) $(BINDIR)/libtcf$(EXTLIB) $(LIBS) + +$(BINDIR)/%$(EXTOBJ): %.c $(HFILES) Makefile + @$(call MKDIR,$(dir $@)) + $(CC) $(CFLAGS) -c -o $@ $< + +$(BINDIR)/%$(EXTOBJ): $(TCF_AGENT_DIR)/%.c $(HFILES) Makefile + @$(call MKDIR,$(dir $@)) + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + $(call RMDIR,$(BINDIR)) diff --git a/tests/mem-leaks/agent.sln b/tests/mem-leaks/agent.sln new file mode 100644 index 00000000..0701c5ad --- /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 00000000..73c0546b --- /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=".;..\..\agent;..\..\agent\tcf\system\Windows;..\..\agent\tcf\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=".;..\..\agent;..\..\agent\tcf\system\Windows;..\..\agent\tcf\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\tcf\main\cmdline.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\main\cmdline.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\main\main.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\main\server.c"
+ >
+ </File>
+ <File
+ RelativePath=".\tcf\main\services-ext.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\main\services.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\main\test.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\main\test.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="services"
+ >
+ <File
+ RelativePath="..\..\agent\tcf\services\breakpoints.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\breakpoints.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\diagnostics.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\diagnostics.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\discovery.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\discovery.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\discovery_udp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\discovery_udp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\expressions.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\expressions.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\filesystem.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\filesystem.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\linenumbers.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\linenumbers.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\linenumbers_elf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\linenumbers_proxy.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\linenumbers_win32.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\memorymap.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\memorymap.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\memoryservice.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\memoryservice.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\pathmap.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\pathmap.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\processes.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\processes.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\registers.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\registers.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\runctrl.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\runctrl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\stacktrace.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\stacktrace.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\streamsservice.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\streamsservice.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\symbols.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\symbols.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\symbols_alloc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\symbols_elf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\symbols_proxy.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\symbols_win32.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\sysmon.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\sysmon.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\terminals.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\terminals.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="framework"
+ >
+ <File
+ RelativePath="..\..\agent\tcf\framework\asyncreq.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\asyncreq.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\base64.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\base64.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\cache.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\cache.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\channel.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\channel.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\channel_pipe.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\channel_pipe.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\channel_tcp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\channel_tcp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\context.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\context.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\cpudefs.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\cpudefs.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\errors.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\errors.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\events.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\events.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\exceptions.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\exceptions.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\inputbuf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\inputbuf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\ip_ifc.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\ip_ifc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\json.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\json.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\link.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\mdep.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\mdep.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\myalloc.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\myalloc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\outputbuf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\outputbuf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\peer.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\peer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\plugins.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\plugins.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\protocol.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\protocol.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\proxy.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\proxy.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\signames.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\signames.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\streams.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\streams.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\tcf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\trace.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\trace.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\waitpid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\waitpid.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="trace"
+ >
+ <File
+ RelativePath=".\tcf\services\memtrace.c"
+ >
+ </File>
+ <File
+ RelativePath=".\tcf\services\memtrace.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="system"
+ >
+ <Filter
+ Name="Windows"
+ >
+ <File
+ RelativePath="..\..\agent\tcf\system\Windows\context-win32.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\system\Windows\context-win32.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\system\Windows\pthreads-win32.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\system\Windows\regset.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\system\Windows\windbgcache.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\system\Windows\windbgcache.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <File
+ RelativePath=".\tcf\config.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/tests/mem-leaks/tcf/config.h b/tests/mem-leaks/tcf/config.h new file mode 100644 index 00000000..1be5b65a --- /dev/null +++ b/tests/mem-leaks/tcf/config.h @@ -0,0 +1,21 @@ +/******************************************************************************* + * 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. + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ + +#ifndef D_config + +#define USE_HW_BPS 0 +#include "../../agent/tcf/config.h" + +#endif /* D_config */
\ No newline at end of file diff --git a/tests/mem-leaks/tcf/main/services-ext.h b/tests/mem-leaks/tcf/main/services-ext.h new file mode 100644 index 00000000..d8ffca70 --- /dev/null +++ b/tests/mem-leaks/tcf/main/services-ext.h @@ -0,0 +1,26 @@ +/******************************************************************************* + * 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. + * You may elect to redistribute this code under either of these licenses. + * + * 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 <tcf/services/memtrace.h> + +static void ini_ext_services(Protocol * proto, TCFBroadcastGroup * bcg) { + ini_mem_trace_service(proto); +} diff --git a/tests/mem-leaks/tcf/services/memtrace.c b/tests/mem-leaks/tcf/services/memtrace.c new file mode 100644 index 00000000..80a0f659 --- /dev/null +++ b/tests/mem-leaks/tcf/services/memtrace.c @@ -0,0 +1,799 @@ +/******************************************************************************* + * 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. + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ + +/* + * Memory Trace service. + */ + +#include "tcf/config.h" + +#include <stdio.h> +#include <assert.h> +#include <tcf/framework/link.h> +#include <tcf/framework/myalloc.h> +#include <tcf/framework/protocol.h> +#include <tcf/framework/context.h> +#include <tcf/services/breakpoints.h> +#include <tcf/services/stacktrace.h> +#include <tcf/services/linenumbers.h> +#include <tcf/services/memtrace.h> +#if defined(WIN32) +# include <tcf/system/Windows/context-win32.h> +#endif + +#define USE_DEBUG_REGS 0 + +#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 }, + +#if defined(WIN32) + { "_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 }, +#endif + + { 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; +#if !USE_DEBUG_REGS + BreakpointInfo * bp; +#endif + 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; +static RegisterDefinition * reg_def_rdi = NULL; +static RegisterDefinition * reg_def_rsi = 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)((uintptr_t)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; + +#if USE_DEBUG_REGS + CONTEXT regs; + + memset(®s, 0, sizeof(regs)); + regs.ContextFlags = CONTEXT_DEBUG_REGISTERS; + if (GetThreadContext(get_context_handle(r->ctx), ®s) == 0) error = set_win32_errno(GetLastError()); + if (!error) { + regs.Dr7 &= ~0x03030003; + if (SetThreadContext(get_context_handle(r->ctx), ®s) == 0) error = set_win32_errno(GetLastError()); + } +#else + destroy_eventpoint(r->bp); +#endif + + 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++; +} + +#if !USE_DEBUG_REGS +static void rp_callback(Context * ctx, void * args) { + ReturnPoint * r = (ReturnPoint *)args; + assert(r->ctx == ctx); + return_point(ctx, r); +} +#endif + +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; + uint64_t rdi = 0; + uint64_t rsi = 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 = set_errno(errno, "Cannot get top frame"); + if (!error && get_frame_info(ctx, top_frame, &info) < 0) error = set_errno(errno, "Cannot get frame info"); + if (!error && read_reg_value(info, reg_def_esp, &esp) < 0) error = set_errno(errno, "Cannot read SP register"); + if (!error && read_reg_value(info, reg_def_eip, &eip) < 0) error = set_errno(errno, "Cannot read IP register"); +#if defined(__x86_64__) + if (!error && read_reg_value(info, reg_def_rdi, &rdi) < 0) error = set_errno(errno, "Cannot read DI register"); + if (!error && read_reg_value(info, reg_def_rsi, &rsi) < 0) error = set_errno(errno, "Cannot read SI register"); +#endif + if (!error && context_read_mem(ctx, (ContextAddress)esp, buf, sizeof(buf)) < 0) error = set_errno(errno, "Cannot read memory"); + 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) { + if (trace.frame_cnt == 0) error = errno; + break; + } + if (read_reg_value(info, reg_def_eip, &eip) < 0) { + if (trace.frame_cnt == 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) { +#if defined(__x86_64__) + ContextAddress addr = (ContextAddress)rdi; +#else + ContextAddress addr = buf[1]; +#endif + MemBlock * b = find_mem_block(m, addr, addr + 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 { + ReturnPoint * r = (ReturnPoint *)loc_alloc_zero(sizeof(ReturnPoint)); + + r->trace = t; + r->ctx = ctx; + r->mem = m; + r->addr = buf[0]; +#if defined(__x86_64__) + r->args[0] = (ContextAddress)rdi; + r->args[1] = (ContextAddress)rsi; +#else + r->args[0] = buf[1]; + r->args[1] = buf[2]; +#endif + list_add_first(&r->link_mem, &m->link_rtn); + context_lock(r->ctx); + +#if USE_DEBUG_REGS + { + CONTEXT regs; + memset(®s, 0, sizeof(regs)); + regs.ContextFlags = CONTEXT_DEBUG_REGISTERS; + if (GetThreadContext(get_context_handle(ctx), ®s) == 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), ®s) == 0) error = set_win32_errno(GetLastError()); + } + } +#else + { + char buf[64]; + snprintf(buf, sizeof(buf), "0x%" PRIX64, (uint64_t)r->addr); + r->bp = create_eventpoint(buf, ctx, rp_callback, r); + } +#endif + 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("\nID %s, total traces %d\n", m->mem->id, 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%" PRIX64 "\n", (uint64_t)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; + +} + +#if USE_DEBUG_REGS +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; +} +#endif + +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 defined(__x86_64__) + if (strcmp(r->name, "rax") == 0) reg_def_eax = r; + if (strcmp(r->name, "rsp") == 0) reg_def_esp = r; + if (strcmp(r->name, "rip") == 0) reg_def_eip = r; + if (strcmp(r->name, "rdi") == 0) reg_def_rdi = r; + if (strcmp(r->name, "rsi") == 0) reg_def_rsi = r; +#elif defined(__i386__) + 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; +#else +# error Unknown CPU +#endif + r++; + } + + add_context_event_listener(&listener, NULL); +#if USE_DEBUG_REGS + add_context_exception_handler(contex_exception_handler); +#endif +} diff --git a/tests/mem-leaks/tcf/services/memtrace.h b/tests/mem-leaks/tcf/services/memtrace.h new file mode 100644 index 00000000..961dc678 --- /dev/null +++ b/tests/mem-leaks/tcf/services/memtrace.h @@ -0,0 +1,28 @@ +/******************************************************************************* + * 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. + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ + +/* + * Memory Trace service. + */ + +#ifndef D_memtrace +#define D_memtrace + +#include <tcf/config.h> +#include <tcf/framework/protocol.h> + +extern void ini_mem_trace_service(Protocol * proto); + +#endif /* D_memtrace */ diff --git a/tests/test-dwarf/Makefile b/tests/test-dwarf/Makefile new file mode 100644 index 00000000..657b0729 --- /dev/null +++ b/tests/test-dwarf/Makefile @@ -0,0 +1,30 @@ +TCF_AGENT_DIR=../../agent + +include $(TCF_AGENT_DIR)/Makefile.inc + +override CFLAGS += $(foreach dir,$(INCDIRS),-I$(dir)) $(OPTS) + +HFILES := $(foreach dir,$(SRCDIRS) tcf/backend,$(wildcard $(dir)/*.h)) $(HFILES) +CFILES := $(sort $(foreach dir,$(SRCDIRS) tcf/backend,$(wildcard $(dir)/*.c)) $(CFILES)) + +EXECS = $(BINDIR)/dwarf-test$(EXTEXE) + +all: $(EXECS) + +$(BINDIR)/libtcf$(EXTLIB) : $(OFILES) + $(AR) -rc $@ $^ + $(RANLIB) + +$(BINDIR)/dwarf-test$(EXTEXE): $(BINDIR)/tcf/main/main$(EXTOBJ) $(BINDIR)/libtcf$(EXTLIB) + $(CC) $(CFLAGS) -o $@ $(BINDIR)/tcf/main/main$(EXTOBJ) $(BINDIR)/libtcf$(EXTLIB) $(LIBS) + +$(BINDIR)/%$(EXTOBJ): %.c $(HFILES) Makefile + @$(call MKDIR,$(dir $@)) + $(CC) $(CFLAGS) -c -o $@ $< + +$(BINDIR)/%$(EXTOBJ): $(TCF_AGENT_DIR)/%.c $(HFILES) Makefile + @$(call MKDIR,$(dir $@)) + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + $(call RMDIR,$(BINDIR)) diff --git a/tests/test-dwarf/dwarf-test.sln b/tests/test-dwarf/dwarf-test.sln new file mode 100644 index 00000000..5c46eb12 --- /dev/null +++ b/tests/test-dwarf/dwarf-test.sln @@ -0,0 +1,20 @@ +
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual C++ Express 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dwarf-test", "dwarf-test.vcproj", "{D08FED31-38A6-4239-8D20-D4276FC2BAFA}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {D08FED31-38A6-4239-8D20-D4276FC2BAFA}.Debug|Win32.ActiveCfg = Debug|Win32
+ {D08FED31-38A6-4239-8D20-D4276FC2BAFA}.Debug|Win32.Build.0 = Debug|Win32
+ {D08FED31-38A6-4239-8D20-D4276FC2BAFA}.Release|Win32.ActiveCfg = Release|Win32
+ {D08FED31-38A6-4239-8D20-D4276FC2BAFA}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/tests/test-dwarf/dwarf-test.vcproj b/tests/test-dwarf/dwarf-test.vcproj new file mode 100644 index 00000000..c4217bb1 --- /dev/null +++ b/tests/test-dwarf/dwarf-test.vcproj @@ -0,0 +1,692 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="dwarf-test"
+ ProjectGUID="{D08FED31-38A6-4239-8D20-D4276FC2BAFA}"
+ RootNamespace="symtest"
+ 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="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=".;..\..\agent"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="WS2_32.lib Iphlpapi.lib"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ 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="1"
+ 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=".;..\..\agent"
+ 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"
+ 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="framework"
+ >
+ <File
+ RelativePath="..\..\agent\tcf\framework\asyncreq.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\asyncreq.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\base64.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\base64.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\cache.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\cache.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\channel.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\channel.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\channel_pipe.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\channel_pipe.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\channel_tcp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\channel_tcp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\context.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\context.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\cpudefs.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\cpudefs.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\errors.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\errors.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\events.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\events.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\exceptions.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\exceptions.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\inputbuf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\inputbuf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\ip_ifc.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\ip_ifc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\json.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\json.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\link.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\mdep.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\mdep.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\myalloc.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\myalloc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\outputbuf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\outputbuf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\peer.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\peer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\plugins.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\plugins.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\protocol.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\protocol.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\proxy.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\proxy.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\signames.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\signames.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\streams.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\streams.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\tcf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\trace.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\trace.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\waitpid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\framework\waitpid.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="main"
+ >
+ <File
+ RelativePath="..\..\agent\tcf\main\main.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\main\server.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\main\server.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\main\services-ext.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\main\services.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\main\services.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="services"
+ >
+ <File
+ RelativePath="..\..\agent\tcf\services\breakpoints.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\breakpoints.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\diagnostics.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\diagnostics.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\discovery.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\discovery.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\discovery_udp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\discovery_udp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\dwarf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\dwarfcache.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\dwarfcache.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\dwarfexpr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\dwarfexpr.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\dwarfframe.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\dwarfframe.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\dwarfio.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\dwarfio.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\dwarfreloc.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\dwarfreloc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\expressions.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\expressions.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\filesystem.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\filesystem.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\linenumbers.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\linenumbers.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\linenumbers_elf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\linenumbers_proxy.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\linenumbers_win32.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\memorymap.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\memorymap.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\memoryservice.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\memoryservice.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\pathmap.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\pathmap.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\processes.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\processes.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\registers.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\registers.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\runctrl.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\runctrl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\stacktrace.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\stacktrace.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\streamsservice.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\streamsservice.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\symbols.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\symbols.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\symbols_alloc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\symbols_elf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\symbols_proxy.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\symbols_win32.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\sysmon.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\sysmon.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\tcf_elf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\tcf_elf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\terminals.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\terminals.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\vm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\vm.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="machine"
+ >
+ <File
+ RelativePath=".\tcf\machine\cpudefs-ext.h"
+ >
+ </File>
+ <Filter
+ Name="i386"
+ >
+ <File
+ RelativePath="..\..\agent\tcf\machine\i386\elf-mdep.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="backend"
+ >
+ <File
+ RelativePath=".\tcf\backend\backend.c"
+ >
+ </File>
+ <File
+ RelativePath=".\tcf\backend\backend.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="system"
+ >
+ <File
+ RelativePath="..\..\agent\tcf\system\Windows\pthreads-win32.c"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\tcf\config.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/tests/test-dwarf/tcf/backend/backend.c b/tests/test-dwarf/tcf/backend/backend.c new file mode 100644 index 00000000..3b54261b --- /dev/null +++ b/tests/test-dwarf/tcf/backend/backend.c @@ -0,0 +1,565 @@ +/******************************************************************************* + * Copyright (c) 2010, 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. + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ + +/* Fake debug context API implementation. It used for testing symbol services. */ + +#include <tcf/config.h> + +#include <sys/stat.h> +#include <assert.h> +#include <stdio.h> +#if !defined(WIN32) || defined(__CYGWIN__) +# include <dirent.h> +#endif + +#include <tcf/framework/context.h> +#include <tcf/framework/events.h> +#include <tcf/framework/myalloc.h> +#include <tcf/framework/exceptions.h> + +#include <tcf/services/tcf_elf.h> +#include <tcf/services/symbols.h> +#include <tcf/services/linenumbers.h> +#include <tcf/services/memorymap.h> +#include <tcf/services/dwarfframe.h> + +#include <tcf/backend/backend.h> + +#ifndef S_ISDIR +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif + +static Context * elf_ctx = NULL; +static MemoryMap mem_map; +static RegisterDefinition reg_defs[MAX_REGS]; +static char reg_names[MAX_REGS][32]; +static uint8_t reg_vals[MAX_REGS * 8]; +static unsigned reg_size = 0; + +static uint8_t frame_data[0x1000]; +static ContextAddress frame_addr = 0x40000000u; + +static const char * elf_file_name = NULL; +static int mem_region_pos = 0; +static ContextAddress pc = 0; +static unsigned pass_cnt = 0; +static int test_posted = 0; +static struct timespec time_start; + +static char ** files = NULL; +static unsigned files_max = 0; +static unsigned files_cnt = 0; + +RegisterDefinition * get_reg_definitions(Context * ctx) { + return reg_defs; +} + +RegisterDefinition * get_PC_definition(Context * ctx) { + return reg_defs; +} + +Context * id2ctx(const char * id) { + if (id != NULL && strcmp(id, elf_ctx->id) == 0) return elf_ctx; + return NULL; +} + +unsigned context_word_size(Context * ctx) { + return get_PC_definition(ctx)->size; +} + +int context_has_state(Context * ctx) { + return 1; +} + +Context * context_get_group(Context * ctx, int group) { + return ctx; +} + +int context_read_reg(Context * ctx, RegisterDefinition * def, unsigned offs, unsigned size, void * buf) { + if (ctx != elf_ctx) { + errno = ERR_INV_CONTEXT; + return -1; + } + memcpy(buf, reg_vals + def->offset + offs, size); + return 0; +} + +int context_write_reg(Context * ctx, RegisterDefinition * def, unsigned offs, unsigned size, void * buf) { + if (ctx != elf_ctx) { + errno = ERR_INV_CONTEXT; + return -1; + } + memcpy(reg_vals + def->offset + offs, buf, size); + return 0; +} + +int context_read_mem(Context * ctx, ContextAddress address, void * buf, size_t size) { + if (address >= frame_addr && address + size >= address && address + size <= frame_addr + sizeof(frame_data)) { + memcpy(buf, frame_data + (address - frame_addr), size); + return 0; + } + memset(buf, 0, size); + return 0; +} + +int context_write_mem(Context * ctx, ContextAddress address, void * buf, size_t size) { + /* TODO: context_write_mem */ + errno = ERR_UNSUPPORTED; + return -1; +} + +int context_get_memory_map(Context * ctx, MemoryMap * map) { + unsigned i; + for (i = 0; i < mem_map.region_cnt; i++) { + MemoryRegion * r = NULL; + if (map->region_cnt >= map->region_max) { + map->region_max += 8; + map->regions = (MemoryRegion *)loc_realloc(map->regions, sizeof(MemoryRegion) * map->region_max); + } + r = map->regions + map->region_cnt++; + *r = mem_map.regions[i]; + if (r->file_name) r->file_name = loc_strdup(r->file_name); + if (r->sect_name) r->sect_name = loc_strdup(r->sect_name); + } + return 0; +} + +int crawl_stack_frame(StackFrame * frame, StackFrame * down) { + if (frame->is_top_frame) { + frame->fp = frame_addr; + return 0; + } + errno = ERR_INV_ADDRESS; + return -1; +} + +static void error(const char * func) { + int err = errno; + printf("File : %s\n", elf_file_name); + printf("Address : 0x%" PRIX64 "\n", (uint64_t)pc); + printf("Function: %s\n", func); + printf("Error : %s\n", errno_to_str(err)); + fflush(stdout); + exit(1); +} + +static void line_numbers_callback(CodeArea * area, void * args) { + CodeArea * dst = (CodeArea *)args; + *dst = *area; +} + +static void print_time(struct timespec time_start, int cnt) { + struct timespec time_now; + struct timespec time_diff; + if (cnt == 0) return; + clock_gettime(CLOCK_REALTIME, &time_now); + time_diff.tv_sec = time_now.tv_sec - time_start.tv_sec; + if (time_now.tv_nsec < time_start.tv_nsec) { + time_diff.tv_sec--; + time_diff.tv_nsec = time_now.tv_nsec + 1000000000 - time_start.tv_nsec; + } + else { + time_diff.tv_nsec = time_now.tv_nsec - time_start.tv_nsec; + } + time_diff.tv_nsec /= cnt; + time_diff.tv_nsec += (long)(((uint64_t)(time_diff.tv_sec % cnt) * 1000000000) / cnt); + time_diff.tv_sec /= cnt; + printf("search time: %ld.%06ld\n", (long)time_diff.tv_sec, time_diff.tv_nsec / 1000); + fflush(stdout); +} + +static void test(void * args); + +static void loc_var_func(void * args, Symbol * sym) { + int frame = 0; + Context * ctx = NULL; + RegisterDefinition * reg = NULL; + ContextAddress addr = 0; + ContextAddress size = 0; + SYM_FLAGS flags = 0; + int symbol_class = 0; + int type_class = 0; + Symbol * type = NULL; + Symbol * index_type = NULL; + Symbol * base_type = NULL; + ContextAddress length = 0; + int64_t lower_bound = 0; + void * value = NULL; + size_t value_size = 0; + int value_big_endian = 0; + + if (get_symbol_flags(sym, &flags) < 0) { + error("get_symbol_flags"); + } + + if (get_symbol_address(sym, &addr) < 0) { + int err = errno; + if ((get_symbol_register(sym, &ctx, &frame, ®) < 0 || reg == NULL) && + (get_symbol_value(sym, &value, &value_size, &value_big_endian) < 0 || value == NULL)) { + if (strncmp(errno_to_str(err), "No object location info found", 29) == 0) return; + if (strncmp(errno_to_str(err), "Object is not available", 23) == 0) return; + if (strncmp(errno_to_str(err), "Object has no RT address", 24) == 0) return; + errno = err; + error("get_symbol_address"); + } + } + if (get_symbol_size(sym, &size) < 0) { + error("get_symbol_size"); + } + if (get_symbol_class(sym, &symbol_class) < 0) { + error("get_symbol_class"); + } + if (get_symbol_type(sym, &type) < 0) { + error("get_symbol_type"); + } + if (type != NULL) { + if (get_symbol_type_class(sym, &type_class) < 0) { + error("get_symbol_type_class"); + } + if (get_symbol_flags(type, &flags) < 0) { + error("get_symbol_flags"); + } + if (type_class == TYPE_CLASS_ARRAY) { + if (get_symbol_index_type(type, &index_type) < 0) { + error("get_symbol_index_type"); + } + if (get_symbol_base_type(type, &base_type) < 0) { + error("get_symbol_base_type"); + } + if (get_symbol_length(type, &length) < 0) { + error("get_symbol_length"); + } + if (get_symbol_lower_bound(type, &lower_bound) < 0) { + error("get_symbol_lower_bound"); + } + } + else if (type_class == TYPE_CLASS_POINTER) { + if (get_symbol_base_type(type, &base_type) < 0) { + error("get_symbol_base_type"); + } + } + else if (type_class == TYPE_CLASS_ENUMERATION) { + int i; + int count = 0; + Symbol ** children = NULL; + if (get_symbol_children(type, &children, &count) < 0) { + error("get_symbol_children"); + } + for (i = 0; i < count; i++) { + void * value = NULL; + size_t value_size = 0; + int big_endian = 0; + if (get_symbol_value(children[i], &value, &value_size, &big_endian) < 0) { + error("get_symbol_value"); + } + } + } + } +} + +static void next_pc(void) { + Symbol * sym = NULL; + CodeArea area; + ContextAddress lt_addr; + ELF_File * lt_file; + ELF_Section * lt_sec; + struct timespec time_now; + Trap trap; + int test_cnt = 0; + int loaded = mem_region_pos < 0; + + for (;;) { + if (mem_region_pos < 0) { + mem_region_pos = 0; + pc = mem_map.regions[mem_region_pos].addr; + } + else if (pc + 5 < mem_map.regions[mem_region_pos].addr + mem_map.regions[mem_region_pos].size) { + pc += 5; + } + else if (mem_region_pos + 1 < (int)mem_map.region_cnt) { + mem_region_pos++; + pc = mem_map.regions[mem_region_pos].addr; + } + else { + mem_region_pos++; + pc = 0; + print_time(time_start, test_cnt); + return; + } + + while ((mem_map.regions[mem_region_pos].flags & MM_FLAG_X) == 0) { + if (mem_region_pos + 1 < (int)mem_map.region_cnt) { + mem_region_pos++; + pc = mem_map.regions[mem_region_pos].addr; + } + else { + mem_region_pos++; + pc = 0; + print_time(time_start, test_cnt); + return; + } + } + + set_regs_PC(elf_ctx, pc); + send_context_changed_event(elf_ctx); + + if (find_symbol_by_addr(elf_ctx, STACK_NO_FRAME, pc, &sym) < 0) { + if (get_error_code(errno) != ERR_SYM_NOT_FOUND) { + error("find_symbol_by_addr"); + } + } + else { + char * name = NULL; + char name_buf[0x1000]; + if (get_symbol_name(sym, &name) < 0) { + error("get_symbol_name"); + } + if (name != NULL) { + strcpy(name_buf, name); + if (find_symbol_by_name(elf_ctx, STACK_TOP_FRAME, 0, name_buf, &sym) < 0) { + if (get_error_code(errno) != ERR_SYM_NOT_FOUND) { + error("find_symbol_by_name"); + } + } + else { + if (get_symbol_name(sym, &name) < 0) { + error("get_symbol_name"); + } + if (strcmp(name_buf, name) != 0) { + errno = ERR_OTHER; + error("strcmp(name_buf, name)"); + } + } + } + } + + if (find_symbol_by_name(elf_ctx, STACK_TOP_FRAME, 0, "@ non existing name @", &sym) < 0) { + if (get_error_code(errno) != ERR_SYM_NOT_FOUND) { + error("find_symbol_by_name"); + } + } + + memset(&area, 0, sizeof(area)); + if (address_to_line(elf_ctx, pc, pc + 1, line_numbers_callback, &area) < 0) { + error("address_to_line"); + } + else if (area.start_line > 0) { + char elf_file_name[0x1000]; + strlcpy(elf_file_name, area.file, sizeof(elf_file_name)); + if (line_to_address(elf_ctx, elf_file_name, area.start_line, area.start_column, line_numbers_callback, &area) < 0) { + error("line_to_address"); + } + } + + if (enumerate_symbols(elf_ctx, STACK_TOP_FRAME, loc_var_func, NULL) < 0) { + error("enumerate_symbols"); + } + + lt_file = NULL; + lt_sec = NULL; + lt_addr = elf_map_to_link_time_address(elf_ctx, pc, <_file, <_sec); + assert(lt_file != NULL); + assert(pc == elf_map_to_run_time_address(elf_ctx, lt_file, lt_sec, lt_addr)); + if (set_trap(&trap)) { + get_dwarf_stack_frame_info(elf_ctx, lt_file, lt_sec, lt_addr); + clear_trap(&trap); + } + else { + error("get_dwarf_stack_frame_info"); + } + + test_cnt++; + if (loaded) { + struct timespec time_diff; + clock_gettime(CLOCK_REALTIME, &time_now); + time_diff.tv_sec = time_now.tv_sec - time_start.tv_sec; + if (time_now.tv_nsec < time_start.tv_nsec) { + time_diff.tv_sec--; + time_diff.tv_nsec = time_now.tv_nsec + 1000000000 - time_start.tv_nsec; + } + else { + time_diff.tv_nsec = time_now.tv_nsec - time_start.tv_nsec; + } + printf("load time: %ld.%06ld\n", (long)time_diff.tv_sec, time_diff.tv_nsec / 1000); + fflush(stdout); + time_start = time_now; + loaded = 0; + } + else if (test_cnt >= 100000) { + print_time(time_start, test_cnt); + clock_gettime(CLOCK_REALTIME, &time_start); + test_posted = 1; + post_event(test, NULL); + return; + } + } +} + +static void next_file(void) { + unsigned j; + ELF_File * f = NULL; + struct stat st; + + if (pass_cnt == files_cnt) exit(0); + elf_file_name = files[pass_cnt % files_cnt]; + + printf("File: %s\n", elf_file_name); + fflush(stdout); + if (stat(elf_file_name, &st) < 0) { + printf("Cannot stat ELF: %s\n", errno_to_str(errno)); + exit(1); + } + + clock_gettime(CLOCK_REALTIME, &time_start); + + f = elf_open(elf_file_name);; + if (f == NULL) { + printf("Cannot open ELF: %s\n", errno_to_str(errno)); + exit(1); + } + + if (elf_ctx == NULL) { + elf_ctx = create_context("test"); + elf_ctx->stopped = 1; + elf_ctx->pending_intercept = 1; + elf_ctx->mem = elf_ctx; + elf_ctx->big_endian = f->big_endian; + list_add_first(&elf_ctx->ctxl, &context_root); + elf_ctx->ref_count++; + } + + context_clear_memory_map(&mem_map); + for (j = 0; j < f->pheader_cnt; j++) { + MemoryRegion * r = NULL; + ELF_PHeader * p = f->pheaders + j; + if (p->type != PT_LOAD) continue; + if (mem_map.region_cnt >= mem_map.region_max) { + mem_map.region_max += 8; + mem_map.regions = (MemoryRegion *)loc_realloc(mem_map.regions, sizeof(MemoryRegion) * mem_map.region_max); + } + r = mem_map.regions + mem_map.region_cnt++; + memset(r, 0, sizeof(MemoryRegion)); + r->addr = p->address; + r->file_name = loc_strdup(elf_file_name); + r->file_offs = p->offset; + r->size = p->file_size; + r->flags = MM_FLAG_R | MM_FLAG_W; + if (p->flags & PF_X) r->flags |= MM_FLAG_X; + r->dev = st.st_dev; + r->ino = st.st_ino; + } + if (mem_map.region_cnt == 0) { + for (j = 0; j < f->section_cnt; j++) { + ELF_Section * sec = f->sections + j; + if (sec->size == 0) continue; + if (sec->name == NULL) continue; + if (strcmp(sec->name, ".text") == 0 || + strcmp(sec->name, ".data") == 0 || + strcmp(sec->name, ".bss") == 0) { + MemoryRegion * r = NULL; + if (mem_map.region_cnt >= mem_map.region_max) { + mem_map.region_max += 8; + mem_map.regions = (MemoryRegion *)loc_realloc(mem_map.regions, sizeof(MemoryRegion) * mem_map.region_max); + } + r = mem_map.regions + mem_map.region_cnt++; + memset(r, 0, sizeof(MemoryRegion)); + r->addr = sec->addr + 0x10000; + r->size = sec->size; + r->file_offs = sec->offset; + r->bss = strcmp(sec->name, ".bss") == 0; + r->dev = st.st_dev; + r->ino = st.st_ino; + r->file_name = loc_strdup(elf_file_name); + r->sect_name = loc_strdup(sec->name); + r->flags = MM_FLAG_R | MM_FLAG_W; + if (strcmp(sec->name, ".text") == 0) r->flags |= MM_FLAG_X; + } + } + } + if (mem_map.region_cnt == 0) { + printf("File has no program headers.\n"); + exit(1); + } + memory_map_event_module_loaded(elf_ctx); + mem_region_pos = -1; + + reg_size = 0; + memset(reg_defs, 0, sizeof(reg_defs)); + memset(reg_vals, 0, sizeof(reg_vals)); + for (j = 0; j < MAX_REGS - 1; j++) { + RegisterDefinition * r = reg_defs + j; + r->big_endian = f->big_endian; + r->dwarf_id = (int16_t)(j == 0 ? -1 : j - 1); + r->eh_frame_id = -1; + r->name = reg_names[j]; + snprintf(reg_names[j], sizeof(reg_names[j]), "R%d", j); + r->offset = reg_size; + r->size = f->elf64 ? 8 : 4; + if (j == 0) r->role = "PC"; + reg_size += r->size; + } + + pc = 0; + pass_cnt++; + + test_posted = 1; + post_event(test, NULL); +} + +static void test(void * args) { + assert(test_posted); + test_posted = 0; + if (elf_file_name == NULL || mem_region_pos >= (int)mem_map.region_cnt) { + next_file(); + } + else { + next_pc(); + } +} + +static void on_elf_file_closed(ELF_File * f) { + if (!test_posted) { + test_posted = 1; + post_event(test, NULL); + } +} + +void init_contexts_sys_dep(void) { + const char * dir_name = "files"; + DIR * dir = opendir(dir_name); + if (dir == NULL) { + printf("Cannot open '%s' directory\n", dir_name); + fflush(stdout); + exit(1); + } + for (;;) { + struct dirent * e = readdir(dir); + char path[FILE_PATH_SIZE]; + struct stat st; + if (e == NULL) break; + snprintf(path, sizeof(path), "%s/%s", dir_name, e->d_name); + if (stat(path, &st) == 0 && !S_ISDIR(st.st_mode)) { + if (files_cnt >= files_max) { + files_max += 8; + files = (char **)loc_realloc(files, files_max * sizeof(char *)); + } + files[files_cnt++] = loc_strdup(path); + } + } + closedir(dir); + elf_add_close_listener(on_elf_file_closed); + test_posted = 1; + post_event(test, NULL); +} diff --git a/tests/test-dwarf/tcf/backend/backend.h b/tests/test-dwarf/tcf/backend/backend.h new file mode 100644 index 00000000..f9aaa0b2 --- /dev/null +++ b/tests/test-dwarf/tcf/backend/backend.h @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2010, 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. + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ + +/* Fake debug context API implementation. It used for testing symbol services. */ + +#ifndef D_backend +#define D_backend + +#include <tcf/config.h> +#include <tcf/framework/channel.h> + +#define MAX_REGS 2000 + +struct RegisterData { + uint8_t data[MAX_REGS * 8]; + uint8_t mask[MAX_REGS * 8]; +}; + +#endif /* D_backend */ diff --git a/tests/test-dwarf/tcf/config.h b/tests/test-dwarf/tcf/config.h new file mode 100644 index 00000000..144cec5c --- /dev/null +++ b/tests/test-dwarf/tcf/config.h @@ -0,0 +1,98 @@ +/******************************************************************************* + * 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. + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ + +/* + * This file contains "define" statements that control agent configuration. + * SERVICE_* definitions control which service implementations are included into the agent. + */ + +#ifndef D_config +#define D_config + +#include <tcf/framework/mdep.h> + +#if !defined(SERVICE_Locator) +#define SERVICE_Locator 1 +#endif +#if !defined(SERVICE_Registers) +#define SERVICE_Registers 1 +#endif +#if !defined(SERVICE_Memory) +#define SERVICE_Memory 1 +#endif +#if !defined(SERVICE_LineNumbers) +#define SERVICE_LineNumbers 1 +#endif +#if !defined(SERVICE_Symbols) +#define SERVICE_Symbols 1 +#endif +#if !defined(SERVICE_Expressions) +#define SERVICE_Expressions 1 +#endif +#if !defined(SERVICE_MemoryMap) +#define SERVICE_MemoryMap 1 +#endif +#if !defined(SERVICE_StackTrace) +#define SERVICE_StackTrace 1 +#endif + +#if !defined(ENABLE_ZeroCopy) +#define ENABLE_ZeroCopy 1 +#endif + +#if !defined(ENABLE_Trace) +# define ENABLE_Trace 1 +#endif + +#if !defined(ENABLE_Discovery) +# define ENABLE_Discovery 0 +#endif + +#if !defined(ENABLE_ContextProxy) +# define ENABLE_ContextProxy 1 +#endif + +#if !defined(ENABLE_SymbolsProxy) +# define ENABLE_SymbolsProxy 0 +#endif + +#if !defined(ENABLE_LineNumbersProxy) +# define ENABLE_LineNumbersProxy 0 +#endif + +#if !defined(ENABLE_Symbols) +# define ENABLE_Symbols (ENABLE_SymbolsProxy || SERVICE_Symbols) +#endif + +#if !defined(ENABLE_LineNumbers) +# define ENABLE_LineNumbers (ENABLE_LineNumbersProxy || SERVICE_LineNumbers) +#endif + +#if !defined(ENABLE_DebugContext) +# define ENABLE_DebugContext 1 +#endif + +#if !defined(ENABLE_ELF) +# define ENABLE_ELF 1 +#endif + +#define ENABLE_SSL 0 +#define ENABLE_Unix_Domain 0 + +#if !defined(ENABLE_STREAM_MACROS) +#define ENABLE_STREAM_MACROS 1 +#endif + +#endif /* D_config */ diff --git a/tests/test-dwarf/tcf/machine/cpudefs-ext.h b/tests/test-dwarf/tcf/machine/cpudefs-ext.h new file mode 100644 index 00000000..18cb5704 --- /dev/null +++ b/tests/test-dwarf/tcf/machine/cpudefs-ext.h @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2007, 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. + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ + +#include <tcf/backend/backend.h> + +static RegisterDefinition * get_reg_by_dwarf_id(unsigned id) { + static RegisterDefinition ** map = NULL; + static unsigned map_length = 0; + + if (map == NULL) { + RegisterDefinition * r; + RegisterDefinition * regs_index = get_reg_definitions(NULL); + for (r = regs_index; r->name != NULL; r++) { + if (r->dwarf_id >= (int)map_length) map_length = r->dwarf_id + 1; + } + map = (RegisterDefinition **)loc_alloc_zero(sizeof(RegisterDefinition *) * map_length); + for (r = regs_index; r->name != NULL; r++) { + if (r->dwarf_id >= 0) map[r->dwarf_id] = r; + } + } + return id < map_length ? map[id] : NULL; +} + +static RegisterDefinition * get_reg_by_eh_frame_id(unsigned id) { + static RegisterDefinition ** map = NULL; + static unsigned map_length = 0; + + if (map == NULL) { + RegisterDefinition * r; + RegisterDefinition * regs_index = get_reg_definitions(NULL); + for (r = regs_index; r->name != NULL; r++) { + if (r->eh_frame_id >= (int)map_length) map_length = r->eh_frame_id + 1; + } + map = (RegisterDefinition **)loc_alloc_zero(sizeof(RegisterDefinition *) * map_length); + for (r = regs_index; r->name != NULL; r++) { + if (r->eh_frame_id >= 0) map[r->eh_frame_id] = r; + } + } + return id < map_length ? map[id] : NULL; +} + +RegisterDefinition * get_reg_by_id(Context * ctx, unsigned id, RegisterIdScope * scope) { + RegisterDefinition * def = NULL; + switch (scope->id_type) { + case REGNUM_DWARF: def = get_reg_by_dwarf_id(id); break; + case REGNUM_EH_FRAME: def = get_reg_by_eh_frame_id(id); break; + } + if (def == NULL) set_errno(ERR_OTHER, "Invalid register ID"); + return def; +} + +int read_reg_bytes(StackFrame * frame, RegisterDefinition * reg_def, unsigned offs, unsigned size, uint8_t * buf) { + if (reg_def != NULL && frame != NULL) { + if (frame->is_top_frame) { + return context_read_reg(frame->ctx, reg_def, offs, size, buf); + } + if (frame->regs != NULL) { + size_t i; + uint8_t * r_addr = (uint8_t *)&frame->regs->data + reg_def->offset; + uint8_t * m_addr = (uint8_t *)&frame->regs->mask + reg_def->offset; + for (i = 0; i < size; i++) { + if (m_addr[offs + i] != 0xff) { + errno = ERR_INV_CONTEXT; + return -1; + } + } + if (offs + size > reg_def->size) { + errno = ERR_INV_DATA_SIZE; + return -1; + } + memcpy(buf, r_addr + offs, size); + return 0; + } + } + errno = ERR_INV_CONTEXT; + return -1; +} + +int write_reg_bytes(StackFrame * frame, RegisterDefinition * reg_def, unsigned offs, unsigned size, uint8_t * buf) { + if (reg_def != NULL && frame != NULL) { + if (frame->is_top_frame) { + return context_write_reg(frame->ctx, reg_def, offs, size, buf); + } + if (frame->regs == NULL && context_has_state(frame->ctx)) { + frame->regs = (RegisterData *)loc_alloc_zero(sizeof(RegisterData)); + } + if (frame->regs != NULL) { + uint8_t * r_addr = (uint8_t *)&frame->regs->data + reg_def->offset; + uint8_t * m_addr = (uint8_t *)&frame->regs->mask + reg_def->offset; + + if (offs + size > reg_def->size) { + errno = ERR_INV_DATA_SIZE; + return -1; + } + memcpy(r_addr + offs, buf, size); + memset(m_addr + offs, 0xff, size); + return 0; + } + } + errno = ERR_INV_CONTEXT; + return -1; +} |