diff options
author | eutarass | 2009-11-12 00:40:13 +0000 |
---|---|---|
committer | eutarass | 2009-11-12 00:40:13 +0000 |
commit | 19550fa598e785d40b1e38c3299f0baa84e8bf42 (patch) | |
tree | 1e9633ba398df2734a380e3b325634aefbd1ef37 | |
parent | 28522ca4e290e13668d5cd6628410c2908d3aa16 (diff) | |
download | org.eclipse.tcf.agent-19550fa598e785d40b1e38c3299f0baa84e8bf42.tar.gz org.eclipse.tcf.agent-19550fa598e785d40b1e38c3299f0baa84e8bf42.tar.xz org.eclipse.tcf.agent-19550fa598e785d40b1e38c3299f0baa84e8bf42.zip |
TCF Agent:
1. CPU registers and stack frame basic handling is moved to a new separate module cpudefs.c
2. Architecture dependent CPU registers and stack frame definitions are moved into separate header files - cpudefs-mdep.h
3. Implemented stack unwinding using DWARF sections .debug_frame and .eh_frame
4. Changed year in copyright notices to 2009
TCF Debugger:
1. Fixed elements order in registers view.
2. Changed source level stepping logic to better support stepping over function epilogue.
75 files changed, 2276 insertions, 1564 deletions
diff --git a/agent.vcproj b/agent.vcproj index c140f697..256bd0ef 100644 --- a/agent.vcproj +++ b/agent.vcproj @@ -45,7 +45,7 @@ Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
- AdditionalIncludeDirectories=".,framework,services,system/Windows,main"
+ AdditionalIncludeDirectories=".,framework,services,system/Windows,machine/x86_64,main"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
StringPooling="true"
RuntimeLibrary="0"
@@ -134,7 +134,7 @@ <Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories=".,framework,services,system/Windows,main"
+ AdditionalIncludeDirectories=".,framework,services,system/Windows,machine/x86_64,main"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
RuntimeLibrary="1"
@@ -199,482 +199,530 @@ <References>
</References>
<Files>
- <File
- RelativePath=".\framework\asyncreq.c"
- >
- </File>
- <File
- RelativePath=".\framework\asyncreq.h"
- >
- </File>
- <File
- RelativePath=".\framework\base64.c"
- >
- </File>
- <File
- RelativePath=".\framework\base64.h"
- >
- </File>
- <File
- RelativePath=".\services\breakpoints.c"
- >
- </File>
- <File
- RelativePath=".\services\breakpoints.h"
- >
- </File>
- <File
- RelativePath=".\framework\channel.c"
- >
- </File>
- <File
- RelativePath=".\framework\channel.h"
- >
- </File>
- <File
- RelativePath=".\framework\channel_tcp.c"
+ <Filter
+ Name="framework"
>
- </File>
- <File
- RelativePath=".\framework\channel_tcp.h"
+ <File
+ RelativePath=".\framework\asyncreq.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\asyncreq.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\base64.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\base64.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\channel.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\channel.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\channel_tcp.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\channel_tcp.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\context.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\context.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\cpudefs.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\cpudefs.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\errors.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\errors.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\events.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\events.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\exceptions.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\exceptions.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\expressions.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\expressions.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\inputbuf.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\inputbuf.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\ip_ifc.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\ip_ifc.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\json.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\json.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\link.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\mdep.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\mdep.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\myalloc.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\myalloc.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\peer.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\peer.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\plugins.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\plugins.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\protocol.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\protocol.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\proxy.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\proxy.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\streams.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\streams.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\tcf.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\trace.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\trace.h"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\waitpid.c"
+ >
+ </File>
+ <File
+ RelativePath=".\framework\waitpid.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="services"
>
- </File>
- <File
- RelativePath=".\main\cmdline.c"
+ <File
+ RelativePath=".\services\breakpoints.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\breakpoints.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\diagnostics.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\diagnostics.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\discovery.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\discovery.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\discovery_udp.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\discovery_udp.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\dwarf.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\dwarfcache.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\dwarfcache.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\dwarfexpr.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\dwarfexpr.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\dwarfframe.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\dwarfframe.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\dwarfio.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\dwarfio.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\filesystem.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\filesystem.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\linenumbers.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\linenumbers_elf.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\linenumbers_win32.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\memorymap.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\memorymap.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\memoryservice.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\memoryservice.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\processes.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\processes.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\registers.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\registers.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\runctrl.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\runctrl.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\stacktrace.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\stacktrace.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\streamsservice.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\streamsservice.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\symbols.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\symbols.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\symbols_elf.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\symbols_win32.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\sysmon.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\sysmon.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services\tcf_elf.c"
+ >
+ </File>
+ <File
+ RelativePath=".\services\tcf_elf.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="main"
>
- </File>
- <File
- RelativePath=".\main\cmdline.h"
+ <File
+ RelativePath=".\main\cmdline.c"
+ >
+ </File>
+ <File
+ RelativePath=".\main\cmdline.h"
+ >
+ </File>
+ <File
+ RelativePath=".\main\main.c"
+ >
+ </File>
+ <File
+ RelativePath=".\main\main_client.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\main\main_log.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\main\main_lua.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\main\main_reg.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\main\main_va.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\main\test.c"
+ >
+ </File>
+ <File
+ RelativePath=".\main\test.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="system"
>
- </File>
+ <Filter
+ Name="Windows"
+ >
+ <File
+ RelativePath=".\system\Windows\windbgcache.c"
+ >
+ </File>
+ <File
+ RelativePath=".\system\Windows\windbgcache.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="machine"
+ >
+ <Filter
+ Name="x86_64"
+ >
+ <File
+ RelativePath=".\machine\x86_64\cpudefs-mdep.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
<File
RelativePath=".\config.h"
>
</File>
- <File
- RelativePath=".\framework\context.c"
- >
- </File>
- <File
- RelativePath=".\framework\context.h"
- >
- </File>
- <File
- RelativePath=".\services\diagnostics.c"
- >
- </File>
- <File
- RelativePath=".\services\diagnostics.h"
- >
- </File>
- <File
- RelativePath=".\services\discovery.c"
- >
- </File>
- <File
- RelativePath=".\services\discovery.h"
- >
- </File>
- <File
- RelativePath=".\services\discovery_udp.c"
- >
- </File>
- <File
- RelativePath=".\services\discovery_udp.h"
- >
- </File>
- <File
- RelativePath=".\services\dwarf.h"
- >
- </File>
- <File
- RelativePath=".\services\dwarfcache.c"
- >
- </File>
- <File
- RelativePath=".\services\dwarfcache.h"
- >
- </File>
- <File
- RelativePath=".\services\dwarfexpr.c"
- >
- </File>
- <File
- RelativePath=".\services\dwarfexpr.h"
- >
- </File>
- <File
- RelativePath=".\services\dwarfio.c"
- >
- </File>
- <File
- RelativePath=".\services\dwarfio.h"
- >
- </File>
- <File
- RelativePath=".\framework\errors.c"
- >
- </File>
- <File
- RelativePath=".\framework\errors.h"
- >
- </File>
- <File
- RelativePath=".\framework\events.c"
- >
- </File>
- <File
- RelativePath=".\framework\events.h"
- >
- </File>
- <File
- RelativePath=".\framework\exceptions.c"
- >
- </File>
- <File
- RelativePath=".\framework\exceptions.h"
- >
- </File>
- <File
- RelativePath=".\services\expressions.c"
- >
- </File>
- <File
- RelativePath=".\services\expressions.h"
- >
- </File>
- <File
- RelativePath=".\services\filesystem.c"
- >
- </File>
- <File
- RelativePath=".\services\filesystem.h"
- >
- </File>
- <File
- RelativePath=".\framework\inputbuf.c"
- >
- </File>
- <File
- RelativePath=".\framework\inputbuf.h"
- >
- </File>
- <File
- RelativePath=".\framework\ip_ifc.c"
- >
- </File>
- <File
- RelativePath=".\framework\ip_ifc.h"
- >
- </File>
- <File
- RelativePath=".\framework\json.c"
- >
- </File>
- <File
- RelativePath=".\framework\json.h"
- >
- </File>
- <File
- RelativePath=".\services\linenumbers.h"
- >
- </File>
- <File
- RelativePath=".\services\linenumbers_elf.c"
- >
- </File>
- <File
- RelativePath=".\services\linenumbers_win32.c"
- >
- </File>
- <File
- RelativePath=".\framework\link.h"
- >
- </File>
- <File
- RelativePath=".\main\main.c"
- >
- </File>
- <File
- RelativePath=".\main\main_client.c"
- >
- <FileConfiguration
- Name="Release|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath=".\main\main_log.c"
- >
- <FileConfiguration
- Name="Release|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath=".\main\main_lua.c"
- >
- <FileConfiguration
- Name="Release|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath=".\main\main_reg.c"
- >
- <FileConfiguration
- Name="Release|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath=".\main\main_va.c"
- >
- <FileConfiguration
- Name="Release|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath=".\framework\mdep.c"
- >
- </File>
- <File
- RelativePath=".\framework\mdep.h"
- >
- </File>
- <File
- RelativePath=".\services\memorymap.c"
- >
- </File>
- <File
- RelativePath=".\services\memorymap.h"
- >
- </File>
- <File
- RelativePath=".\services\memoryservice.c"
- >
- </File>
- <File
- RelativePath=".\services\memoryservice.h"
- >
- </File>
- <File
- RelativePath=".\framework\myalloc.c"
- >
- </File>
- <File
- RelativePath=".\framework\myalloc.h"
- >
- </File>
- <File
- RelativePath=".\framework\peer.c"
- >
- </File>
- <File
- RelativePath=".\framework\peer.h"
- >
- </File>
- <File
- RelativePath=".\framework\plugins.c"
- >
- </File>
- <File
- RelativePath=".\framework\plugins.h"
- >
- </File>
- <File
- RelativePath=".\services\processes.c"
- >
- </File>
- <File
- RelativePath=".\services\processes.h"
- >
- </File>
- <File
- RelativePath=".\framework\protocol.c"
- >
- </File>
- <File
- RelativePath=".\framework\protocol.h"
- >
- </File>
- <File
- RelativePath=".\framework\proxy.c"
- >
- </File>
- <File
- RelativePath=".\framework\proxy.h"
- >
- </File>
- <File
- RelativePath=".\services\registers.c"
- >
- </File>
- <File
- RelativePath=".\services\registers.h"
- >
- </File>
- <File
- RelativePath=".\services\runctrl.c"
- >
- </File>
- <File
- RelativePath=".\services\runctrl.h"
- >
- </File>
- <File
- RelativePath=".\services\stacktrace.c"
- >
- </File>
- <File
- RelativePath=".\services\stacktrace.h"
- >
- </File>
- <File
- RelativePath=".\framework\streams.c"
- >
- </File>
- <File
- RelativePath=".\framework\streams.h"
- >
- </File>
- <File
- RelativePath=".\services\streamsservice.c"
- >
- </File>
- <File
- RelativePath=".\services\streamsservice.h"
- >
- </File>
- <File
- RelativePath=".\services\symbols.c"
- >
- </File>
- <File
- RelativePath=".\services\symbols.h"
- >
- </File>
- <File
- RelativePath=".\services\symbols_elf.c"
- >
- </File>
- <File
- RelativePath=".\services\symbols_win32.c"
- >
- </File>
- <File
- RelativePath=".\services\sysmon.c"
- >
- </File>
- <File
- RelativePath=".\services\sysmon.h"
- >
- </File>
- <File
- RelativePath=".\framework\tcf.h"
- >
- </File>
- <File
- RelativePath=".\services\tcf_elf.c"
- >
- </File>
- <File
- RelativePath=".\services\tcf_elf.h"
- >
- </File>
- <File
- RelativePath=".\main\test.c"
- >
- </File>
- <File
- RelativePath=".\main\test.h"
- >
- </File>
- <File
- RelativePath=".\framework\trace.c"
- >
- </File>
- <File
- RelativePath=".\framework\trace.h"
- >
- </File>
- <File
- RelativePath=".\framework\waitpid.c"
- >
- </File>
- <File
- RelativePath=".\framework\waitpid.h"
- >
- </File>
- <File
- RelativePath=".\system\Windows\windbgcache.c"
- >
- </File>
- <File
- RelativePath=".\system\Windows\windbgcache.h"
- >
- </File>
</Files>
<Globals>
</Globals>
diff --git a/framework/context.c b/framework/context.c index fdc98f29..313de06e 100644 --- a/framework/context.c +++ b/framework/context.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. @@ -990,8 +990,6 @@ int context_single_step(Context * ctx) { #if defined(__i386__) || defined(__x86_64__) ctx->regs.EFlags |= 0x100; ctx->regs_dirty = 1; -#else -# error "context_single_step() is not implemented for CPU other then X86" #endif ctx->pending_step = 1; return win32_resume(ctx); diff --git a/framework/context.h b/framework/context.h index 24777462..e570f430 100644 --- a/framework/context.h +++ b/framework/context.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. @@ -20,60 +20,9 @@ #define D_context #include "config.h" +#include "cpudefs.h" #include "link.h" -typedef uintptr_t ContextAddress; /* Type to represent byted address inside context memory */ - -#if ENABLE_DebugContext -#if defined(WIN32) || defined(__CYGWIN__) - -typedef CONTEXT REG_SET; -#define get_regs_SP(x) ((x).Esp) -#define get_regs_BP(x) ((x).Ebp) -#define get_regs_PC(x) ((x).Eip) -#define set_regs_PC(x,y) (x).Eip = (y) - -#elif defined(_WRS_KERNEL) - -#include <regs.h> - -#elif defined(__APPLE__) - -#include <mach/thread_status.h> -typedef x86_thread_state32_t REG_SET; -#define get_regs_SP(x) ((x).__esp) -#define get_regs_BP(x) ((x).__ebp) -#define get_regs_PC(x) ((x).__eip) -#define set_regs_PC(x,y) (x).__eip = (unsigned long)(y) - -#elif defined(__FreeBSD__) || defined(__NetBSD__) - -#include <machine/reg.h> -typedef struct reg REG_SET; -#define get_regs_SP(x) ((x).r_esp) -#define get_regs_BP(x) ((x).r_ebp) -#define get_regs_PC(x) ((x).r_eip) -#define set_regs_PC(x,y) (x).r_eip = (unsigned int)(y) - -#else - -#include <sys/user.h> -typedef struct user_regs_struct REG_SET; -#if __WORDSIZE == 64 -# define get_regs_SP(x) ((x).rsp) -# define get_regs_BP(x) ((x).rbp) -# define get_regs_PC(x) ((x).rip) -# define set_regs_PC(x,y) (x).rip = (unsigned long)(y) -#else -# define get_regs_SP(x) ((x).esp) -# define get_regs_BP(x) ((x).ebp) -# define get_regs_PC(x) ((x).eip) -# define set_regs_PC(x,y) (x).eip = (unsigned long)(y) -#endif - -#endif -#endif /* ENABLE_DebugContext */ - extern LINK context_root; #define ctxl2ctxp(A) ((Context *)((char *)(A) - offsetof(Context, ctxl))) diff --git a/framework/cpudefs.c b/framework/cpudefs.c new file mode 100644 index 00000000..06957434 --- /dev/null +++ b/framework/cpudefs.c @@ -0,0 +1,193 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 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 + *******************************************************************************/ + +/* + * This module contains definitions of target CPU registers. + */ + +#include "config.h" + +#if ENABLE_DebugContext + +#include <stddef.h> +#include <stdio.h> +#include <assert.h> +#include "cpudefs.h" +#include "errors.h" +#include "context.h" +#include "myalloc.h" +#include "breakpoints.h" +#include "symbols.h" + +#if defined(_WRS_KERNEL) + +/* VxWork has its own register definitions and stack crawling function */ + +static RegisterDefinition * regs_index = NULL; + +RegisterDefinition * get_reg_definitions(void) { + if (regs_index == NULL) { + int cnt = 0; + REG_INDEX * r; + for (r = taskRegName; r->regName; r++) cnt++; + regs_index = loc_alloc_zero(sizeof(RegisterDefinition) * (cnt + 1)); + cnt = 0; + for (r = taskRegName; r->regName; r++) { + regs_index[cnt].name = r->regName; + regs_index[cnt].offset = r->regOff; +#if defined(_WRS_REG_INDEX_REGWIDTH) || (CPU_FAMILY == COLDFIRE) + regs_index[cnt].size = regWidth; +#else + regs_index[cnt].size = 4; +#endif + regs_index[cnt].dwarf_id = -1; + regs_index[cnt].eh_frame_id = -1; + cnt++; + } + } + return regs_index; +} + +RegisterDefinition * get_PC_definition(void) { + static RegisterDefinition * reg_def = NULL; + if (reg_def == NULL) { + RegisterDefinition * r; + for (r = get_reg_definitions(); r->name != NULL; r++) { + if (r->offset == offsetof(REG_SET, reg_pc)) { + reg_def = r; + break; + } + } + } + return reg_def; +} + + +ContextAddress get_regs_PC_func(REG_SET * regs) { + return (ContextAddress)regs->reg_pc; +} + +void set_regs_PC_func(REG_SET * regs, ContextAddress pc) { + regs->reg_pc = (void *)pc; +} + +#else /* _WRS_KERNEL */ + +#include "cpudefs-mdep.h" + +RegisterDefinition * get_reg_definitions(void) { + return regs_index; +} + +#endif /* _WRS_KERNEL */ + +RegisterDefinition * get_reg_by_dwarf_id(int id) { +#if !ENABLE_ELF + return NULL; +#else + static RegisterDefinition ** map = NULL; + static int map_length = 0; + + if (map == NULL) { + RegisterDefinition * r; + for (r = get_reg_definitions(); r->name != NULL; r++) { + if (r->dwarf_id >= map_length) map_length = r->dwarf_id + 1; + } + map = loc_alloc_zero(sizeof(RegisterDefinition *) * map_length); + for (r = get_reg_definitions(); r->name != NULL; r++) { + if (r->dwarf_id >= 0) map[r->dwarf_id] = r; + } + } + return id >= 0 && id < map_length ? map[id] : NULL; +#endif +} + +RegisterDefinition * get_reg_by_eh_frame_id(int id) { +#if !ENABLE_ELF + return NULL; +#else + static RegisterDefinition ** map = NULL; + static int map_length = 0; + + if (map == NULL) { + RegisterDefinition * r; + for (r = get_reg_definitions(); r->name != NULL; r++) { + if (r->eh_frame_id >= map_length) map_length = r->eh_frame_id + 1; + } + map = loc_alloc_zero(sizeof(RegisterDefinition *) * map_length); + for (r = get_reg_definitions(); r->name != NULL; r++) { + if (r->eh_frame_id >= 0) map[r->eh_frame_id] = r; + } + } + return id >= 0 && id < map_length ? map[id] : NULL; +#endif +} + +int read_reg_value(RegisterDefinition * reg_def, StackFrame * frame, uint64_t * value) { + if (reg_def != NULL) { + size_t size = reg_def->size; + if (size <= 8) { + static uint8_t ones[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + uint8_t * r_addr = (uint8_t *)&frame->regs + reg_def->offset; + uint8_t * m_addr = (uint8_t *)&frame->mask + reg_def->offset; + if (memcmp(m_addr, ones, size) == 0) { + if (value != NULL) { + switch (size) { + case 1: *value = *(uint8_t *)r_addr; break; + case 2: *value = *(uint16_t *)r_addr; break; + case 4: *value = *(uint32_t *)r_addr; break; + case 8: *value = *(uint64_t *)r_addr; break; + } + } + return 0; + } + } + else { + errno = ERR_INV_DATA_SIZE; + return -1; + } + } + errno = ERR_INV_CONTEXT; + return -1; +} + +int write_reg_value(RegisterDefinition * reg_def, StackFrame * frame, uint64_t value) { + if (reg_def != NULL) { + size_t size = reg_def->size; + if (size <= 8) { + uint8_t * r_addr = (uint8_t *)&frame->regs + reg_def->offset; + uint8_t * m_addr = (uint8_t *)&frame->mask + reg_def->offset; + memset(m_addr, 0xff, size); + switch (size) { + case 1: *(uint8_t *)r_addr = (uint8_t)value; break; + case 2: *(uint16_t *)r_addr = (uint16_t)value; break; + case 4: *(uint32_t *)r_addr = (uint32_t)value; break; + case 8: *(uint64_t *)r_addr = (uint64_t)value; break; + } + return 0; + } + else { + errno = ERR_INV_DATA_SIZE; + return -1; + } + } + errno = ERR_INV_CONTEXT; + return -1; +} + +size_t get_break_size(void) { + return sizeof(BREAK_INST); +} + +#endif /* ENABLE_DebugContext */ diff --git a/framework/cpudefs.h b/framework/cpudefs.h new file mode 100644 index 00000000..a45155f2 --- /dev/null +++ b/framework/cpudefs.h @@ -0,0 +1,109 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 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 + *******************************************************************************/ + +/* + * This module contains definitions of target CPU registers. + */ + +#ifndef D_cpudefs +#define D_cpudefs + +#include "config.h" + +typedef uintptr_t ContextAddress; /* Type to represent byte address inside context memory */ + +#if ENABLE_DebugContext + +#if defined(WIN32) || defined(__CYGWIN__) + typedef CONTEXT REG_SET; +#elif defined(_WRS_KERNEL) +# include <regs.h> +#elif defined(__APPLE__) +# include <mach/thread_status.h> + typedef x86_thread_state32_t REG_SET; +#elif defined(__FreeBSD__) || defined(__NetBSD__) +# include <machine/reg.h> + typedef struct reg REG_SET; +#else +# include <sys/user.h> + typedef struct user_regs_struct REG_SET; +#endif + +typedef struct RegisterDefinition { + char * name; /* pointer to register name */ + int offset; /* offset to entry in REG_SET */ + int size; /* register size in bytes */ + int dwarf_id; /* ID of the register in DWARF sections */ + int eh_frame_id; /* ID of the register in .eh_frame section */ + int traceable; /* register value can be traced using .eh_frame of .debug_frame */ +} RegisterDefinition; + +typedef struct StackFrame { + int is_top_frame; + ContextAddress fp; /* frame address */ + REG_SET regs; /* registers */ + REG_SET mask; /* registers valid bits mask */ +} StackFrame; + +/* Return array of CPU regiter definitions. LAst item in the array has name == NULL */ +extern RegisterDefinition * get_reg_definitions(void); + +/* Search register definition for given DWARF register ID, return NULL if not found */ +extern RegisterDefinition * get_reg_by_dwarf_id(int id); + +/* Search register definition for given .eh_frame section register ID, return NULL if not found */ +extern RegisterDefinition * get_reg_by_eh_frame_id(int id); + +/* Return register definition of instruction pointer */ +extern RegisterDefinition * get_PC_definition(void); + +/* Read register value from stack frame data, return 0 on success, return -1 and set errno if register is not available */ +extern int read_reg_value(RegisterDefinition * reg_def, StackFrame * frame, uint64_t * value); + +/* Write register value into stack frame data, return 0 on success, return -1 and set errno if register is not available */ +extern int write_reg_value(RegisterDefinition * reg_def, StackFrame * frame, uint64_t value); + +/* Get instruction pointer (PC) value */ +#define get_regs_PC(x) get_regs_PC_func(&(x)) + +/* Set instruction pointer (PC) value */ +#define set_regs_PC(x,y) set_regs_PC_func(&(x), (ContextAddress)(y)) + +extern ContextAddress get_regs_PC_func(REG_SET * regs); +extern void set_regs_PC_func(REG_SET * regs, ContextAddress pc); + +#if !defined(_WRS_KERNEL) +extern unsigned char BREAK_INST[]; /* breakpoint instruction */ +#define BREAK_SIZE get_break_size() /* breakpoint instruction size */ +extern size_t get_break_size(void); +#endif + +struct Context; + +/* + * Retrieve stack frame information by examining stack data in memory. + * + * "frame" is current frame info, it should have frame->regs and frame->mask filled with + * proper values before this function is called. + * + * "down" is next frame - moving from stack top to the bottom. + * + * The function uses register values in current frame to calculate frame address "frame->fp", + * and calculate register values in the next frame. + */ +extern int crawl_stack_frame(struct Context * ctx, StackFrame * frame, StackFrame * down); + +#endif /* ENABLE_DebugContext */ + +#endif /* D_cpudefs */ diff --git a/framework/errors.c b/framework/errors.c index b4ec5b87..4a80c8a4 100644 --- a/framework/errors.c +++ b/framework/errors.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. @@ -27,7 +27,7 @@ #define ERR_SYSTEM (ERR_EXCEPTION + 1) #define ERR_GAI (ERR_EXCEPTION + 2) -static char * exception_msg; +static char exception_msg[256]; static int exception_no; static int errno_gai; @@ -141,7 +141,7 @@ const char * errno_to_str(int err) { case ERR_INV_TRANSPORT: return "Invalid transport name"; case ERR_EXCEPTION: - snprintf(buf, sizeof(buf), "%s: %s", exception_msg, errno_to_str(exception_no)); + snprintf(buf, sizeof(buf), "%s: %s", errno_to_str(exception_no), exception_msg); return buf; #ifdef WIN32 case ERR_SYSTEM: @@ -154,16 +154,18 @@ const char * errno_to_str(int err) { } } -void set_exception_errno(int no, char * msg) { +int set_exception_errno(int no, char * msg) { assert(is_dispatch_thread()); if (msg == NULL) { errno = no; } else { errno = ERR_EXCEPTION; - exception_no = no; - exception_msg = msg; + if (no != ERR_EXCEPTION) exception_no = no; + strncpy(exception_msg, msg, sizeof(exception_msg) - 1); + exception_msg[sizeof(exception_msg) - 1] = 0; } + return errno; } int get_exception_errno(int no) { diff --git a/framework/errors.h b/framework/errors.h index 9bf49041..6b6e23db 100644 --- a/framework/errors.h +++ b/framework/errors.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. @@ -57,7 +57,7 @@ */ extern const char * errno_to_str(int no); -extern void set_exception_errno(int no, char * msg); +extern int set_exception_errno(int no, char * msg); extern int get_exception_errno(int no); extern int set_gai_errno(int gai_error_code); diff --git a/framework/exceptions.c b/framework/exceptions.c index 0175a1eb..67a712fd 100644 --- a/framework/exceptions.c +++ b/framework/exceptions.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. @@ -69,7 +69,7 @@ void exception(int error) { error, errno_to_str(error)); exit(error); } - set_exception_errno(error, NULL); + error = set_exception_errno(error, NULL); longjmp(chain->env, error); } @@ -83,7 +83,7 @@ void str_exception(int error, char * msg) { } strncpy(chain->msg, msg, sizeof(chain->msg) - 1); chain->msg[sizeof(chain->msg) - 1] = 0; - set_exception_errno(error, msg); + error = set_exception_errno(error, msg); longjmp(chain->env, error); } diff --git a/framework/exceptions.h b/framework/exceptions.h index 240f4929..c7b10835 100644 --- a/framework/exceptions.h +++ b/framework/exceptions.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/framework/ip_ifc.c b/framework/ip_ifc.c index 9eb9adf0..b96be8d7 100644 --- a/framework/ip_ifc.c +++ b/framework/ip_ifc.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/framework/ip_ifc.h b/framework/ip_ifc.h index 8d25583f..285e2e54 100644 --- a/framework/ip_ifc.h +++ b/framework/ip_ifc.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/framework/json.c b/framework/json.c index c16abd5b..29489622 100644 --- a/framework/json.c +++ b/framework/json.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/framework/json.h b/framework/json.h index 90501dbe..da00da73 100644 --- a/framework/json.h +++ b/framework/json.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/framework/mdep.c b/framework/mdep.c index 06c5e827..7dd70362 100644 --- a/framework/mdep.c +++ b/framework/mdep.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. @@ -720,8 +720,6 @@ ssize_t pwrite(int fd, const void * buf, size_t size, off_t offset) { #include <shlobj.h> -unsigned char BREAK_INST[] = { 0xcc }; - char * get_os_name(void) { static char str[256]; OSVERSIONINFOEX info; @@ -837,16 +835,6 @@ void ini_mdep(void) { # include <asm/unistd.h> #endif -#if defined(__i386__) || defined(__x86_64__) -unsigned char BREAK_INST[] = { 0xcc }; -#else -#error "Unknown CPU" -#endif - -size_t get_break_size(void) { - return sizeof(BREAK_INST); -} - #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) int clock_gettime(clockid_t clock_id, struct timespec * tp) { struct timeval tv; diff --git a/framework/mdep.h b/framework/mdep.h index 8d79b838..dd4d4fe1 100644 --- a/framework/mdep.h +++ b/framework/mdep.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. @@ -70,9 +70,6 @@ typedef int ssize_t; typedef int socklen_t; -extern unsigned char BREAK_INST[]; /* breakpoint instruction */ -#define BREAK_SIZE 1 /* breakpoint instruction size */ - #if defined(__CYGWIN__) #ifndef _LARGEFILE_SOURCE @@ -291,9 +288,6 @@ extern char * canonicalize_file_name(const char * path); #define environ taskIdCurrent->ppEnviron -#define get_regs_PC(x) (*(int *)((int)&(x) + PC_OFFSET)) -#define set_regs_PC(x,y) *(int *)((int)&(x) + PC_OFFSET) = (int)(y) - #define closesocket close typedef unsigned long uintptr_t; @@ -378,10 +372,6 @@ extern int tkill(pid_t pid, int signal); #define closesocket close -extern unsigned char BREAK_INST[]; /* breakpoint instruction */ -#define BREAK_SIZE get_break_size() /* breakpoint instruction size */ -extern size_t get_break_size(void); - #endif extern pthread_attr_t pthread_create_attr; diff --git a/framework/myalloc.c b/framework/myalloc.c index a67a2118..960130b3 100644 --- a/framework/myalloc.c +++ b/framework/myalloc.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/framework/myalloc.h b/framework/myalloc.h index 33f28157..43d1d217 100644 --- a/framework/myalloc.h +++ b/framework/myalloc.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/framework/peer.c b/framework/peer.c index f5ea35b0..9d308c22 100644 --- a/framework/peer.c +++ b/framework/peer.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/framework/peer.h b/framework/peer.h index 25a6c5f9..4f4c7a8d 100644 --- a/framework/peer.h +++ b/framework/peer.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/framework/protocol.c b/framework/protocol.c index bbd6a62b..5659fea3 100644 --- a/framework/protocol.c +++ b/framework/protocol.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/framework/protocol.h b/framework/protocol.h index 0962f588..eb80bbcf 100644 --- a/framework/protocol.h +++ b/framework/protocol.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/framework/proxy.h b/framework/proxy.h index d4e60cdf..3a35c7a2 100644 --- a/framework/proxy.h +++ b/framework/proxy.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/framework/streams.c b/framework/streams.c index 116c4317..acc5986f 100644 --- a/framework/streams.c +++ b/framework/streams.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/framework/streams.h b/framework/streams.h index a97dfbb3..f8ba09dc 100644 --- a/framework/streams.h +++ b/framework/streams.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/framework/tcf.h b/framework/tcf.h index 7047084b..522714f0 100644 --- a/framework/tcf.h +++ b/framework/tcf.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/framework/trace.c b/framework/trace.c index 81963225..abc15012 100644 --- a/framework/trace.c +++ b/framework/trace.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/framework/trace.h b/framework/trace.h index 59e20d00..e0556aba 100644 --- a/framework/trace.h +++ b/framework/trace.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/machine/i386/cpudefs-mdep.h b/machine/i386/cpudefs-mdep.h new file mode 100644 index 00000000..1636f8de --- /dev/null +++ b/machine/i386/cpudefs-mdep.h @@ -0,0 +1,2 @@ +#include "machine/x86_64/cpudefs-mdep.h" + diff --git a/machine/i686/cpudefs-mdep.h b/machine/i686/cpudefs-mdep.h new file mode 100644 index 00000000..ebebb103 --- /dev/null +++ b/machine/i686/cpudefs-mdep.h @@ -0,0 +1 @@ +#include "machine/x86_64/cpudefs-mdep.h" diff --git a/machine/x86_64/cpudefs-mdep.h b/machine/x86_64/cpudefs-mdep.h new file mode 100644 index 00000000..99277f5e --- /dev/null +++ b/machine/x86_64/cpudefs-mdep.h @@ -0,0 +1,328 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 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 + *******************************************************************************/ + +/* + * This module provides CPU specific definitions for X86. + */ + +#if defined(__i386__) || defined(__x86_64__) + +#define REG_OFFSET(name) offsetof(REG_SET, name) + +RegisterDefinition regs_index[] = { +#if defined(WIN32) && defined(__i386__) + { "eax", REG_OFFSET(Eax), 4, 0, 0, 0}, + { "ecx", REG_OFFSET(Ecx), 4, 1, 1, 0}, + { "edx", REG_OFFSET(Edx), 4, 2, 2, 0}, + { "ebx", REG_OFFSET(Ebx), 4, 3, 3, 0}, + { "esp", REG_OFFSET(Esp), 4, 4, 4, 1}, + { "ebp", REG_OFFSET(Ebp), 4, 5, 5, 1}, + { "esi", REG_OFFSET(Esi), 4, 6, 6, 0}, + { "edi", REG_OFFSET(Edi), 4, 7, 7, 0}, + { "eip", REG_OFFSET(Eip), 4, 8, 8, 1}, + { "eflags", REG_OFFSET(EFlags), 4, 9, 9, 0}, + { "cs", REG_OFFSET(SegCs), 4, -1, -1, 0}, + { "ss", REG_OFFSET(SegSs), 4, -1, -1, 0}, +#elif defined(__APPLE__) && defined(__i386__) + { "eax", REG_OFFSET(__eax), 4, 0, 0, 0}, + { "ecx", REG_OFFSET(__ecx), 4, 1, 1, 0}, + { "edx", REG_OFFSET(__edx), 4, 2, 2, 0}, + { "ebx", REG_OFFSET(__ebx), 4, 3, 3, 0}, + { "esp", REG_OFFSET(__esp), 4, 4, 4, 1}, + { "ebp", REG_OFFSET(__ebp), 4, 5, 5, 1}, + { "esi", REG_OFFSET(__esi), 4, 6, 6, 0}, + { "edi", REG_OFFSET(__edi), 4, 7, 7, 0}, + { "eip", REG_OFFSET(__eip), 4, 8, 8, 1}, + { "eflags", REG_OFFSET(__eflags), 4, 9, 9, 0}, +#elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(__i386__) + { "eax", REG_OFFSET(r_eax), 4, 0, 0, 0}, + { "ecx", REG_OFFSET(r_ecx), 4, 1, 1, 0}, + { "edx", REG_OFFSET(r_edx), 4, 2, 2, 0}, + { "ebx", REG_OFFSET(r_ebx), 4, 3, 3, 0}, + { "esp", REG_OFFSET(r_esp), 4, 4, 4, 1}, + { "ebp", REG_OFFSET(r_ebp), 4, 5, 5, 1}, + { "esi", REG_OFFSET(r_esi), 4, 6, 6, 0}, + { "edi", REG_OFFSET(r_edi), 4, 7, 7, 0}, + { "eip", REG_OFFSET(r_eip), 4, 8, 8, 1}, + { "eflags", REG_OFFSET(r_eflags), 4, 9, 9, 0}, +#elif defined(__x86_64__) + { "rax", REG_OFFSET(rax), 8, 0, 0, 0}, + { "rdx", REG_OFFSET(rdx), 8, 1, 1, 0}, + { "rcx", REG_OFFSET(rcx), 8, 2, 2, 0}, + { "rbx", REG_OFFSET(rbx), 8, 3, 3, 0}, + { "rsi", REG_OFFSET(rsi), 8, 4, 4, 0}, + { "rdi", REG_OFFSET(rdi), 8, 5, 5, 0}, + { "rbp", REG_OFFSET(rbp), 8, 6, 6, 1}, + { "rsp", REG_OFFSET(rsp), 8, 7, 7, 1}, + { "r8", REG_OFFSET(r8), 8, 8, 8, 0}, + { "r9", REG_OFFSET(r9), 8, 9, 9, 0}, + { "r10", REG_OFFSET(r10), 8, 10, 10, 0}, + { "r11", REG_OFFSET(r11), 8, 11, 11, 0}, + { "r12", REG_OFFSET(r12), 8, 12, 12, 0}, + { "r13", REG_OFFSET(r13), 8, 13, 13, 0}, + { "r14", REG_OFFSET(r14), 8, 14, 14, 0}, + { "r15", REG_OFFSET(r15), 8, 15, 15, 0}, + { "rip", REG_OFFSET(rip), 8, -1, -1, 1}, + { "eflags", REG_OFFSET(eflags), 4, 49, -1, 0}, + { "es", REG_OFFSET(es), 4, 50, -1, 0}, + { "cs", REG_OFFSET(cs), 4, 51, -1, 0}, + { "ss", REG_OFFSET(ss), 4, 52, -1, 0}, + { "ds", REG_OFFSET(ds), 4, 53, -1, 0}, + { "fs", REG_OFFSET(fs), 4, 54, -1, 0}, + { "gs", REG_OFFSET(gs), 4, 55, -1, 0}, + { "fs_base", REG_OFFSET(fs_base), 4, 58, -1, 0}, + { "gs_base", REG_OFFSET(gs_base), 4, 59, -1, 0}, +#elif defined(__i386__) + { "eax", REG_OFFSET(eax), 4, 0, 0, 0}, + { "ecx", REG_OFFSET(ecx), 4, 1, 1, 0}, + { "edx", REG_OFFSET(edx), 4, 2, 2, 0}, + { "ebx", REG_OFFSET(ebx), 4, 3, 3, 0}, + { "esp", REG_OFFSET(esp), 4, 4, 4, 1}, + { "ebp", REG_OFFSET(ebp), 4, 5, 5, 1}, + { "esi", REG_OFFSET(esi), 4, 6, 6, 0}, + { "edi", REG_OFFSET(edi), 4, 7, 7, 0}, + { "eip", REG_OFFSET(eip), 4, 8, 8, 1}, + { "eflags", REG_OFFSET(eflags), 4, 9, 9, 0}, +#else +# error "Unknown CPU" +#endif + { NULL, 0, 0, 0, 0, 0}, +}; + +static int read_mem(Context * ctx, ContextAddress address, void * buf, size_t size) { + if (context_read_mem(ctx, address, buf, size) < 0) return -1; + check_breakpoints_on_memory_read(ctx, address, buf, size); + return 0; +} + +#if defined(WIN32) || defined(__CYGWIN__) +# define REG_SP Esp +# define REG_BP Ebp +# define REG_IP Eip +#elif defined(__APPLE__) +# define REG_SP __esp +# define REG_BP __ebp +# define REG_IP __eip +#elif defined(__FreeBSD__) || defined(__NetBSD__) +# define REG_SP r_esp +# define REG_BP r_ebp +# define REG_IP r_eip +#elif defined(__x86_64__) +# define REG_SP rsp +# define REG_BP rbp +# define REG_IP rip +#else +# define REG_SP esp +# define REG_BP ebp +# define REG_IP eip +#endif + +#define JMPD08 0xeb +#define JMPD32 0xe9 +#define GRP5 0xff +#define JMPN 0x25 +#define PUSH_EBP 0x55 +#define MOV_ESP00 0x89 +#define MOV_ESP01 0xe5 +#define MOV_ESP10 0x8b +#define MOV_ESP11 0xec +#define ENTER 0xc8 +#define RET 0xc3 +#define RETADD 0xc2 +#define REXW 0x48 + +/* + * trace_jump - resolve any JMP instructions to final destination + * + * This routine returns a pointer to the next non-JMP instruction to be + * executed if the PC were at the specified <adrs>. That is, if the instruction + * at <adrs> is not a JMP, then <adrs> is returned. Otherwise, if the + * instruction at <adrs> is a JMP, then the destination of the JMP is + * computed, which then becomes the new <adrs> which is tested as before. + * Thus we will eventually return the address of the first non-JMP instruction + * to be executed. + * + * The need for this arises because compilers may put JMPs to instructions + * that we are interested in, instead of the instruction itself. For example, + * optimizers may replace a stack pop with a JMP to a stack pop. Or in very + * UNoptimized code, the first instruction of a subroutine may be a JMP to + * a PUSH %EBP MOV %ESP %EBP, instead of a PUSH %EBP MOV %ESP %EBP (compiler + * may omit routine "post-amble" at end of parsing the routine!). We call + * this routine anytime we are looking for a specific kind of instruction, + * to help handle such cases. + * + * RETURNS: The address that a chain of branches points to. + */ +static ContextAddress trace_jump(Context * ctx, ContextAddress addr) { + int cnt = 0; + /* while instruction is a JMP, get destination adrs */ + while (cnt < 100) { + unsigned char instr; /* instruction opcode at <addr> */ + ContextAddress dest; /* Jump destination address */ + if (read_mem(ctx, addr, &instr, 1) < 0) break; + + /* If instruction is a JMP, get destination adrs */ + if (instr == JMPD08) { + signed char disp08; + if (read_mem(ctx, addr + 1, &disp08, 1) < 0) break; + dest = addr + 2 + disp08; + } + else if (instr == JMPD32) { + int disp32; + assert(sizeof(disp32) == 4); + if (read_mem(ctx, addr + 1, &disp32, 4) < 0) break; + dest = addr + 5 + disp32; + } + else if (instr == GRP5) { + ContextAddress ptr; + if (read_mem(ctx, addr + 1, &instr, 1) < 0) break; + if (instr != JMPN) break; + if (read_mem(ctx, addr + 2, &ptr, sizeof(ptr)) < 0) break; + if (read_mem(ctx, ptr, &dest, sizeof(dest)) < 0) break; + } + else { + break; + } + if (dest == addr) break; + addr = dest; + cnt++; + } + return addr; +} + +static int func_entry(unsigned char * code) { + if (*code != PUSH_EBP) return 0; + code++; + if (*code == REXW) code++; + if (code[0] == MOV_ESP00 && code[1] == MOV_ESP01) return 1; + if (code[0] == MOV_ESP10 && code[1] == MOV_ESP11) return 1; + return 0; +} + +int crawl_stack_frame(Context * ctx, StackFrame * frame, StackFrame * down) { + ContextAddress reg_ip = frame->regs.REG_IP; + ContextAddress reg_sp = frame->regs.REG_SP; + ContextAddress reg_bp = frame->regs.REG_BP; + + ContextAddress dwn_ip = 0; + ContextAddress dwn_sp = 0; + ContextAddress dwn_bp = 0; + + if (frame->mask.REG_IP != ~(ContextAddress)0) return 0; + if (frame->mask.REG_SP != ~(ContextAddress)0) return 0; + if (frame->mask.REG_BP != ~(ContextAddress)0) return 0; + + if (frame->is_top_frame) { + /* Top frame */ + ContextAddress addr = trace_jump(ctx, reg_ip); + ContextAddress plt = is_plt_section(ctx, addr); + + /* + * we don't have a stack frame in a few restricted but useful cases: + * 1) we are at a PUSH %EBP MOV %ESP %EBP or RET or ENTER instruction, + * 2) we are the first instruction of a subroutine (this may NOT be + * a PUSH %EBP MOV %ESP %EBP instruction with some compilers) + * 3) we are inside PLT entry + */ + if (plt) { + /* TODO: support for large code model PLT */ + if (addr - plt == 0) { + dwn_sp = reg_sp + sizeof(ContextAddress) * 2; + } + else if (addr - plt < 16) { + dwn_sp = reg_sp + sizeof(ContextAddress) * 3; + } + else if ((addr - plt - 16) % 16 < 11) { + dwn_sp = reg_sp + sizeof(ContextAddress); + } + else { + dwn_sp = reg_sp + sizeof(ContextAddress) * 2; + } + dwn_bp = reg_bp; + } + else { + unsigned char code[5]; + + if (read_mem(ctx, addr - 1, code, sizeof(code)) < 0) return -1; + + if (func_entry(code + 1) || code[1] == ENTER || code[1] == RET || code[1] == RETADD) { + dwn_sp = reg_sp + sizeof(ContextAddress); + dwn_bp = reg_bp; + } + else if (func_entry(code)) { + dwn_sp = reg_sp + sizeof(ContextAddress) * 2; + dwn_bp = reg_bp; + } + else { + dwn_sp = reg_bp + sizeof(ContextAddress) * 2; + if (read_mem(ctx, reg_bp, &dwn_bp, sizeof(ContextAddress)) < 0) dwn_bp = 0; + } + } + } + else { + dwn_sp = reg_bp + sizeof(ContextAddress) * 2; + if (read_mem(ctx, reg_bp, &dwn_bp, sizeof(ContextAddress)) < 0) dwn_bp = 0; + } + + if (read_mem(ctx, dwn_sp - sizeof(ContextAddress), &dwn_ip, sizeof(ContextAddress)) < 0) dwn_ip = 0; + + if (dwn_bp < reg_sp) dwn_bp = 0; + + if (dwn_sp != 0) { + down->regs.REG_SP = dwn_sp; + down->mask.REG_SP = ~(ContextAddress)0; + } + if (dwn_bp != 0) { + down->regs.REG_BP = dwn_bp; + down->mask.REG_BP = ~(ContextAddress)0; + } + if (dwn_ip != 0) { + down->regs.REG_IP = dwn_ip; + down->mask.REG_IP = ~(ContextAddress)0; + } + + frame->fp = dwn_sp; + + return 0; +} + +RegisterDefinition * get_PC_definition(void) { + static RegisterDefinition * reg_def = NULL; + if (reg_def == NULL) { + RegisterDefinition * r; + for (r = get_reg_definitions(); r->name != NULL; r++) { + if (r->offset == offsetof(REG_SET, REG_IP)) { + reg_def = r; + break; + } + } + } + return reg_def; +} + +ContextAddress get_regs_PC_func(REG_SET * regs) { + return regs->REG_IP; +} + +void set_regs_PC_func(REG_SET * regs, ContextAddress pc) { + regs->REG_IP = pc; +} + +unsigned char BREAK_INST[] = { 0xcc }; + +#else + +# error "Unknown CPU" + +#endif diff --git a/main/cmdline.h b/main/cmdline.h index e2125d2d..04391af3 100644 --- a/main/cmdline.h +++ b/main/cmdline.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/main/main.c b/main/main.c index 9b6af230..c039f638 100644 --- a/main/main.c +++ b/main/main.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/main/main_client.c b/main/main_client.c index a5e781cd..674c914e 100644 --- a/main/main_client.c +++ b/main/main_client.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/main/main_lua.c b/main/main_lua.c index 04e15e1a..d2ecdf9b 100644 --- a/main/main_lua.c +++ b/main/main_lua.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/main/main_reg.c b/main/main_reg.c index e00af83c..9fc568c7 100644 --- a/main/main_reg.c +++ b/main/main_reg.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/main/test.c b/main/test.c index 1d0092f9..c18e14b3 100644 --- a/main/test.c +++ b/main/test.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/main/test.h b/main/test.h index 9e80f06e..991713b6 100644 --- a/main/test.h +++ b/main/test.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/services/breakpoints.c b/services/breakpoints.c index ca7ccd66..2ec7def2 100644 --- a/services/breakpoints.c +++ b/services/breakpoints.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. @@ -309,7 +309,7 @@ void check_breakpoints_on_memory_read(Context * ctx, ContextAddress address, voi if (bi->ctx->mem != ctx->mem) continue; if (bi->address + BREAK_SIZE <= address) continue; if (bi->address >= address + size) continue; - for (i = 0; i < BREAK_SIZE; i++) { + for (i = 0; i < (int)BREAK_SIZE; i++) { if (bi->address + i < address) continue; if (bi->address + i >= address + size) continue; buf[bi->address + i - address] = bi->saved_code[i]; @@ -330,7 +330,7 @@ void check_breakpoints_on_memory_write(Context * ctx, ContextAddress address, vo if (bi->ctx->mem != ctx->mem) continue; if (bi->address + BREAK_SIZE <= address) continue; if (bi->address >= address + size) continue; - for (i = 0; i < BREAK_SIZE; i++) { + for (i = 0; i < (int)BREAK_SIZE; i++) { if (bi->address + i < address) continue; if (bi->address + i >= address + size) continue; bi->saved_code[i] = buf[bi->address + i - address]; diff --git a/services/breakpoints.h b/services/breakpoints.h index 92f1c681..ed58bf81 100644 --- a/services/breakpoints.h +++ b/services/breakpoints.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/services/diagnostics.c b/services/diagnostics.c index e8745073..c24e35ed 100644 --- a/services/diagnostics.c +++ b/services/diagnostics.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/services/diagnostics.h b/services/diagnostics.h index dd7dcbd6..dbb8f043 100644 --- a/services/diagnostics.h +++ b/services/diagnostics.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/services/discovery.h b/services/discovery.h index c58d3194..4e2c6708 100644 --- a/services/discovery.h +++ b/services/discovery.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/services/discovery_udp.c b/services/discovery_udp.c index 53e4928b..b6df6333 100644 --- a/services/discovery_udp.c +++ b/services/discovery_udp.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/services/discovery_udp.h b/services/discovery_udp.h index ec4fdb97..48fdb5a4 100644 --- a/services/discovery_udp.h +++ b/services/discovery_udp.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/services/dwarf.h b/services/dwarf.h index f6de8f7f..284af029 100644 --- a/services/dwarf.h +++ b/services/dwarf.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 1996, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 1996, 2009 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. diff --git a/services/dwarfcache.c b/services/dwarfcache.c index 9b13393e..570dfd89 100644 --- a/services/dwarfcache.c +++ b/services/dwarfcache.c @@ -23,7 +23,6 @@ #if ENABLE_ELF #include <assert.h> -#include <stdio.h> #include "dwarf.h" #include "dwarfio.h" #include "dwarfcache.h" @@ -52,7 +51,8 @@ unsigned calc_symbol_name_hash(char * s) { while (*s) { unsigned g; h = (h << 4) + *s++; - if (g = h & 0xf0000000) h ^= g >> 24; + g = h & 0xf0000000; + if (g) h ^= g >> 24; h &= ~g; } return h % SYM_HASH_SIZE; @@ -119,9 +119,9 @@ static void read_mod_fund_type(U2_T Form, ObjectInfo ** Type) { size_t BufPos; dio_ChkBlock(Form, &Buf, &BufSize); *Type = find_object_info(sDebugSection->addr + dio_GetPos() - 1); - (*Type)->mTag = TAG_lo_user; + (*Type)->mTag = TAG_fund_type; (*Type)->mCompUnit = sCompUnit; - (*Type)->mEncoding = Buf[BufSize - 1]; + (*Type)->mFundType = Buf[BufSize - 1]; BufPos = BufSize - 1; while (BufPos > 0) { U2_T Tag = 0; @@ -198,11 +198,11 @@ static void read_tag_com_unit(U2_T Attr, U2_T Form) { break; case AT_low_pc: dio_ChkAddr(Form); - Unit->mLowPC = (ContextAddress)dio_gFormRef; + Unit->mLowPC = (ContextAddress)dio_gFormData; break; case AT_high_pc: dio_ChkAddr(Form); - Unit->mHighPC = (ContextAddress)dio_gFormRef; + Unit->mHighPC = (ContextAddress)dio_gFormData; break; case AT_ranges: dio_ChkData(Form); @@ -221,7 +221,7 @@ static void read_tag_com_unit(U2_T Attr, U2_T Form) { Unit->mLineInfoOffs = dio_gFormData; break; case AT_base_types: - Unit->mBaseTypes = find_comp_unit(dio_gFormRef); + Unit->mBaseTypes = find_comp_unit(dio_gFormData); break; } } @@ -260,22 +260,22 @@ static void read_object_attributes(U2_T Tag, U2_T Attr, U2_T Form) { break; case AT_sibling: dio_ChkRef(Form); - Sibling = dio_gFormRef - sDebugSection->addr; + Sibling = dio_gFormData - sDebugSection->addr; break; case AT_type: dio_ChkRef(Form); - Info->mType = find_object_info(dio_gFormRef); + Info->mType = find_object_info(dio_gFormData); break; case AT_fund_type: dio_ChkData(Form); Info->mType = find_object_info(sDebugSection->addr + dio_GetPos() - dio_gFormDataSize); - Info->mType->mTag = TAG_lo_user; + Info->mType->mTag = TAG_fund_type; Info->mCompUnit = sCompUnit; - Info->mType->mEncoding = (U2_T)dio_gFormData; + Info->mType->mFundType = (U2_T)dio_gFormData; break; case AT_user_def_type: dio_ChkRef(Form); - Info->mType = find_object_info(dio_gFormRef); + Info->mType = find_object_info(dio_gFormData); break; case AT_mod_fund_type: read_mod_fund_type(Form, &Info->mType); @@ -283,18 +283,6 @@ static void read_object_attributes(U2_T Tag, U2_T Attr, U2_T Form) { case AT_mod_u_d_type: read_mod_user_def_type(Form, &Info->mType); break; - case AT_encoding: - dio_ChkData(Form); - Info->mEncoding = (U2_T)dio_gFormData; - break; - case AT_low_pc: - dio_ChkAddr(Form); - Info->mLowPC = (ContextAddress)dio_gFormRef; - break; - case AT_high_pc: - dio_ChkAddr(Form); - Info->mHighPC = (ContextAddress)dio_gFormRef; - break; case AT_name: dio_ChkString(Form); Info->mName = dio_gFormDataAddr; @@ -450,6 +438,12 @@ static void load_debug_sections(void) { else if (strcmp(sec->name, ".debug_loc") == 0) { sCache->mDebugLoc = sec; } + else if (strcmp(sec->name, ".debug_frame") == 0) { + sCache->mDebugFrame = sec; + } + else if (strcmp(sec->name, ".eh_frame") == 0) { + sCache->mEHFrame = sec; + } } if (sObjectList == NULL) { @@ -466,7 +460,6 @@ static void load_debug_sections(void) { static U2_T gop_gAttr = 0; static U2_T gop_gForm = 0; -static U8_T gop_gFormRef = 0; /* Absolute address */ static U8_T gop_gFormData = 0; static size_t gop_gFormDataSize = 0; static void * gop_gFormDataAddr = NULL; @@ -474,7 +467,6 @@ static void * gop_gFormDataAddr = NULL; static void get_object_property_callback(U2_T Tag, U2_T Attr, U2_T Form) { if (Attr != gop_gAttr) return; gop_gForm = Form; - gop_gFormRef = dio_gFormRef; gop_gFormData = dio_gFormData; gop_gFormDataSize = dio_gFormDataSize; gop_gFormDataAddr = dio_gFormDataAddr; @@ -499,24 +491,25 @@ U8_T get_numeric_property_value(PropertyValue * Value) { int read_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Obj, int Attr, PropertyValue * Value) { Trap trap; + if (Obj->mTag == TAG_fund_type) { + /* TAG_fund_type is virtual DWARF object that is created by DWARF reader. It has no properties. */ + errno = ERR_SYM_NOT_FOUND; + return -1; + } + memset(Value, 0, sizeof(PropertyValue)); Value->mContext = Ctx; Value->mFrame = Frame; Value->mObject = Obj; - Value->mAttr = Attr; + Value->mAttr = (U2_T)Attr; Value->mBigEndian = Obj->mCompUnit->mFile->big_endian; - if (Attr == AT_location && Obj->mLowPC != 0) { - Value->mValue = Obj->mLowPC; - return 0; - } - sCompUnit = Obj->mCompUnit; sCache = (DWARFCache *)sCompUnit->mFile->dwarf_dt_cache; sDebugSection = sCompUnit->mSection; dio_EnterDebugSection(&sCompUnit->mDesc, sDebugSection, Obj->mID - sDebugSection->addr); if (set_trap(&trap)) { - gop_gAttr = Attr; + gop_gAttr = (U2_T)Attr; gop_gForm = 0; dio_ReadEntry(get_object_property_callback); clear_trap(&trap); @@ -536,7 +529,7 @@ int read_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Obj, int A case FORM_REF8 : case FORM_REF_UDATA : { - ObjectInfo * RefObj = find_object(sCache, gop_gFormRef); + ObjectInfo * RefObj = find_object(sCache, gop_gFormData); PropertyValue ValueAddr; if (read_and_evaluate_dwarf_object_property(Ctx, Frame, 0, RefObj, AT_location, &ValueAddr) < 0) return -1; @@ -577,10 +570,11 @@ int read_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Obj, int A break; case FORM_SDATA : case FORM_UDATA : + case FORM_ADDR: Value->mValue = gop_gFormData; break; default: - errno = ENOENT; + errno = ERR_SYM_NOT_FOUND; return -1; } return 0; @@ -850,7 +844,7 @@ void load_line_numbers(DWARFCache * Cache, CompUnit * Unit) { state.mFile = dio_ReadULEB128(); break; case DW_LNS_set_column: - state.mColumn = dio_ReadULEB128(); + state.mColumn = (U2_T)dio_ReadULEB128(); break; case DW_LNS_negate_stmt: state.mFlags ^= LINE_IsStmt; diff --git a/services/dwarfcache.h b/services/dwarfcache.h index 7b5f4db8..d173a9fd 100644 --- a/services/dwarfcache.h +++ b/services/dwarfcache.h @@ -30,6 +30,7 @@ #include "context.h" #include "tcf_elf.h" #include "dwarfio.h" +#include "stacktrace.h" typedef struct FileInfo FileInfo; typedef struct LocationInfo LocationInfo; @@ -62,6 +63,8 @@ struct SymbolSection { unsigned * mHashNext; }; +#define TAG_fund_type 0x2000 + struct ObjectInfo { ObjectInfo * mHashNext; ObjectInfo * mListNext; @@ -69,13 +72,10 @@ struct ObjectInfo { ObjectInfo * mChildren; ObjectInfo * mParent; - U2_T mTag; U8_T mID; + U2_T mTag; - ContextAddress mLowPC; - ContextAddress mHighPC; - - U2_T mEncoding; + U2_T mFundType; ObjectInfo * mType; CompUnit * mCompUnit; char * mName; @@ -153,6 +153,8 @@ struct DWARFCache { ELF_Section * mDebugARanges; ELF_Section * mDebugLine; ELF_Section * mDebugLoc; + ELF_Section * mDebugFrame; + ELF_Section * mEHFrame; SymbolSection ** mSymSections; unsigned mSymSectionsCnt; unsigned mSymSectionsLen; diff --git a/services/dwarfexpr.c b/services/dwarfexpr.c index 36442207..ab2b8335 100644 --- a/services/dwarfexpr.c +++ b/services/dwarfexpr.c @@ -37,7 +37,7 @@ static unsigned sExprStackLen = 0; static unsigned sExprStackMax = 0; static int sKeepStack = 0; -#define check_e_stack(n) if (sExprStackLen < n) { errno = ERR_INV_DWARF; return -1; } +#define check_e_stack(n) if (sExprStackLen < n) { errno = set_exception_errno(ERR_INV_DWARF, "invalid DWARF expression stack"); return -1; } static ObjectInfo * get_parent_function(ObjectInfo * Info) { while (Info != NULL) { @@ -54,391 +54,36 @@ static ObjectInfo * get_parent_function(ObjectInfo * Info) { } static int get_register(Context * Ctx, int Frame, unsigned rg, U8_T * value) { -#if !ENABLE_DebugContext -#elif defined(__linux__) && defined(__i386__) || \ - defined(_WRS_KERNEL) && (CPU_FAMILY==SIMNT || CPU_FAMILY==I80X86) - ContextAddress IP, FP; - if (is_top_frame(Ctx, Frame)) { - switch (rg) { - case 0: - *value = (ContextAddress)Ctx->regs.eax; - return 0; - case 1: - *value = (ContextAddress)Ctx->regs.ecx; - return 0; - case 2: - *value = (ContextAddress)Ctx->regs.edx; - return 0; - case 3: - *value = (ContextAddress)Ctx->regs.ebx; - return 0; - case 4: - *value = (ContextAddress)Ctx->regs.esp; - return 0; - case 5: - *value = (ContextAddress)Ctx->regs.ebp; - return 0; - case 6: - *value = (ContextAddress)Ctx->regs.esi; - return 0; - case 7: - *value = (ContextAddress)Ctx->regs.edi; - return 0; - case 8: -#ifdef _WRS_KERNEL - *value = (ContextAddress)Ctx->regs.pc; -#else - *value = (ContextAddress)Ctx->regs.eip; -#endif - return 0; - case 9: - *value = (ContextAddress)Ctx->regs.eflags; - return 0; - } - } - if (get_frame_info(Ctx, Frame, &IP, NULL, &FP) < 0) return -1; - switch (rg) { - case 5: - *value = FP; - return 0; - case 8: - *value = IP; - return 0; - } -#elif defined(__linux__) && defined(__x86_64__) - ContextAddress RA, FP; - if (is_top_frame(Ctx, Frame)) { - switch (rg) { - case 0: - *value = Ctx->regs.rax; - return 0; - case 1: - *value = Ctx->regs.rbx; - return 0; - case 2: - *value = Ctx->regs.rcx; - return 0; - case 3: - *value = Ctx->regs.rdx; - return 0; - case 4: - *value = Ctx->regs.rsi; - return 0; - case 5: - *value = Ctx->regs.rdi; - return 0; - case 6: - *value = Ctx->regs.rbp; - return 0; - case 7: - *value = Ctx->regs.rsp; - return 0; - case 8: - *value = Ctx->regs.r8; - return 0; - case 9: - *value = Ctx->regs.r9; - return 0; - case 10: - *value = Ctx->regs.r10; - return 0; - case 11: - *value = Ctx->regs.r11; - return 0; - case 12: - *value = Ctx->regs.r11; - return 0; - case 13: - *value = Ctx->regs.r13; - return 0; - case 14: - *value = Ctx->regs.r14; - return 0; - case 15: - *value = Ctx->regs.r15; - return 0; - case 16: - if (get_frame_info(Ctx, Frame, NULL, &RA, NULL) < 0) return -1; - *value = RA; - return 0; - } - } - if (get_frame_info(Ctx, Frame, NULL, &RA, &FP) < 0) return -1; - switch (rg) { - case 6: - *value = FP; - return 0; - case 16: - *value = RA; - return 0; - } -#elif defined(__APPLE__) && defined(__i386__) - ContextAddress IP, FP; - if (is_top_frame(Ctx, Frame)) { - switch (rg) { - case 0: - *value = (ContextAddress)Ctx->regs.__eax; - return 0; - case 1: - *value = (ContextAddress)Ctx->regs.__ecx; - return 0; - case 2: - *value = (ContextAddress)Ctx->regs.__edx; - return 0; - case 3: - *value = (ContextAddress)Ctx->regs.__ebx; - return 0; - case 4: - *value = (ContextAddress)Ctx->regs.__esp; - return 0; - case 5: - *value = (ContextAddress)Ctx->regs.__ebp; - return 0; - case 6: - *value = (ContextAddress)Ctx->regs.__esi; - return 0; - case 7: - *value = (ContextAddress)Ctx->regs.__edi; - return 0; - case 8: - *value = (ContextAddress)Ctx->regs.__eip; - return 0; - case 9: - *value = (ContextAddress)Ctx->regs.__eflags; - return 0; - } - } - if (get_frame_info(Ctx, Frame, &IP, NULL, &FP) < 0) return -1; - switch (rg) { - case 5: - *value = FP; - return 0; - case 8: - *value = IP; - return 0; - } -#elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(__i386__) - ContextAddress IP, FP; - if (is_top_frame(Ctx, Frame)) { - switch (rg) { - case 0: - *value = (ContextAddress)Ctx->regs.r_eax; - return 0; - case 1: - *value = (ContextAddress)Ctx->regs.r_ecx; - return 0; - case 2: - *value = (ContextAddress)Ctx->regs.r_edx; - return 0; - case 3: - *value = (ContextAddress)Ctx->regs.r_ebx; - return 0; - case 4: - *value = (ContextAddress)Ctx->regs.r_esp; - return 0; - case 5: - *value = (ContextAddress)Ctx->regs.r_ebp; - return 0; - case 6: - *value = (ContextAddress)Ctx->regs.r_esi; - return 0; - case 7: - *value = (ContextAddress)Ctx->regs.r_edi; - return 0; - case 8: - *value = (ContextAddress)Ctx->regs.r_eip; - return 0; - case 9: - *value = (ContextAddress)Ctx->regs.r_eflags; - return 0; - } - } - if (get_frame_info(Ctx, Frame, &IP, NULL, &FP) < 0) return -1; - switch (rg) { - case 5: - *value = FP; - return 0; - case 8: - *value = IP; - return 0; +#if ENABLE_DebugContext + RegisterDefinition * reg_def = get_reg_by_dwarf_id(rg); + if (reg_def != NULL) { + StackFrame * info; + if (get_frame_info(Ctx, Frame, &info) < 0) return -1; + if (read_reg_value(reg_def, info, value) >= 0) return 0; } -#else -#error "Unknown DWARF registers mapping" #endif - trace(LOG_ALWAYS, "get_register: Unsupported DWARF register number %d", rg); errno = ERR_UNSUPPORTED; return -1; } static int set_register(Context * Ctx, int Frame, unsigned rg, U8_T value) { -#if !ENABLE_DebugContext -#elif defined(__linux__) && defined(__i386__) || \ - defined(_WRS_KERNEL) && (CPU_FAMILY==SIMNT || CPU_FAMILY==I80X86) - if (is_top_frame(Ctx, Frame)) { - switch (rg) { - case 0: - Ctx->regs.eax = (ContextAddress)value; - return 0; - case 1: - Ctx->regs.ecx = (ContextAddress)value; - return 0; - case 2: - Ctx->regs.edx = (ContextAddress)value; - return 0; - case 3: - Ctx->regs.ebx = (ContextAddress)value; - return 0; - case 4: - Ctx->regs.esp = (ContextAddress)value; - return 0; - case 5: - Ctx->regs.ebp = (ContextAddress)value; - return 0; - case 6: - Ctx->regs.esi = (ContextAddress)value; - return 0; - case 7: - Ctx->regs.edi = (ContextAddress)value; - return 0; - case 8: -#ifdef _WRS_KERNEL - Ctx->regs.pc = (void *)(ContextAddress)value; -#else - Ctx->regs.eip = (ContextAddress)value; -#endif - return 0; - case 9: - Ctx->regs.eflags = (ContextAddress)value; - return 0; - } - } -#elif defined(__linux__) && defined(__x86_64__) - if (is_top_frame(Ctx, Frame)) { - switch (rg) { - case 0: - Ctx->regs.rax = (ContextAddress)value; - return 0; - case 1: - Ctx->regs.rbx = (ContextAddress)value; - return 0; - case 2: - Ctx->regs.rcx = (ContextAddress)value; - return 0; - case 3: - Ctx->regs.rdx = (ContextAddress)value; - return 0; - case 4: - Ctx->regs.rsi = (ContextAddress)value; - return 0; - case 5: - Ctx->regs.rdi = (ContextAddress)value; - return 0; - case 6: - Ctx->regs.rbp = (ContextAddress)value; - return 0; - case 7: - Ctx->regs.rsp = (ContextAddress)value; - return 0; - case 8: - Ctx->regs.r8 = (ContextAddress)value; - return 0; - case 9: - Ctx->regs.r9 = (ContextAddress)value; - return 0; - case 10: - Ctx->regs.r10 = (ContextAddress)value; - return 0; - case 11: - Ctx->regs.r11 = (ContextAddress)value; - return 0; - case 12: - Ctx->regs.r12 = (ContextAddress)value; - return 0; - case 13: - Ctx->regs.r13 = (ContextAddress)value; - return 0; - case 14: - Ctx->regs.r14 = (ContextAddress)value; - return 0; - case 15: - Ctx->regs.r15 = (ContextAddress)value; - return 0; - } - } -#elif defined(__APPLE__) && defined(__i386__) - if (is_top_frame(Ctx, Frame)) { - switch (rg) { - case 0: - Ctx->regs.__eax = (ContextAddress)value; - return 0; - case 1: - Ctx->regs.__ecx = (ContextAddress)value; - return 0; - case 2: - Ctx->regs.__edx = (ContextAddress)value; - return 0; - case 3: - Ctx->regs.__ebx = (ContextAddress)value; - return 0; - case 4: - Ctx->regs.__esp = (ContextAddress)value; - return 0; - case 5: - Ctx->regs.__ebp = (ContextAddress)value; - return 0; - case 6: - Ctx->regs.__esi = (ContextAddress)value; - return 0; - case 7: - Ctx->regs.__edi = (ContextAddress)value; - return 0; - case 8: - Ctx->regs.__eip = (ContextAddress)value; - return 0; - case 9: - Ctx->regs.__eflags = (ContextAddress)value; - return 0; - } - } -#elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(__i386__) - if (is_top_frame(Ctx, Frame)) { - switch (rg) { - case 0: - Ctx->regs.r_eax = (ContextAddress)value; - return 0; - case 1: - Ctx->regs.r_ecx = (ContextAddress)value; - return 0; - case 2: - Ctx->regs.r_edx = (ContextAddress)value; - return 0; - case 3: - Ctx->regs.r_ebx = (ContextAddress)value; - return 0; - case 4: - Ctx->regs.r_esp = (ContextAddress)value; - return 0; - case 5: - Ctx->regs.r_ebp = (ContextAddress)value; - return 0; - case 6: - Ctx->regs.r_esi = (ContextAddress)value; - return 0; - case 7: - Ctx->regs.r_edi = (ContextAddress)value; - return 0; - case 8: - Ctx->regs.r_eip = (ContextAddress)value; - return 0; - case 9: - Ctx->regs.r_eflags = (ContextAddress)value; +#if ENABLE_DebugContext + RegisterDefinition * reg_def = get_reg_by_dwarf_id(rg); + if (reg_def != NULL) { + size_t size = reg_def->size; + if (size <= 8 && Ctx->stopped && is_top_frame(Ctx, Frame)) { + U1_T * addr = (U1_T *)&Ctx->regs + reg_def->offset; + switch (size) { + case 1: *(U1_T *)addr = (U1_T)value; break; + case 2: *(U2_T *)addr = (U2_T)value; break; + case 4: *(U4_T *)addr = (U4_T)value; break; + case 8: *(U8_T *)addr = (U8_T)value; break; + } + Ctx->regs_dirty = 1; return 0; } } -#else -#error "Unknown DWARF registers mapping" #endif - trace(LOG_ALWAYS, "set_register: Unsupported DWARF register number %d", rg); errno = ERR_UNSUPPORTED; return -1; } @@ -450,7 +95,7 @@ static int register_access_func(PropertyValue * Value, int write, U8_T * Data) { static int evaluate_expression(U8_T BaseAddress, PropertyValue * Value, U1_T * Buf, size_t Size) { if (Size == 0) { - errno = ERR_INV_DWARF; + errno = set_exception_errno(ERR_INV_DWARF, "DWARF expression size = 0"); return -1; } dio_EnterDataSection(&Value->mObject->mCompUnit->mDesc, Buf, 0, Size); @@ -465,8 +110,8 @@ static int evaluate_expression(U8_T BaseAddress, PropertyValue * Value, U1_T * B switch (Op) { case OP_addr: if ((sExprStack[sExprStackLen++] = elf_map_to_run_time_address( - Value->mContext, Value->mObject->mCompUnit->mFile, dio_ReadAddress())) == 0) { - errno = ERR_INV_DWARF; + Value->mContext, Value->mObject->mCompUnit->mFile, (ContextAddress)dio_ReadAddress())) == 0) { + errno = set_exception_errno(ERR_INV_DWARF, "object has no RT address"); return -1; } break; @@ -803,7 +448,7 @@ static int evaluate_expression(U8_T BaseAddress, PropertyValue * Value, U1_T * B { unsigned n = Op - OP_reg0; if (dio_GetPos() < Size) { - errno = ERR_INV_DWARF; + errno = set_exception_errno(ERR_INV_DWARF, "OP_reg must be last instruction"); return -1; } Value->mValue = n; @@ -814,7 +459,7 @@ static int evaluate_expression(U8_T BaseAddress, PropertyValue * Value, U1_T * B { unsigned n = dio_ReadULEB128(); if (dio_GetPos() < Size) { - errno = ERR_INV_DWARF; + errno = set_exception_errno(ERR_INV_DWARF, "OP_regx must be last instruction"); return -1; } Value->mValue = n; @@ -863,8 +508,9 @@ static int evaluate_expression(U8_T BaseAddress, PropertyValue * Value, U1_T * B ObjectInfo * Parent = get_parent_function(Value->mObject); int error = 0; + memset(&FP, 0, sizeof(FP)); sKeepStack++; - if (Parent == NULL) error = ERR_INV_DWARF; + if (Parent == NULL) error = set_exception_errno(ERR_INV_DWARF, "OP_fbreg: no parent function"); if (!error && read_and_evaluate_dwarf_object_property(Value->mContext, Value->mFrame, 0, Parent, AT_frame_base, &FP) < 0) error = errno; sKeepStack--; @@ -913,20 +559,21 @@ static int evaluate_expression(U8_T BaseAddress, PropertyValue * Value, U1_T * B } static int evaluate_location(U8_T BaseAddresss, PropertyValue * Value) { - U1_T * Addr = NULL; + U8_T IP = 0; U8_T Offset = 0; U8_T Base = 0; U8_T BaseMark = 0; - ContextAddress IP = 0; + StackFrame * Frame = NULL; DWARFCache * Cache = (DWARFCache *)Value->mObject->mCompUnit->mFile->dwarf_dt_cache; assert(Cache->magic == SYM_CACHE_MAGIC); if (Cache->mDebugLoc == NULL) { - errno = ERR_INV_DWARF; + errno = set_exception_errno(ERR_INV_DWARF, "missing .debug_loc section"); return -1; } if (elf_load(Cache->mDebugLoc) < 0) return -1; - if (get_frame_info(Value->mContext, Value->mFrame, &IP, NULL, NULL) < 0) return -1; + if (get_frame_info(Value->mContext, Value->mFrame, &Frame) < 0) return -1; + if (read_reg_value(get_PC_definition(), Frame, &IP) < 0) return -1; dio_EnterDataSection(&Value->mObject->mCompUnit->mDesc, Value->mAddr, 0, Value->mSize); switch (Value->mSize) { case 4: @@ -938,12 +585,11 @@ static int evaluate_location(U8_T BaseAddresss, PropertyValue * Value) { BaseMark = ~(U8_T)0; break; default: - errno = ERR_INV_DWARF; + errno = set_exception_errno(ERR_INV_DWARF, "invalid .debug_loc pointer size"); return -1; } - Addr = Cache->mDebugLoc->data; Base = Value->mObject->mCompUnit->mLowPC; - dio_EnterDataSection(&Value->mObject->mCompUnit->mDesc, Addr, Offset, Cache->mDebugLoc->size); + dio_EnterDataSection(&Value->mObject->mCompUnit->mDesc, Cache->mDebugLoc->data, Offset, Cache->mDebugLoc->size); for (;;) { U8_T Addr0 = dio_ReadAddress(); U8_T Addr1 = dio_ReadAddress(); @@ -955,10 +601,10 @@ static int evaluate_location(U8_T BaseAddresss, PropertyValue * Value) { } else { U2_T Size = dio_ReadU2(); - ContextAddress RTAddr0 = elf_map_to_run_time_address(Value->mContext, Cache->mFile, Base + Addr0); - ContextAddress RTAddr1 = Addr1 - Addr0 + RTAddr0; + ContextAddress RTAddr0 = elf_map_to_run_time_address(Value->mContext, Cache->mFile, (ContextAddress)(Base + Addr0)); + ContextAddress RTAddr1 = (ContextAddress)(Addr1 - Addr0) + RTAddr0; if (RTAddr0 != 0 && IP >= RTAddr0 && IP < RTAddr1) { - return evaluate_expression(BaseAddresss, Value, Addr + dio_GetPos(), Size); + return evaluate_expression(BaseAddresss, Value, dio_GetDataPtr(), Size); } dio_Skip(Size); } @@ -984,7 +630,7 @@ int dwarf_evaluate_expression(U8_T BaseAddress, PropertyValue * Value) { } if (set_trap(&trap)) { if (Value->mAccessFunc != NULL || Value->mAddr == NULL || Value->mSize == 0) { - error = ERR_INV_DWARF; + error = set_exception_errno(ERR_INV_DWARF, "invalid DWARF expression reference"); } else if (Value->mForm == FORM_DATA4 || Value->mForm == FORM_DATA8) { if (evaluate_location(BaseAddress, Value) < 0) error = errno; @@ -998,7 +644,9 @@ int dwarf_evaluate_expression(U8_T BaseAddress, PropertyValue * Value) { error = trap.error; } - if (!error && !sKeepStack && sExprStackLen != (Value->mAccessFunc == NULL ? 1 : 0)) error = ERR_INV_DWARF; + if (!error && !sKeepStack && sExprStackLen != (Value->mAccessFunc == NULL ? 1u : 0u)) { + error = set_exception_errno(ERR_INV_DWARF, "invalid DWARF expression stack"); + } if (!error) { if (Value->mAccessFunc == NULL) { diff --git a/services/dwarfframe.c b/services/dwarfframe.c new file mode 100644 index 00000000..96711c20 --- /dev/null +++ b/services/dwarfframe.c @@ -0,0 +1,554 @@ +/******************************************************************************* + * Copyright (c) 2007-2009 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 + *******************************************************************************/ + +/* + * This module implements handling of .debug_frame and .eh_frame sections. + * + * Functions in this module use exceptions to report errors, see exceptions.h + */ + +#include "config.h" + +#if ENABLE_ELF + +#include <assert.h> +#include <stdio.h> +#include "dwarfio.h" +#include "dwarfframe.h" +#include "exceptions.h" +#include "breakpoints.h" +#include "myalloc.h" + +#define EH_PE_omit 0xff + +#define EH_PE_absptr 0x00 +#define EH_PE_uleb128 0x01 +#define EH_PE_udata2 0x02 +#define EH_PE_udata4 0x03 +#define EH_PE_udata8 0x04 +#define EH_PE_sleb128 0x09 +#define EH_PE_sdata2 0x0a +#define EH_PE_sdata4 0x0b +#define EH_PE_sdata8 0x0c + +#define EH_PB_pcrel 0x01 +#define EH_PB_textrel 0x02 +#define EH_PB_datarel 0x03 +#define EH_PB_funcrel 0x04 +#define EH_PB_aligned 0x05 + +#define EH_PE_indirect 0x80 + +#define RULE_OFFSET 1 +#define RULE_SAME_VALUE 2 +#define RULE_REGISTER 3 +#define RULE_EXPRESSION 4 +#define RULE_VAL_OFFSET 5 +#define RULE_VAL_EXPRESSION 6 + +typedef struct RegisterRules { + int rule; + I4_T offset; + U1_T * expression; +} RegisterRules; + +typedef struct StackFrameRegisters { + RegisterRules * regs; + int regs_cnt; + int regs_max; +} StackFrameRegisters; + +typedef struct StackFrameRules { + Context * ctx; + ELF_Section * section; + int eh_frame; + U1_T version; + U4_T code_alignment; + I4_T data_alignment; + U8_T cie_pos; + char * cie_aug; + U8_T cie_eh_data; + U4_T fde_aug_length; + U1_T * fde_aug_data; + U1_T lsda_encoding; + U1_T prh_encoding; + U1_T addr_encoding; + U8_T location; + int return_address_register; + int cfa_rule; + I4_T cfa_offset; + U4_T cfa_register; + U1_T * cfa_expression; +} StackFrameRules; + +static StackFrameRegisters frame_regs; +static StackFrameRegisters cie_regs; +static StackFrameRegisters * regs_stack = NULL; +static int regs_stack_max = 0; +static int regs_stack_pos = 0; + +static StackFrameRules rules; + +static RegisterRules * get_reg(StackFrameRegisters * regs, int reg) { + RegisterDefinition * reg_def; + while (reg >= regs->regs_max) { + regs->regs_max = regs->regs_max == 0 ? 32 : regs->regs_max * 2; + regs->regs = loc_realloc(regs->regs, sizeof(RegisterRules) * regs->regs_max); + } + while (regs->regs_cnt <= reg) { + int n = regs->regs_cnt++; + memset(regs->regs + n, 0, sizeof(RegisterRules)); + reg_def = rules.eh_frame ? + get_reg_by_eh_frame_id(n) : + get_reg_by_dwarf_id(n); + if (reg_def != NULL && reg_def->traceable) { + /* It looks like GCC assumes that an unspecified register implies "same value" */ + regs->regs[n].rule = RULE_SAME_VALUE; + } + } + return regs->regs + reg; +} + +static void copy_register_rules(StackFrameRegisters * dst, StackFrameRegisters * src) { + int n; + dst->regs_cnt = 0; + for (n = 0; n < src->regs_cnt; n++) { + *get_reg(dst, n) = *get_reg(src, n); + } +} + +static StackFrameRegisters * get_regs_stack_item(int n) { + while (n >= regs_stack_max) { + int max = regs_stack_max; + regs_stack_max = regs_stack_max == 0 ? 8 : regs_stack_max * 2; + regs_stack = loc_realloc(regs_stack, sizeof(StackFrameRegisters) * regs_stack_max); + memset(regs_stack + max, 0, sizeof(StackFrameRegisters) * (regs_stack_max - max)); + } + return regs_stack + n; +} + +static U8_T read_frame_data_pointer(U1_T encoding, int abs) { + U8_T v = 0; + if (encoding != EH_PE_omit) { + U8_T pos = dio_GetPos(); + switch (encoding & 0xf) { + case EH_PE_absptr: + v = dio_ReadAddress(); + break; + case EH_PE_uleb128: + v = dio_ReadU8LEB128(); + break; + case EH_PE_udata2: + v = dio_ReadU2(); + break; + case EH_PE_udata4: + v = dio_ReadU4(); + break; + case EH_PE_udata8: + v = dio_ReadU8(); + break; + case EH_PE_sleb128: + v = dio_ReadS8LEB128(); + break; + case EH_PE_sdata2: + v = (I2_T)dio_ReadU2(); + break; + case EH_PE_sdata4: + v = (I4_T)dio_ReadU4(); + break; + case EH_PE_sdata8: + v = (I8_T)dio_ReadU8(); + break; + default: + printf("cie at 0x%08x\n", (U4_T)rules.cie_pos); + str_exception(ERR_INV_DWARF, "Unknown encoding of .eh_frame section pointers"); + break; + } + if (v != 0 && !abs) { + switch ((encoding >> 4) & 0x7) { + case 0: + break; + case EH_PB_pcrel: + v += rules.section->addr + pos; + break; + case EH_PB_datarel: + v += rules.section->addr; + break; + case EH_PB_textrel: + case EH_PB_funcrel: + case EH_PB_aligned: + default: + str_exception(ERR_INV_DWARF, "Unknown encoding of .eh_frame section pointers"); + break; + } + if (encoding & EH_PE_indirect) { + unsigned idx; + U8_T res = 0; + ELF_File * file = rules.section->file; + for (idx = 1; idx < file->section_cnt; idx++) { + ELF_Section * sec = file->sections + idx; + if ((sec->flags & SHF_ALLOC) == 0) continue; + if (sec->addr <= v && sec->addr + sec->size > v) { + res = elf_read_section(sec, (uintptr_t)(v - sec->addr), file->elf64 ? 8 : 4); + break; + } + } + v = res; + } + } + } + return v; +} + +static void exec_stack_frame_instruction(void) { + RegisterRules * reg; + U4_T n; + U1_T op = dio_ReadU1(); + switch (op) { + case 0x00: /* DW_CFA_nop */ + break; + case 0x01: /* DW_CFA_set_loc */ + rules.location = read_frame_data_pointer(rules.addr_encoding, 0); + break; + case 0x02: /* DW_CFA_advance_loc1 */ + rules.location += dio_ReadU1() * rules.code_alignment; + break; + case 0x03: /* DW_CFA_advance_loc2 */ + rules.location += dio_ReadU2() * rules.code_alignment; + break; + case 0x04: /* DW_CFA_advance_loc4 */ + rules.location += dio_ReadU4() * rules.code_alignment; + break; + case 0x05: /* DW_CFA_offset_extended */ + reg = get_reg(&frame_regs, dio_ReadULEB128()); + reg->rule = RULE_OFFSET; + reg->offset = dio_ReadULEB128() * rules.data_alignment; + break; + case 0x06: /* DW_CFA_restore_extended */ + n = dio_ReadULEB128(); + reg = get_reg(&frame_regs, n); + *reg = *get_reg(&cie_regs, n); + break; + case 0x07: /* DW_CFA_undefined */ + reg = get_reg(&frame_regs, dio_ReadULEB128()); + memset(reg, 0, sizeof(*reg)); + break; + case 0x08: /* DW_CFA_same_value */ + reg = get_reg(&frame_regs, dio_ReadULEB128()); + reg->rule = RULE_SAME_VALUE; + break; + case 0x09: /* DW_CFA_register */ + reg = get_reg(&frame_regs, dio_ReadULEB128()); + reg->rule = RULE_REGISTER; + reg->offset = dio_ReadULEB128(); + break; + case 0x0a: /* DW_CFA_remember_state */ + copy_register_rules(get_regs_stack_item(regs_stack_pos++), &frame_regs); + break; + case 0x0b: /* DW_CFA_restore_state */ + if (regs_stack_pos <= 0) { + str_exception(ERR_INV_DWARF, "Invalid DW_CFA_restore_state instruction"); + } + copy_register_rules(&frame_regs, get_regs_stack_item(--regs_stack_pos)); + break; + case 0x0c: /* DW_CFA_def_cfa */ + rules.cfa_rule = RULE_OFFSET; + rules.cfa_register = dio_ReadULEB128(); + rules.cfa_offset = dio_ReadULEB128(); + break; + case 0x0d: /* DW_CFA_def_cfa_register */ + rules.cfa_rule = RULE_OFFSET; + rules.cfa_register = dio_ReadULEB128(); + break; + case 0x0e: /* DW_CFA_def_cfa_offset */ + rules.cfa_rule = RULE_OFFSET; + rules.cfa_offset = dio_ReadULEB128(); + break; + case 0x0f: /* DW_CFA_def_cfa_expression */ + rules.cfa_rule = RULE_EXPRESSION; + rules.cfa_offset = dio_ReadULEB128(); + rules.cfa_expression = dio_GetDataPtr(); + dio_Skip(rules.cfa_offset); + break; + case 0x10: /* DW_CFA_expression */ + reg = get_reg(&frame_regs, dio_ReadULEB128()); + reg->rule = RULE_EXPRESSION; + reg->offset = dio_ReadULEB128(); + reg->expression = dio_GetDataPtr(); + dio_Skip(reg->offset); + break; + case 0x11: /* DW_CFA_offset_extended_sf */ + reg = get_reg(&frame_regs, dio_ReadULEB128()); + reg->rule = RULE_OFFSET; + reg->offset = dio_ReadSLEB128() * rules.data_alignment; + break; + case 0x12: /* DW_CFA_def_cfa_sf */ + rules.cfa_rule = RULE_OFFSET; + rules.cfa_register = dio_ReadULEB128(); + rules.cfa_offset = dio_ReadSLEB128() * rules.data_alignment; + break; + case 0x13: /* DW_CFA_def_cfa_offset_sf */ + rules.cfa_rule = RULE_OFFSET; + rules.cfa_offset = dio_ReadSLEB128() * rules.data_alignment; + break; + case 0x14: /* DW_CFA_val_offset */ + reg = get_reg(&frame_regs, dio_ReadULEB128()); + reg->rule = RULE_VAL_OFFSET; + reg->offset = dio_ReadULEB128() * rules.data_alignment; + break; + case 0x15: /* DW_CFA_val_offset_sf */ + reg = get_reg(&frame_regs, dio_ReadULEB128()); + reg->rule = RULE_VAL_OFFSET; + reg->offset = dio_ReadSLEB128() * rules.data_alignment; + break; + case 0x16: /* DW_CFA_val_expression */ + reg = get_reg(&frame_regs, dio_ReadULEB128()); + reg->rule = RULE_VAL_EXPRESSION; + reg->offset = dio_ReadULEB128(); + reg->expression = dio_GetDataPtr(); + dio_Skip(reg->offset); + break; + default: + switch (op >> 6) { + case 0: + str_exception(ERR_INV_DWARF, "Unsupported instruction in Call Frame Information"); + break; + case 1: /* DW_CFA_advance_loc */ + rules.location += (op & 0x3f) * rules.code_alignment; + break; + case 2: /* DW_CFA_offset */ + reg = get_reg(&frame_regs, op & 0x3f); + reg->rule = RULE_OFFSET; + reg->offset = dio_ReadULEB128() * rules.data_alignment; + break; + case 3: /* DW_CFA_restore */ + n = op & 0x3f; + reg = get_reg(&frame_regs, n); + *reg = *get_reg(&cie_regs, n); + break; + } + } +} + +static int fill_frame_register(RegisterRules * reg, RegisterDefinition * reg_def, StackFrame * frame, StackFrame * down) { + switch (reg->rule) { + case RULE_OFFSET: + if (frame->fp != 0 && reg_def != NULL) { + size_t size = reg_def->size; + if (size <= 8) { + U1_T v[8]; + if (context_read_mem(rules.ctx, frame->fp + reg->offset, v, size) < 0) return -1; + check_breakpoints_on_memory_read(rules.ctx, frame->fp + reg->offset, v, size); + switch (size) { + case 1: write_reg_value(reg_def, down, *(U1_T *)v); break; + case 2: write_reg_value(reg_def, down, *(U2_T *)v); break; + case 4: write_reg_value(reg_def, down, *(U4_T *)v); break; + case 8: write_reg_value(reg_def, down, *(U8_T *)v); break; + } + } + } + break; + case RULE_SAME_VALUE: + if (reg_def != NULL) { + U8_T v = 0; + if (read_reg_value(reg_def, frame, &v) >= 0) { + write_reg_value(reg_def, down, v); + } + } + break; + case RULE_REGISTER: + if (reg_def != NULL) { + RegisterDefinition * src_index = rules.eh_frame ? + get_reg_by_eh_frame_id(reg->offset) : + get_reg_by_dwarf_id(reg->offset); + if (src_index != NULL) { + U8_T v = 0; + if (read_reg_value(src_index, frame, &v) >= 0) { + write_reg_value(reg_def, down, v); + } + } + } + break; + case RULE_VAL_OFFSET: + if (frame->fp != 0 && reg_def != NULL) { + U8_T v = frame->fp + reg->offset; + write_reg_value(reg_def, down, v); + } + break; + case RULE_EXPRESSION: + case RULE_VAL_EXPRESSION: + /* TODO: RULE_EXPRESSION */ + break; + } + return 0; +} + +static int fill_stack_frame(StackFrame * frame, StackFrame * down) { + int i; + U8_T v = 0; + RegisterRules * reg; + RegisterDefinition * reg_def; + + switch (rules.cfa_rule) { + case RULE_OFFSET: + reg_def = rules.eh_frame ? + get_reg_by_eh_frame_id(rules.cfa_register) : + get_reg_by_dwarf_id(rules.cfa_register); + if (reg_def != NULL) { + if (read_reg_value(reg_def, frame, &v) >= 0) { + frame->fp = (ContextAddress)(v + rules.cfa_offset); + } + } + break; + /* TODO: RULE_EXPRESSION */ + } + + reg = get_reg(&frame_regs, rules.return_address_register); + if (reg->rule != 0 && fill_frame_register(reg, get_PC_definition(), frame, down) < 0) return -1; + for (i = 0; i < frame_regs.regs_cnt; i++) { + if (i == rules.return_address_register) continue; + reg = get_reg(&frame_regs, i); + if (reg->rule == 0) continue; + reg_def = rules.eh_frame ? + get_reg_by_eh_frame_id(i) : + get_reg_by_dwarf_id(i); + if (fill_frame_register(reg, reg_def, frame, down) < 0) return -1; + } + return 0; +} + +static void read_frame_cie(U8_T pos) { + int cie_dwarf64 = 0; + U8_T saved_pos = dio_GetPos(); + U8_T cie_length = 0; + U8_T cie_end = 0; + + rules.cie_pos = pos; + dio_Skip(pos - dio_GetPos()); + cie_length = dio_ReadU4(); + if (cie_length == 0xffffffffu) { + cie_length = dio_ReadU8(); + cie_dwarf64 = 1; + } + cie_end = dio_GetPos() + cie_length; + dio_Skip(cie_dwarf64 ? 8 : 4); + rules.version = dio_ReadU1(); + if (rules.version != 1 && rules.version != 3) { + str_exception(ERR_INV_DWARF, "Unsupported version of Call Frame Information"); + } + rules.cie_aug = dio_ReadString(); + if (rules.cie_aug != NULL && strcmp(rules.cie_aug, "eh") == 0) { + rules.cie_eh_data = dio_ReadAddress(); + } + rules.code_alignment = dio_ReadULEB128(); + rules.data_alignment = dio_ReadSLEB128(); + rules.return_address_register = dio_ReadULEB128(); + rules.lsda_encoding = 0; + rules.prh_encoding = 0; + rules.addr_encoding = 0; + if (rules.cie_aug != NULL && rules.cie_aug[0] == 'z') { + U4_T aug_length = dio_ReadULEB128(); + U8_T aug_pos = dio_GetPos(); + char * p = rules.cie_aug + 1; + while (*p) { + switch (*p++) { + case 'L': + rules.lsda_encoding = dio_ReadU1(); + break; + case 'P': + rules.prh_encoding = dio_ReadU1(); + read_frame_data_pointer(rules.prh_encoding, 0); + break; + case 'R': + rules.addr_encoding = dio_ReadU1(); + break; + } + } + dio_Skip(aug_pos + aug_length - dio_GetPos()); + } + cie_regs.regs_cnt = 0; + frame_regs.regs_cnt = 0; + regs_stack_pos = 0; + while (dio_GetPos() < cie_end) { + exec_stack_frame_instruction(); + } + copy_register_rules(&cie_regs, &frame_regs); + dio_Skip(saved_pos - dio_GetPos()); +} + +void get_dwarf_stack_frame_info(Context * ctx, ELF_File * file, StackFrame * frame, StackFrame * down) { + /* TODO: use .eh_frame_hdr section for faster frame data search */ + U8_T IP = 0; + DWARFCache * cache = get_dwarf_cache(file); + ELF_Section * section = cache->mDebugFrame; + if (section == NULL) section = cache->mEHFrame; + if (section == NULL) return; + + if (read_reg_value(get_PC_definition(), frame, &IP) < 0) exception(errno); + memset(&rules, 0, sizeof(StackFrameRules)); + rules.ctx = ctx; + rules.section = section; + rules.eh_frame = section == cache->mEHFrame; + rules.cie_pos = ~(U8_T)0; + dio_EnterDebugSection(NULL, section, 0); + while (dio_GetPos() < section->size) { + int fde_dwarf64 = 0; + U8_T fde_length = 0; + U8_T fde_pos = 0; + U8_T fde_end = 0; + U8_T cie_ref = 0; + int fde_flag = 0; + + fde_length = dio_ReadU4(); + if (fde_length == 0xffffffffu) { + fde_length = dio_ReadU8(); + fde_dwarf64 = 1; + } + if (fde_length == 0) break; + fde_pos = dio_GetPos(); + fde_end = fde_pos + fde_length; + cie_ref = fde_dwarf64 ? dio_ReadU8() : dio_ReadU4(); + if (rules.eh_frame) fde_flag = cie_ref != 0; + else if (fde_dwarf64) fde_flag = cie_ref != ~(U8_T)0; + else fde_flag = cie_ref != ~(U4_T)0; + if (fde_flag) { + U8_T Addr, Range, AddrRT; + if (rules.eh_frame) cie_ref = fde_pos - cie_ref; + if (cie_ref != rules.cie_pos) read_frame_cie(cie_ref); + Addr = read_frame_data_pointer(rules.addr_encoding, 0); + Range = read_frame_data_pointer(rules.addr_encoding, 1); + AddrRT = elf_map_to_run_time_address(ctx, file, (ContextAddress)Addr); + if (AddrRT != 0 && AddrRT <= IP && AddrRT + Range > IP) { + if (rules.cie_aug != NULL && rules.cie_aug[0] == 'z') { + rules.fde_aug_length = dio_ReadULEB128(); + rules.fde_aug_data = dio_GetDataPtr(); + dio_Skip(rules.fde_aug_length); + } + copy_register_rules(&frame_regs, &cie_regs); + rules.location = Addr; + regs_stack_pos = 0; + while (dio_GetPos() < fde_end) { + exec_stack_frame_instruction(); + if (rules.location - Addr + AddrRT > IP) break; + } + fill_stack_frame(frame, down); + break; + } + } + dio_Skip(fde_end - dio_GetPos()); + } + dio_ExitSection(); +} + +#endif /* ENABLE_ELF */ diff --git a/services/dwarfframe.h b/services/dwarfframe.h new file mode 100644 index 00000000..d4939ed8 --- /dev/null +++ b/services/dwarfframe.h @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2007-2009 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 + *******************************************************************************/ + +/* + * This module implements handling of .debug_frame and .eh_frame sections. + * + * Functions in this module use exceptions to report errors, see exceptions.h + */ + +#ifndef D_dwarfframe +#define D_dwarfframe + +#include "config.h" + +#if ENABLE_ELF + +#include "context.h" +#include "dwarfcache.h" + +/* + * Lookup stack frame data in ELF file, in .debug_frame and .eh_frame sections. + * + * "frame" is current frame info, it should have frame->regs and frame->mask filled with + * proper values before this function is called. + * + * "down" is next frame - moving from stack top to the bottom. + * + * The function uses register values in current frame to calculate frame address "frame->fp", + * and calculate register values in the next frame. + * + * If frame data is not found the function does nothing. + * In case of error reading frame data, the function throws an exception. + */ +extern void get_dwarf_stack_frame_info(Context * ctx, ELF_File * file, StackFrame * frame, StackFrame * down); + +#endif /* ENABLE_ELF */ + +#endif /* D_dwarfframe */ diff --git a/services/dwarfio.c b/services/dwarfio.c index 343c2ba4..72b38897 100644 --- a/services/dwarfio.c +++ b/services/dwarfio.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2009 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. @@ -59,13 +59,13 @@ typedef struct DIO_Cache DIO_Cache; U8_T dio_gEntryPos = 0; -U8_T dio_gFormRef = 0; U8_T dio_gFormData = 0; size_t dio_gFormDataSize = 0; void * dio_gFormDataAddr = NULL; static ELF_Section * sSection; -static U1_T sBigEndian; +static int sBigEndian; +static int sAddressSize; static U1_T * sData; static U8_T sDataPos; static U8_T sDataLen; @@ -116,6 +116,9 @@ void dio_EnterDebugSection(DIO_UnitDescriptor * Unit, ELF_Section * Section, U8_ sDataPos = Offset; sDataLen = Section->size; sBigEndian = Section->file->big_endian; + if (Unit != NULL) sAddressSize = Unit->mAddressSize; + else if (Section->file->elf64) sAddressSize = 8; + else sAddressSize = 4; sUnit = Unit; dio_gEntryPos = 0; assert(sData != NULL); @@ -127,6 +130,7 @@ void dio_EnterDataSection(DIO_UnitDescriptor * Unit, U1_T * Data, U8_T Offset, U sDataPos = Offset; sDataLen = Size; sBigEndian = Unit->mFile->big_endian; + sAddressSize = Unit->mAddressSize; sUnit = Unit; dio_gEntryPos = 0; assert(sData != NULL); @@ -144,6 +148,10 @@ U8_T dio_GetPos() { return sDataPos; } +U1_T * dio_GetDataPtr(void) { + return sData + sDataPos; +} + void dio_Skip(I8_T Bytes) { if (sDataPos + Bytes > sDataLen) exception(ERR_EOF); sDataPos += Bytes; @@ -249,7 +257,7 @@ U8_T dio_ReadUX(int Size) { } U8_T dio_ReadAddress(void) { - switch (sUnit->mAddressSize) { + switch (sAddressSize) { case 2: return dio_ReadU2(); case 4: @@ -304,7 +312,8 @@ static U1_T * dio_LoadStringTable(U4_T * StringTableSize) { } static void dio_ReadFormAddr(void) { - dio_gFormRef = dio_ReadAddress(); + dio_gFormData = dio_ReadAddress(); + dio_gFormDataSize = sAddressSize; } static void dio_ReadFormBlock(U4_T Size) { @@ -321,20 +330,23 @@ static void dio_ReadFormData(U1_T Size, U8_T Data) { } static void dio_ReadFormRef(void) { - dio_gFormRef = dio_ReadU4(); + dio_gFormData = dio_ReadU4(); + dio_gFormDataSize = 4; } static void dio_ReadFormRelRef(U8_T Offset) { if (sUnit->mUnitSize > 0 && Offset >= sUnit->mUnitSize) { str_exception(ERR_INV_DWARF, "invalid REF attribute value"); } - dio_gFormRef = sSection->addr + sUnit->mUnitOffs + Offset; + dio_gFormData = sSection->addr + sUnit->mUnitOffs + Offset; + dio_gFormDataSize = sAddressSize; } static void dio_ReadFormRefAddr(void) { U4_T Size = sUnit->mAddressSize; if (sUnit->mVersion >= 3) Size = sUnit->m64bit ? 8 : 4; - dio_gFormRef = dio_ReadUX(Size); + dio_gFormData = dio_ReadUX(Size); + dio_gFormDataSize = Size; } static void dio_ReadFormString(void) { @@ -362,7 +374,6 @@ static void dio_ReadAttribute(U2_T Attr, U2_T Form) { dio_gFormDataAddr = NULL; dio_gFormDataSize = 0; dio_gFormData = 0; - dio_gFormRef = 0; switch (Form) { case FORM_ADDR : dio_ReadFormAddr(); break; case FORM_REF : dio_ReadFormRef(); break; @@ -443,7 +454,7 @@ void dio_ReadEntry(DIO_EntryCallBack CallBack) { if (Attr == AT_sibling && sUnit->mUnitSize == 0) { dio_ChkRef(Form); assert(sUnit->mVersion == 1); - sUnit->mUnitSize = (U4_T)(dio_gFormRef - sSection->addr - sUnit->mUnitOffs); + sUnit->mUnitSize = (U4_T)(dio_gFormData - sSection->addr - sUnit->mUnitOffs); assert(sUnit->mUnitOffs < dio_GetPos()); assert(sUnit->mUnitOffs + sUnit->mUnitSize >= dio_GetPos()); } diff --git a/services/dwarfio.h b/services/dwarfio.h index 62637d50..53bdd475 100644 --- a/services/dwarfio.h +++ b/services/dwarfio.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2009 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. @@ -37,7 +37,6 @@ typedef struct DIO_UnitDescriptor { extern U8_T dio_gEntryPos; -extern U8_T dio_gFormRef; /* Absolute address */ extern U8_T dio_gFormData; extern size_t dio_gFormDataSize; extern void * dio_gFormDataAddr; @@ -49,6 +48,7 @@ extern void dio_ExitSection(void); extern void dio_Skip(I8_T Bytes); extern void dio_Read(U1_T * Buf, U4_T Size); extern U8_T dio_GetPos(void); /* Offset in the section */ +extern U1_T * dio_GetDataPtr(void); extern U1_T dio_ReadU1(void); extern U2_T dio_ReadU2(void); diff --git a/services/expressions.c b/services/expressions.c index 364d2fa2..3a1f7575 100644 --- a/services/expressions.c +++ b/services/expressions.c @@ -2209,6 +2209,7 @@ static void command_evaluate(char * token, Channel * c) { if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); if (expression_context_id(id, parent, &ctx, &frame, name, &expr) < 0) err = errno; + if (!err && frame != STACK_NO_FRAME && !ctx->intercepted) err = ERR_IS_RUNNING; if (!err && evaluate_expression(ctx, frame, expr ? expr->script : name, 0, &value) < 0) err = errno; if (value.size >= 0x100000) err = ERR_BUFFER_OVERFLOW; diff --git a/services/expressions.h b/services/expressions.h index 97b6a65f..4efa49a9 100644 --- a/services/expressions.h +++ b/services/expressions.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/services/filesystem.c b/services/filesystem.c index d1a43fd8..8dd6e36e 100644 --- a/services/filesystem.c +++ b/services/filesystem.c @@ -1174,6 +1174,7 @@ static void command_roots(char * token, Channel * c) { } } #elif defined(_WRS_KERNEL) + /* TODO: iosDvList */ write_stream(&c->out, '{'); json_write_string(&c->out, "FileName"); write_stream(&c->out, ':'); diff --git a/services/filesystem.h b/services/filesystem.h index b53406b9..239be92d 100644 --- a/services/filesystem.h +++ b/services/filesystem.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/services/linenumbers.h b/services/linenumbers.h index 68b5dae8..da40dce2 100644 --- a/services/linenumbers.h +++ b/services/linenumbers.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/services/linenumbers_elf.c b/services/linenumbers_elf.c index c82b9527..8df3cba4 100644 --- a/services/linenumbers_elf.c +++ b/services/linenumbers_elf.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/services/linenumbers_win32.c b/services/linenumbers_win32.c index 05235990..c2baafac 100644 --- a/services/linenumbers_win32.c +++ b/services/linenumbers_win32.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. @@ -20,7 +20,7 @@ #include "config.h" -#if SERVICE_LineNumbers && defined(_MSC_VER) +#if SERVICE_LineNumbers && defined(_MSC_VER) && !ENABLE_ELF #include <errno.h> #include <assert.h> diff --git a/services/memoryservice.c b/services/memoryservice.c index 3177a87a..9d19c531 100644 --- a/services/memoryservice.c +++ b/services/memoryservice.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/services/memoryservice.h b/services/memoryservice.h index b58a08b3..b0dd07c1 100644 --- a/services/memoryservice.h +++ b/services/memoryservice.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/services/processes.c b/services/processes.c index 809febec..f50b448f 100644 --- a/services/processes.c +++ b/services/processes.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/services/processes.h b/services/processes.h index b018efd8..ace94ff2 100644 --- a/services/processes.h +++ b/services/processes.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/services/registers.c b/services/registers.c index 343ea292..46c26735 100644 --- a/services/registers.c +++ b/services/registers.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. @@ -29,117 +29,15 @@ #include "context.h" #include "json.h" #include "exceptions.h" +#include "stacktrace.h" #include "registers.h" static const char * REGISTERS = "Registers"; -#if defined(_WRS_KERNEL) - -# define regs_index taskRegName -# if defined(_WRS_REG_INDEX_REGWIDTH) || (CPU_FAMILY==COLDFIRE) -# define REG_WIDTH(x) (x).regWidth -# else -# define REG_WIDTH(x) 4 -# endif - -#else - -typedef struct { - char *regName; /* pointer to register name */ - int regOff; /* offset to entry in REG_SET */ - int regWidth; /* register width in bytes */ -} REG_INDEX; - -#define REG_WIDTH(x) (x).regWidth - -#define REG_OFFSET(name) offsetof(REG_SET, name) - -static REG_INDEX regs_index[] = { -#if defined(WIN32) && defined(__i386__) - { "edi", REG_OFFSET(Edi), 4}, - { "esi", REG_OFFSET(Esi), 4}, - { "ebp", REG_OFFSET(Ebp), 4}, - { "esp", REG_OFFSET(Esp), 4}, - { "ebx", REG_OFFSET(Ebx), 4}, - { "edx", REG_OFFSET(Edx), 4}, - { "ecx", REG_OFFSET(Ecx), 4}, - { "eax", REG_OFFSET(Eax), 4}, - { "eflags", REG_OFFSET(EFlags), 4}, - { "eip", REG_OFFSET(Eip), 4}, - { "cs", REG_OFFSET(SegCs), 4}, - { "ss", REG_OFFSET(SegSs), 4}, -#elif defined(__APPLE__) && defined(__i386__) - { "edi", REG_OFFSET(__edi), 4}, - { "esi", REG_OFFSET(__esi), 4}, - { "ebp", REG_OFFSET(__ebp), 4}, - { "esp", REG_OFFSET(__esp), 4}, - { "ebx", REG_OFFSET(__ebx), 4}, - { "edx", REG_OFFSET(__edx), 4}, - { "ecx", REG_OFFSET(__ecx), 4}, - { "eax", REG_OFFSET(__eax), 4}, - { "eflags", REG_OFFSET(__eflags), 4}, - { "eip", REG_OFFSET(__eip), 4}, -#elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(__i386__) - { "edi", REG_OFFSET(r_edi), 4}, - { "esi", REG_OFFSET(r_esi), 4}, - { "ebp", REG_OFFSET(r_ebp), 4}, - { "esp", REG_OFFSET(r_esp), 4}, - { "ebx", REG_OFFSET(r_ebx), 4}, - { "edx", REG_OFFSET(r_edx), 4}, - { "ecx", REG_OFFSET(r_ecx), 4}, - { "eax", REG_OFFSET(r_eax), 4}, - { "eflags", REG_OFFSET(r_eflags), 4}, - { "eip", REG_OFFSET(r_eip), 4}, -#elif defined(__x86_64__) - { "rax", REG_OFFSET(rax), 8}, - { "rbx", REG_OFFSET(rbx), 8}, - { "rcx", REG_OFFSET(rcx), 8}, - { "rdx", REG_OFFSET(rdx), 8}, - { "rsi", REG_OFFSET(rsi), 8}, - { "rdi", REG_OFFSET(rdi), 8}, - { "r8", REG_OFFSET(r8), 8}, - { "r9", REG_OFFSET(r9), 8}, - { "r10", REG_OFFSET(r10), 8}, - { "r11", REG_OFFSET(r11), 8}, - { "r12", REG_OFFSET(r12), 8}, - { "r13", REG_OFFSET(r13), 8}, - { "r14", REG_OFFSET(r14), 8}, - { "r15", REG_OFFSET(r15), 8}, - { "rbp", REG_OFFSET(rbp), 8}, - { "rsp", REG_OFFSET(rsp), 8}, - { "rip", REG_OFFSET(rip), 8}, - { "eflags", REG_OFFSET(eflags), 4}, - { "cs", REG_OFFSET(cs), 4}, - { "ss", REG_OFFSET(ss), 4}, - { "ds", REG_OFFSET(ds), 4}, - { "es", REG_OFFSET(es), 4}, - { "fs", REG_OFFSET(fs), 4}, - { "gs", REG_OFFSET(gs), 4}, - { "fs_base", REG_OFFSET(fs_base), 4}, - { "gs_base", REG_OFFSET(gs_base), 4}, -#elif defined(__i386__) - { "edi", REG_OFFSET(edi), 4}, - { "esi", REG_OFFSET(esi), 4}, - { "ebp", REG_OFFSET(ebp), 4}, - { "esp", REG_OFFSET(esp), 4}, - { "ebx", REG_OFFSET(ebx), 4}, - { "edx", REG_OFFSET(edx), 4}, - { "ecx", REG_OFFSET(ecx), 4}, - { "eax", REG_OFFSET(eax), 4}, - { "eflags", REG_OFFSET(eflags), 4}, - { "eip", REG_OFFSET(eip), 4}, -#else -# error "Unknown CPU" -#endif - { NULL, 0, 0}, -}; - -#endif /* _WRS_KERNEL */ - static short endianess_test = 0x0201; #define BIG_ENDIAN_DATA (*(char *)&endianess_test == 0x02) -static void write_context(OutputStream * out, char * id, Context * ctx, REG_INDEX * idx) { +static void write_context(OutputStream * out, char * id, Context * ctx, int frame, RegisterDefinition * reg_def) { assert(!ctx->exited); write_stream(out, '{'); @@ -156,12 +54,12 @@ static void write_context(OutputStream * out, char * id, Context * ctx, REG_INDE write_stream(out, ','); json_write_string(out, "Name"); write_stream(out, ':'); - json_write_string(out, idx->regName); + json_write_string(out, reg_def->name); write_stream(out, ','); json_write_string(out, "Size"); write_stream(out, ':'); - json_write_long(out, REG_WIDTH(*idx)); + json_write_long(out, reg_def->size); write_stream(out, ','); json_write_string(out, "Readable"); @@ -189,17 +87,20 @@ static void write_context(OutputStream * out, char * id, Context * ctx, REG_INDE write_stream(out, 0); } -static int id2register(char * id, Context ** ctx, REG_INDEX ** idx) { +static int id2register(char * id, Context ** ctx, int * frame, RegisterDefinition ** reg_def) { int i; char name[64]; + RegisterDefinition * reg_defs = get_reg_definitions(); + *ctx = NULL; - *idx = NULL; + *frame = STACK_TOP_FRAME; + *reg_def = NULL; if (*id++ != 'R') { errno = ERR_INV_CONTEXT; return -1; } i = 0; - while (*id != '.') { + while (*id != '.' && *id != '@') { if (*id == 0) { errno = ERR_INV_CONTEXT; return -1; @@ -207,16 +108,30 @@ static int id2register(char * id, Context ** ctx, REG_INDEX ** idx) { name[i++] = *id++; } name[i++] = 0; + if (*id == '@') { + int n = 0; + id++; + while (*id != '.') { + if (*id >= '0' && *id <= '9') { + n = n * 10 + (*id++ - '0'); + } + else { + errno = ERR_INV_CONTEXT; + return -1; + } + } + *frame = n; + } id++; - for (i = 0; regs_index[i].regName != NULL; i++) { - if (strcmp(regs_index[i].regName, name) == 0) break; + for (i = 0; reg_defs[i].name != NULL; i++) { + if (strcmp(reg_defs[i].name, name) == 0) break; } - if (regs_index[i].regName == NULL) { + if (reg_defs[i].name == NULL) { errno = ERR_INV_CONTEXT; return -1; } *ctx = id2ctx(id); - *idx = regs_index + i; + *reg_def = reg_defs + i; if (*ctx == NULL) { errno = ERR_INV_CONTEXT; return -1; @@ -231,20 +146,21 @@ static int id2register(char * id, Context ** ctx, REG_INDEX ** idx) { static void command_get_context(char * token, Channel * c) { int err = 0; char id[256]; + int frame = 0; Context * ctx = NULL; - REG_INDEX * idx = NULL; + RegisterDefinition * reg_def = NULL; json_read_string(&c->inp, id, sizeof(id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); - if (id2register(id, &ctx, &idx) < 0) err = errno; + if (id2register(id, &ctx, &frame, ®_def) < 0) err = errno; write_stringz(&c->out, "R"); write_stringz(&c->out, token); write_errno(&c->out, err); if (err == 0) { - write_context(&c->out, id, ctx, idx); + write_context(&c->out, id, ctx, frame, reg_def); } else { write_stringz(&c->out, "null"); @@ -254,32 +170,50 @@ static void command_get_context(char * token, Channel * c) { static void command_get_children(char * token, Channel * c) { char id[256]; - pid_t pid, parent; + Context * ctx = NULL; + int frame = 0; + StackFrame * frame_info = NULL; + int err = 0; json_read_string(&c->inp, id, sizeof(id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); - pid = id2pid(id, &parent); + if (is_stack_frame_id(id, &ctx, &frame)) { + if (get_frame_info(ctx, frame, &frame_info) < 0) err = errno; + } + else { + pid_t pid, parent; + pid = id2pid(id, &parent); + if (pid != 0 && parent != 0) ctx = context_find_from_pid(pid); + frame = STACK_TOP_FRAME; + } write_stringz(&c->out, "R"); write_stringz(&c->out, token); - write_errno(&c->out, 0); + write_errno(&c->out, err); write_stream(&c->out, '['); - if (pid != 0 && parent != 0) { - Context * ctx = context_find_from_pid(pid); + if (err == 0 && ctx != NULL && context_has_state(ctx)) { if (ctx != NULL) { + int cnt = 0; char t_id[128]; - REG_INDEX * idx = regs_index; + RegisterDefinition * reg_def; strcpy(t_id, thread_id(ctx)); - while (idx->regName != NULL) { - char r_id[128]; - if (idx != regs_index) write_stream(&c->out, ','); - snprintf(r_id, sizeof(r_id), "R%s.%s", idx->regName, t_id); - json_write_string(&c->out, r_id); - idx ++; + for (reg_def = get_reg_definitions(); reg_def->name != NULL; reg_def++) { + if (frame == STACK_TOP_FRAME || read_reg_value(reg_def, frame_info, NULL) == 0) { + char r_id[128]; + if (cnt > 0) write_stream(&c->out, ','); + if (frame == STACK_TOP_FRAME) { + snprintf(r_id, sizeof(r_id), "R%s.%s", reg_def->name, t_id); + } + else { + snprintf(r_id, sizeof(r_id), "R%s@%d.%s", reg_def->name, frame, t_id); + } + json_write_string(&c->out, r_id); + cnt++; + } } } } @@ -303,23 +237,35 @@ static void send_event_register_changed(Channel * c, char * id) { static void command_get(char * token, Channel * c) { int err = 0; char id[256]; + int frame = 0; Context * ctx = NULL; - REG_INDEX * idx = NULL; + RegisterDefinition * reg_def = NULL; + char * data = NULL; json_read_string(&c->inp, id, sizeof(id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); - if (id2register(id, &ctx, &idx) < 0) err = errno; + if (id2register(id, &ctx, &frame, ®_def) < 0) err = errno; else if (!ctx->intercepted) err = ERR_IS_RUNNING; + if (!err) { + if (is_top_frame(ctx, frame)) { + data = (char *)&ctx->regs + reg_def->offset; + } + else { + StackFrame * info = NULL; + if (get_frame_info(ctx, frame, &info)) err = errno; + else if (read_reg_value(reg_def, info, NULL) < 0) err = errno; + else data = (char *)&info->regs + reg_def->offset; + } + } + write_stringz(&c->out, "R"); write_stringz(&c->out, token); write_errno(&c->out, err); if (err == 0) { - char * data = (char *)&ctx->regs + idx->regOff; - int size = REG_WIDTH(*idx); - json_write_binary(&c->out, data, size); + json_write_binary(&c->out, data, reg_def->size); write_stream(&c->out, 0); } else { @@ -334,8 +280,9 @@ static void command_set(char * token, Channel * c) { char val[256]; int val_len = 0; JsonReadBinaryState state; + int frame = 0; Context * ctx = NULL; - REG_INDEX * idx = NULL; + RegisterDefinition * reg_def = NULL; json_read_string(&c->inp, id, sizeof(id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); @@ -349,12 +296,13 @@ static void command_set(char * token, Channel * c) { if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); - if (id2register(id, &ctx, &idx) < 0) err = errno; + if (id2register(id, &ctx, &frame, ®_def) < 0) err = errno; + else if (!is_top_frame(ctx, frame)) err = ERR_INV_CONTEXT; else if (!ctx->intercepted) err = ERR_IS_RUNNING; if (err == 0) { - char * data = (char *)&ctx->regs + idx->regOff; - int size = REG_WIDTH(*idx); + char * data = (char *)&ctx->regs + reg_def->offset; + int size = reg_def->size; if (val_len != size) { err = ERR_INV_DATA_SIZE; } @@ -374,7 +322,9 @@ static void command_set(char * token, Channel * c) { struct Location { char id[256]; Context * ctx; - REG_INDEX * idx; + int frame; + StackFrame * frame_info; + RegisterDefinition * reg_def; unsigned offs; unsigned size; }; @@ -384,7 +334,7 @@ static Location * buf = NULL; static int buf_pos = 0; static int buf_len = 0; -static int read_location_list(InputStream * inp) { +static int read_location_list(InputStream * inp, int setm) { int err = 0; int ch = read_stream(inp); @@ -417,14 +367,20 @@ static int read_location_list(InputStream * inp) { buf = (Location *)loc_realloc(buf, buf_len * sizeof(Location)); } loc = buf + buf_pos++; + memset(loc, 0, sizeof(Location)); json_read_string(inp, loc->id, sizeof(loc->id)); if (read_stream(inp) != ',') exception(ERR_JSON_SYNTAX); loc->offs = (unsigned)json_read_ulong(inp); if (read_stream(inp) != ',') exception(ERR_JSON_SYNTAX); loc->size = (unsigned)json_read_ulong(inp); if (read_stream(inp) != ']') exception(ERR_JSON_SYNTAX); - if (id2register(loc->id, &loc->ctx, &loc->idx) < 0) err = errno; + if (id2register(loc->id, &loc->ctx, &loc->frame, &loc->reg_def) < 0) err = errno; else if (!loc->ctx->intercepted) err = ERR_IS_RUNNING; + if (!err && !is_top_frame(loc->ctx, loc->frame)) { + if (setm) err = ERR_INV_CONTEXT; + else if (get_frame_info(loc->ctx, loc->frame, &loc->frame_info) < 0) err = errno; + else if (read_reg_value(loc->reg_def, loc->frame_info, NULL) < 0) err = errno; + } } ch = read_stream(inp); if (ch == ',') continue; @@ -437,7 +393,7 @@ static int read_location_list(InputStream * inp) { } static void command_getm(char * token, Channel * c) { - int err = read_location_list(&c->inp); + int err = read_location_list(&c->inp, 0); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); @@ -450,7 +406,9 @@ static void command_getm(char * token, Channel * c) { json_write_binary_start(&state, &c->out, -1); for (i = 0; i < buf_pos; i++) { Location * l = buf + i; - char * data = (char *)&l->ctx->regs + l->idx->regOff + l->offs; + char * data = l->frame_info == NULL ? + (char *)&l->ctx->regs + l->reg_def->offset + l->offs : + (char *)&l->frame_info->regs + l->reg_def->offset + l->offs; json_write_binary_data(&state, data, l->size); } json_write_binary_end(&state); @@ -466,13 +424,15 @@ static void command_setm(char * token, Channel * c) { int i = 0; char tmp[256]; JsonReadBinaryState state; - int err = read_location_list(&c->inp); + int err = read_location_list(&c->inp, 1); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); json_read_binary_start(&state, &c->inp); for (i = 0; i < buf_pos; i++) { unsigned rd_done = 0; Location * l = buf + i; - char * data = (char *)&l->ctx->regs + l->idx->regOff + l->offs; + char * data = l->frame_info == NULL ? + (char *)&l->ctx->regs + l->reg_def->offset + l->offs : + (char *)&l->frame_info->regs + l->reg_def->offset + l->offs; while (rd_done < l->size) { int rd = json_read_binary_data(&state, err ? tmp : (data + rd_done), l->size - rd_done); if (rd == 0) break; diff --git a/services/registers.h b/services/registers.h index 987f8170..95d145a4 100644 --- a/services/registers.h +++ b/services/registers.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/services/runctrl.c b/services/runctrl.c index cf3861d8..eaf9794b 100644 --- a/services/runctrl.c +++ b/services/runctrl.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/services/runctrl.h b/services/runctrl.h index 43190a88..da0c3840 100644 --- a/services/runctrl.h +++ b/services/runctrl.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/services/stacktrace.c b/services/stacktrace.c index 3714f9e8..b6565f89 100644 --- a/services/stacktrace.c +++ b/services/stacktrace.c @@ -34,30 +34,21 @@ #include "stacktrace.h" #include "breakpoints.h" #include "symbols.h" +#include "dwarfframe.h" -static const char * STACKTRACE = "StackTrace"; +#define MAX_FRAMES 1000 -struct StackFrame { - ContextAddress fp; /* frame address */ - ContextAddress ip; /* istruction pointer */ - ContextAddress rp; /* return address */ - ContextAddress fn; /* address of function */ - int arg_cnt; /* number of function arguments */ - ContextAddress args;/* address of function arguments */ -}; +static const char * STACKTRACE = "StackTrace"; struct StackTrace { int error; int frame_cnt; int frame_max; - struct StackFrame frames[1]; + struct StackFrame frames[1]; /* ordered bottom to top */ }; -typedef struct StackFrame StackFrame; typedef struct StackTrace StackTrace; -static Context dump_stack_ctx; - static void add_frame(Context * ctx, StackFrame * frame) { StackTrace * stack_trace = (StackTrace *)ctx->stack_trace; if (stack_trace->frame_cnt >= stack_trace->frame_max) { @@ -74,6 +65,8 @@ static void add_frame(Context * ctx, StackFrame * frame) { #include <trcLib.h> static Context * client_ctx; +static int frame_cnt; +static ContextAddress frame_rp; static void vxworks_stack_trace_callback( void * callAdrs, /* address from which function was called */ @@ -86,213 +79,91 @@ static void vxworks_stack_trace_callback( { StackFrame f; memset(&f, 0, sizeof(f)); - f.rp = (ContextAddress)callAdrs; - f.fn = (ContextAddress)funcAdrs; - f.arg_cnt = nargs; - f.args = (ContextAddress)args; + if (frame_cnt == 0) { + f.is_top_frame = 1; + f.regs = client_ctx->regs; + memset(&f.mask, 0xff, sizeof(f.mask)); + } + else { + write_reg_value(get_PC_definition(), &f, frame_rp); + } + f.fp = (ContextAddress)args; + frame_rp = (ContextAddress)callAdrs; add_frame(client_ctx, &f); + frame_cnt++; } static int trace_stack(Context * ctx) { - int i; - StackTrace * s; client_ctx = ctx; + frame_cnt = 0; trcStack(&ctx->regs, (FUNCPTR)vxworks_stack_trace_callback, ctx->pid); - s = (StackTrace *)ctx->stack_trace; - if (s->frame_cnt == 0) { - vxworks_stack_trace_callback(NULL, 0, 0, NULL, ctx->pid, 1); - } - /* VxWorks stack trace is in reverse order - from bottom to top */ - for (i = 0; i < s->frame_cnt / 2; i++) { - StackFrame f = s->frames[i]; - s->frames[i] = s->frames[s->frame_cnt - i - 1]; - s->frames[s->frame_cnt - i - 1] = f; - } - for (i = 0; i < s->frame_cnt; i++) { - s->frames[i].ip = i == 0 ? get_regs_PC(ctx->regs) : s->frames[i - 1].rp; - } + if (frame_cnt == 0) vxworks_stack_trace_callback(NULL, 0, 0, NULL, ctx->pid, 1); return 0; } #else -static int read_mem(Context * ctx, ContextAddress address, void * buf, size_t size) { - if (ctx == &dump_stack_ctx) { - /* Tracing current thread stack */ - memmove(buf, (void *)address, size); - } - else { - if (context_read_mem(ctx, address, buf, size) < 0) return -1; - check_breakpoints_on_memory_read(ctx, address, buf, size); - } - return 0; -} - -#if defined(__i386__) || defined(__x86_64__) - -#define MAX_FRAMES 1000 - -#define JMPD08 0xeb -#define JMPD32 0xe9 -#define GRP5 0xff -#define JMPN 0x25 -#define PUSH_EBP 0x55 -#define MOV_ESP00 0x89 -#define MOV_ESP01 0xe5 -#define MOV_ESP10 0x8b -#define MOV_ESP11 0xec -#define ENTER 0xc8 -#define RET 0xc3 -#define RETADD 0xc2 -#define REXW 0x48 +static int walk_frames(Context * ctx) { + unsigned cnt = 0; + StackFrame frame; + StackFrame down; -/* - * trace_jump - resolve any JMP instructions to final destination - * - * This routine returns a pointer to the next non-JMP instruction to be - * executed if the pc were at the specified <adrs>. That is, if the instruction - * at <adrs> is not a JMP, then <adrs> is returned. Otherwise, if the - * instruction at <adrs> is a JMP, then the destination of the JMP is - * computed, which then becomes the new <adrs> which is tested as before. - * Thus we will eventually return the address of the first non-JMP instruction - * to be executed. - * - * The need for this arises because compilers may put JMPs to instructions - * that we are interested in, instead of the instruction itself. For example, - * optimizers may replace a stack pop with a JMP to a stack pop. Or in very - * UNoptimized code, the first instruction of a subroutine may be a JMP to - * a PUSH %EBP MOV %ESP %EBP, instead of a PUSH %EBP MOV %ESP %EBP (compiler - * may omit routine "post-amble" at end of parsing the routine!). We call - * this routine anytime we are looking for a specific kind of instruction, - * to help handle such cases. - * - * RETURNS: The address that a chain of branches points to. - */ -static ContextAddress trace_jump(Context * ctx, ContextAddress addr) { - int cnt = 0; - /* while instruction is a JMP, get destination adrs */ - while (cnt < 100) { - unsigned char instr; /* instruction opcode at <addr> */ - ContextAddress dest; /* Jump destination address */ - if (read_mem(ctx, addr, &instr, 1) < 0) break; - - /* If instruction is a JMP, get destination adrs */ - if (instr == JMPD08) { - signed char disp08; - if (read_mem(ctx, addr + 1, &disp08, 1) < 0) break; - dest = addr + 2 + disp08; - } - else if (instr == JMPD32) { - int disp32; - assert(sizeof(disp32) == 4); - if (read_mem(ctx, addr + 1, &disp32, 4) < 0) break; - dest = addr + 5 + disp32; - } - else if (instr == GRP5) { - ContextAddress ptr; - if (read_mem(ctx, addr + 1, &instr, 1) < 0) break; - if (instr != JMPN) break; - if (read_mem(ctx, addr + 2, &ptr, sizeof(ptr)) < 0) break; - if (read_mem(ctx, ptr, &dest, sizeof(dest)) < 0) break; - } - else { - break; + memset(&frame, 0, sizeof(frame)); + frame.is_top_frame = 1; + frame.regs = ctx->regs; + memset(&frame.mask, 0xff, sizeof(frame.mask)); + while (cnt < MAX_FRAMES) { + memset(&down, 0, sizeof(down)); +#if ENABLE_ELF + { + int error = 0; + int found = 0; + ContextAddress ip = get_regs_PC(frame.regs); + ELF_File * file = elf_list_first(ctx, ip, ip + 1); + while (error == 0 && file != NULL) { + Trap trap; + if (set_trap(&trap)) { + get_dwarf_stack_frame_info(ctx, file, &frame, &down); + if (frame.fp != 0) found = 1; + clear_trap(&trap); + } + else { + error = trap.error; + } + if (error || found) break; + file = elf_list_next(ctx); + if (file == NULL) error = errno; + } + elf_list_done(ctx); + if (error) { + errno = error; + return -1; + } } - if (dest == addr) break; - addr = dest; +#endif + if (frame.fp == 0 && crawl_stack_frame(ctx, &frame, &down) < 0) return -1; + if (cnt > 0 && frame.fp == 0) break; + add_frame(ctx, &frame); cnt++; + frame = down; } - return addr; -} -static int func_entry(unsigned char * code) { - if (*code != PUSH_EBP) return 0; - code++; - if (*code == REXW) code++; - if (code[0] == MOV_ESP00 && code[1] == MOV_ESP01) return 1; - if (code[0] == MOV_ESP10 && code[1] == MOV_ESP11) return 1; return 0; } static int trace_stack(Context * ctx) { - ContextAddress pc = get_regs_PC(ctx->regs); - ContextAddress fp = get_regs_BP(ctx->regs); - ContextAddress fp_prev = 0; - - ContextAddress addr = trace_jump(ctx, pc); - ContextAddress plt = is_plt_section(ctx, addr); - unsigned char code[5]; - unsigned cnt = 0; - - /* - * we don't have a stack frame in a few restricted but useful cases: - * 1) we are at a PUSH %EBP MOV %ESP %EBP or RET or ENTER instruction, - * 2) we are the first instruction of a subroutine (this may NOT be - * a PUSH %EBP MOV %ESP %EBP instruction with some compilers) - * 3) we are inside PLT entry - */ - - if (plt) { - fp_prev = fp; - if (addr - plt == 0) { - fp = get_regs_SP(ctx->regs); - } - else if (addr - plt < sizeof(ContextAddress) * 4) { - fp = get_regs_SP(ctx->regs) + sizeof(ContextAddress); - } - else if ((addr - plt) % (sizeof(ContextAddress) * 4) < sizeof(ContextAddress) * 2) { - fp = get_regs_SP(ctx->regs) - sizeof(ContextAddress); - } - else { - fp = get_regs_SP(ctx->regs); - } - } - else { - if (read_mem(ctx, addr - 1, code, sizeof(code)) < 0) return -1; - - if (func_entry(code + 1) || code[1] == ENTER || code[1] == RET || code[1] == RETADD) { - fp_prev = fp; - fp = get_regs_SP(ctx->regs) - sizeof(ContextAddress); - } - else if (func_entry(code)) { - fp_prev = fp; - fp = get_regs_SP(ctx->regs); - } - } - - while (cnt < MAX_FRAMES) { - ContextAddress frame[2]; - ContextAddress fp_next; - StackFrame f; - memset(&f, 0, sizeof(f)); - f.ip = pc; - if (fp == 0) { - add_frame(ctx, &f); - break; - } - if (read_mem(ctx, fp, frame, sizeof(frame)) < 0) { - memset(frame, 0, sizeof(frame)); - } - f.fp = fp; - f.rp = frame[1]; - add_frame(ctx, &f); - cnt++; - fp_next = fp_prev != 0 ? fp_prev : frame[0]; - fp_prev = 0; - if (fp_next <= fp) break; - fp = fp_next; - pc = f.rp; + int i; + StackTrace * s; + if (walk_frames(ctx) < 0) return -1; + s = (StackTrace *)ctx->stack_trace; + for (i = 0; i < s->frame_cnt / 2; i++) { + StackFrame f = s->frames[i]; + s->frames[i] = s->frames[s->frame_cnt - i - 1]; + s->frames[s->frame_cnt - i - 1] = f; } - return 0; } -#else - -#error "Unknown CPU" - -#endif - #endif static StackTrace * create_stack_trace(Context * ctx) { @@ -308,6 +179,7 @@ static StackTrace * create_stack_trace(Context * ctx) { else if (trace_stack(ctx) < 0) { stack_trace = (StackTrace *)ctx->stack_trace; stack_trace->error = errno; + /* TODO: need to save error message text in stack_trace */ } else { stack_trace = (StackTrace *)ctx->stack_trace; @@ -348,31 +220,10 @@ static int id2frame(char * id, Context ** ctx, int * frame) { return 0; } -static int id2frame_index(char * id, Context ** ctx, int * idx) { - int frame = 0; - StackTrace * s = NULL; - - if (id2frame(id, ctx, &frame) < 0) return -1; - - if (!(*ctx)->stopped) { - errno = ERR_IS_RUNNING; - return -1; - } - s = create_stack_trace(*ctx); - if (s->error != 0) { - errno = s->error; - return -1; - } - if (frame < 0 || frame >= s->frame_cnt) { - errno = ERR_INV_CONTEXT; - return -1; - } +static void write_context(OutputStream * out, char * id, Context * ctx, int level, StackFrame * frame, StackFrame * down) { + uint64_t v; + RegisterDefinition * reg_def = get_PC_definition(); - *idx = s->frame_cnt - frame - 1; - return 0; -} - -static void write_context(OutputStream * out, char * id, Context * ctx, int level, StackFrame * frame) { write_stream(out, '{'); json_write_string(out, "ID"); @@ -398,32 +249,18 @@ static void write_context(OutputStream * out, char * id, Context * ctx, int leve json_write_ulong(out, frame->fp); } - if (frame->rp) { - write_stream(out, ','); - json_write_string(out, "RP"); - write_stream(out, ':'); - json_write_ulong(out, frame->rp); - } - - if (frame->ip) { + if (read_reg_value(reg_def, frame, &v) == 0) { write_stream(out, ','); json_write_string(out, "IP"); write_stream(out, ':'); - json_write_ulong(out, frame->ip); + json_write_ulong(out, (ContextAddress)v); } - if (frame->arg_cnt) { + if (down != NULL && read_reg_value(reg_def, down, &v) == 0) { write_stream(out, ','); - json_write_string(out, "ArgsCnt"); - write_stream(out, ':'); - json_write_ulong(out, frame->arg_cnt); - } - - if (frame->args) { - write_stream(out, ','); - json_write_string(out, "ArgsAddr"); + json_write_string(out, "RP"); write_stream(out, ':'); - json_write_ulong(out, frame->args); + json_write_ulong(out, (ContextAddress)v); } write_stream(out, '}'); @@ -445,9 +282,9 @@ static void command_get_context(char * token, Channel * c) { for (i = 0; i < id_cnt; i++) { StackTrace * s = NULL; Context * ctx = NULL; - int idx = 0; + int frame = 0; if (i > 0) write_stream(&c->out, ','); - if (id2frame_index(ids[i], &ctx, &idx) < 0) { + if (id2frame(ids[i], &ctx, &frame) < 0) { err = errno; } else if (!ctx->intercepted) { @@ -456,12 +293,13 @@ static void command_get_context(char * token, Channel * c) { else { s = create_stack_trace(ctx); } - if (s == NULL || idx < 0 || idx >= s->frame_cnt) { + if (s == NULL || frame < 0 || frame >= s->frame_cnt) { write_string(&c->out, "null"); } else { - int level = s->frame_cnt - idx - 1; - write_context(&c->out, ids[i], ctx, level, s->frames + idx); + StackFrame * f = s->frames + frame; + StackFrame * d = frame > 0 ? f - 1 : NULL; + write_context(&c->out, ids[i], ctx, frame, f, d); } } write_stream(&c->out, ']'); @@ -526,32 +364,6 @@ static void delete_stack_trace(Context * ctx, void * client_data) { } } -void dump_stack_trace(void) { -#ifdef WIN32 - dump_stack_ctx.handle = OpenThread(THREAD_GET_CONTEXT, FALSE, GetCurrentThreadId()); - memset(&dump_stack_ctx.regs, 0, sizeof(dump_stack_ctx.regs)); - dump_stack_ctx.regs.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; - if (GetThreadContext(dump_stack_ctx.handle, &dump_stack_ctx.regs) == 0) { - set_win32_errno(GetLastError()); - trace(LOG_ALWAYS, "dump_stack_trace: Can't read thread registers: %d: %s", - errno, errno_to_str(errno)); - } - else { - int i; - StackTrace * s; - trace(LOG_ALWAYS, "Stack trace:"); - s = create_stack_trace(&dump_stack_ctx); - for (i = 0; i < s->frame_cnt; i++) { - StackFrame * f = s->frames + i; - trace(LOG_ALWAYS, " 0x%0*lx 0x%0*lx", sizeof(f->ip) * 2, f->ip, sizeof(f->fp) * 2, f->fp); - } - } - CloseHandle(dump_stack_ctx.handle); -#else - trace(LOG_ALWAYS, "dump_stack_trace: not implemented"); -#endif -} - int is_stack_frame_id(char * id, Context ** ctx, int * frame) { return id2frame(id, ctx, frame) == 0; } @@ -582,10 +394,10 @@ char * get_stack_frame_id(Context * ctx, int frame) { return id; } -int get_frame_info(Context * ctx, int frame, ContextAddress * ip, ContextAddress * rp, ContextAddress * fp) { - StackFrame * f; - StackTrace * s; +int get_frame_info(Context * ctx, int frame, StackFrame ** info) { + StackTrace * stack; + *info = NULL; if (ctx == NULL || !context_has_state(ctx)) { errno = ERR_INV_CONTEXT; return -1; @@ -595,42 +407,33 @@ int get_frame_info(Context * ctx, int frame, ContextAddress * ip, ContextAddress return -1; } - if (frame == STACK_TOP_FRAME && !rp && !fp && !ctx->regs_error) { - /* Optimization: no need to perform stack trace */ - if (ip) *ip = get_regs_PC(ctx->regs); - return 0; - } - - s = create_stack_trace(ctx); - if (s->error != 0) { - errno = s->error; + stack = create_stack_trace(ctx); + if (stack->error != 0) { + errno = stack->error; return -1; } if (frame == STACK_TOP_FRAME) { - frame = s->frame_cnt - 1; + frame = stack->frame_cnt - 1; } - else if (frame < 0 || frame >= s->frame_cnt) { + else if (frame < 0 || frame >= stack->frame_cnt) { errno = ERR_INV_CONTEXT; return -1; } - f = s->frames + (s->frame_cnt - frame - 1); - if (ip) *ip = f->ip; - if (rp) *rp = f->rp; - if (fp) *fp = f->fp; + *info = stack->frames + frame; return 0; } int is_top_frame(Context * ctx, int frame) { - StackTrace * s; + StackTrace * stack; if (ctx == NULL || !context_has_state(ctx)) return 0; if (!ctx->stopped) return 0; if (frame == STACK_TOP_FRAME) return 1; - s = create_stack_trace(ctx); - if (s->error != 0) return 0; - return frame == s->frame_cnt - 1; + stack = create_stack_trace(ctx); + if (stack->error != 0) return 0; + return frame == stack->frame_cnt - 1; } void ini_stack_trace_service(Protocol * proto, TCFBroadcastGroup * bcg) { @@ -644,7 +447,6 @@ void ini_stack_trace_service(Protocol * proto, TCFBroadcastGroup * bcg) { add_context_event_listener(&listener, bcg); add_command_handler(proto, STACKTRACE, "getContext", command_get_context); add_command_handler(proto, STACKTRACE, "getChildren", command_get_children); - memset(&dump_stack_ctx, 0, sizeof(dump_stack_ctx)); } #endif diff --git a/services/stacktrace.h b/services/stacktrace.h index 85b76c1d..9f309ef3 100644 --- a/services/stacktrace.h +++ b/services/stacktrace.h @@ -29,13 +29,6 @@ #if SERVICE_StackTrace /* - * Dump current stack trace into log. - * The function can be used to debug the agent itself. - */ -extern void dump_stack_trace(void); - - -/* * Check if given context ID is stack frame ID. * Return 1 if frame ID, 0 otherwise. */ @@ -48,11 +41,8 @@ extern char * get_stack_frame_id(Context * ctx, int frame); /* * Get information about given stack frame. - * ip - instruction pointer (in this frame) - * rp - return pointer (parent frame instruction pointer) - * fp - frame pointer (frame address on the thread stack) */ -extern int get_frame_info(Context * ctx, int frame, ContextAddress * ip, ContextAddress * rp, ContextAddress * fp); +extern int get_frame_info(Context * ctx, int frame, StackFrame ** info); /* * Return 1 if 'frame' is the top frame of the context. @@ -66,7 +56,7 @@ extern void ini_stack_trace_service(Protocol *, TCFBroadcastGroup *); #else /* SERVICE_StackTrace */ -#define get_frame_info(ctx, frame, ip, rp, fp) (errno = ERR_UNSUPPORTED, -1) +#define get_frame_info(ctx, frame, info) (errno = ERR_UNSUPPORTED, -1) #define is_stack_frame_id(id, ctx, frame) 0 #define get_stack_frame_id(ctx, frame) NULL #define is_top_frame(ctx, frame) (frame == STACK_TOP_FRAME) diff --git a/services/symbols_elf.c b/services/symbols_elf.c index 38977406..93718fd0 100644 --- a/services/symbols_elf.c +++ b/services/symbols_elf.c @@ -103,6 +103,7 @@ static void object2symbol(Context * ctx, ObjectInfo * obj, Symbol * sym) { case TAG_set_type: case TAG_subrange_type: case TAG_base_type: + case TAG_fund_type: case TAG_file_type: case TAG_packed_type: case TAG_thrown_type: @@ -129,7 +130,15 @@ static void object2symbol(Context * ctx, ObjectInfo * obj, Symbol * sym) { } } -static int find_in_object_tree(Context * ctx, ObjectInfo * list, ContextAddress ip, char * name, Symbol * sym) { +static int get_num_prop(Context * ctx, int frame, ObjectInfo * obj, int at, U8_T * res) { + PropertyValue v; + + if (read_and_evaluate_dwarf_object_property(ctx, frame, 0, obj, at, &v) < 0) return 0; + *res = get_numeric_property_value(&v); + return 1; +} + +static int find_in_object_tree(Context * ctx, int frame, ObjectInfo * list, ContextAddress ip, char * name, Symbol * sym) { int found = 0; ObjectInfo * obj = list; while (obj != NULL) { @@ -139,7 +148,7 @@ static int find_in_object_tree(Context * ctx, ObjectInfo * list, ContextAddress } switch (obj->mTag) { case TAG_enumeration_type: - if (find_in_object_tree(ctx, obj->mChildren, ip, name, sym)) found = 1; + if (find_in_object_tree(ctx, frame, obj->mChildren, ip, name, sym)) found = 1; break; case TAG_global_subroutine: case TAG_subroutine: @@ -147,10 +156,14 @@ static int find_in_object_tree(Context * ctx, ObjectInfo * list, ContextAddress case TAG_entry_point: case TAG_lexical_block: { - ContextAddress addr0 = elf_map_to_run_time_address(ctx, obj->mCompUnit->mFile, obj->mLowPC); - ContextAddress addr1 = obj->mHighPC - obj->mLowPC + addr0; - if (addr0 != 0 && addr0 <= ip && addr1 > ip) { - if (find_in_object_tree(ctx, obj->mChildren, ip, name, sym)) return 1; + U8_T LowPC, HighPC; + if (get_num_prop(ctx, frame, obj, AT_low_pc, &LowPC) && + get_num_prop(ctx, frame, obj, AT_high_pc, &HighPC)) { + ContextAddress addr0 = elf_map_to_run_time_address(ctx, obj->mCompUnit->mFile, (ContextAddress)LowPC); + ContextAddress addr1 = (ContextAddress)(HighPC - LowPC) + addr0; + if (addr0 != 0 && addr0 <= ip && addr1 > ip) { + if (find_in_object_tree(ctx, frame, obj->mChildren, ip, name, sym)) return 1; + } } } break; @@ -160,16 +173,16 @@ static int find_in_object_tree(Context * ctx, ObjectInfo * list, ContextAddress return found; } -static int find_in_dwarf(DWARFCache * cache, Context * ctx, char * name, ContextAddress ip, Symbol * sym) { +static int find_in_dwarf(DWARFCache * cache, Context * ctx, int frame, char * name, ContextAddress ip, Symbol * sym) { unsigned i; for (i = 0; i < cache->mCompUnitsCnt; i++) { CompUnit * unit = cache->mCompUnits[i]; ContextAddress addr0 = elf_map_to_run_time_address(ctx, unit->mFile, unit->mLowPC); ContextAddress addr1 = unit->mHighPC - unit->mLowPC + addr0; if (addr0 != 0 && addr0 <= ip && addr1 > ip) { - if (find_in_object_tree(ctx, unit->mChildren, ip, name, sym)) return 1; + if (find_in_object_tree(ctx, frame, unit->mChildren, ip, name, sym)) return 1; if (unit->mBaseTypes != NULL) { - if (find_in_object_tree(ctx, unit->mBaseTypes->mChildren, ip, name, sym)) return 1; + if (find_in_object_tree(ctx, frame, unit->mBaseTypes->mChildren, ip, name, sym)) return 1; } return 0; } @@ -245,20 +258,23 @@ int find_symbol(Context * ctx, int frame, char * name, Symbol * sym) { assert(ctx != NULL); if (error == 0 && !found) { - ContextAddress ip = 0; + U8_T ip = 0; if (frame != STACK_NO_FRAME) { - if (get_frame_info(ctx, frame, &ip, NULL, NULL) < 0) error = errno; + StackFrame * frame_info; + if (get_frame_info(ctx, frame, &frame_info) < 0) error = errno; + else if (read_reg_value(get_PC_definition(), frame_info, &ip)) error = errno; } if (error == 0) { - ELF_File * file = elf_list_first(ctx, ip, ip == 0 ? ~(ContextAddress)0 : ip + 1); + ELF_File * file = elf_list_first(ctx, (ContextAddress)ip, + ip == 0 ? ~(ContextAddress)0 : (ContextAddress)(ip + 1)); if (file == NULL) error = errno; while (error == 0 && file != NULL) { Trap trap; if (set_trap(&trap)) { DWARFCache * cache = get_dwarf_cache(file); - if (ip != 0) found = find_in_dwarf(cache, ctx, name, ip, sym); + if (ip != 0) found = find_in_dwarf(cache, ctx, frame, name, (ContextAddress)ip, sym); if (!found) found = find_in_sym_table(cache, ctx, name, sym); if (!found && ip != 0) { char * s = NULL; @@ -277,7 +293,7 @@ int find_symbol(Context * ctx, int frame, char * name, Symbol * sym) { else if (strcmp(name, "signed long long") == 0) s = "long long int"; else if (strcmp(name, "signed long long int") == 0) s = "long long int"; else if (strcmp(name, "unsigned long long") == 0) s = "unsigned long long int"; - if (s != NULL) found = find_in_dwarf(cache, ctx, s, ip, sym); + if (s != NULL) found = find_in_dwarf(cache, ctx, frame, s, (ContextAddress)ip, sym); } clear_trap(&trap); } @@ -306,7 +322,8 @@ int find_symbol(Context * ctx, int frame, char * name, Symbol * sym) { return 0; } -static void enumerate_local_vars(Context * ctx, ObjectInfo * obj, ContextAddress ip, int level, EnumerateSymbolsCallBack * call_back, void * args) { +static void enumerate_local_vars(Context * ctx, int frame, ObjectInfo * obj, + ContextAddress ip, int level, EnumerateSymbolsCallBack * call_back, void * args) { Symbol sym; while (obj != NULL) { switch (obj->mTag) { @@ -316,10 +333,14 @@ static void enumerate_local_vars(Context * ctx, ObjectInfo * obj, ContextAddress case TAG_entry_point: case TAG_lexical_block: { - ContextAddress addr0 = elf_map_to_run_time_address(ctx, obj->mCompUnit->mFile, obj->mLowPC); - ContextAddress addr1 = obj->mHighPC - obj->mLowPC + addr0; - if (addr0 != 0 && addr0 <= ip && addr1 > ip) { - enumerate_local_vars(ctx, obj->mChildren, ip, level + 1, call_back, args); + U8_T LowPC, HighPC; + if (get_num_prop(ctx, frame, obj, AT_low_pc, &LowPC) && + get_num_prop(ctx, frame, obj, AT_high_pc, &HighPC)) { + ContextAddress addr0 = elf_map_to_run_time_address(ctx, obj->mCompUnit->mFile, (ContextAddress)LowPC); + ContextAddress addr1 = (ContextAddress)(HighPC - LowPC) + addr0; + if (addr0 != 0 && addr0 <= ip && addr1 > ip) { + enumerate_local_vars(ctx, frame, obj->mChildren, ip, level + 1, call_back, args); + } } } break; @@ -338,14 +359,17 @@ static void enumerate_local_vars(Context * ctx, ObjectInfo * obj, ContextAddress int enumerate_symbols(Context * ctx, int frame, EnumerateSymbolsCallBack * call_back, void * args) { int error = 0; - ContextAddress ip = 0; + U8_T ip = 0; if (frame != STACK_NO_FRAME) { - if (get_frame_info(ctx, frame, &ip, NULL, NULL) < 0) error = errno; + StackFrame * frame_info; + if (get_frame_info(ctx, frame, &frame_info) < 0) error = errno; + else if (read_reg_value(get_PC_definition(), frame_info, &ip)) error = errno; } if (error == 0) { - ELF_File * file = elf_list_first(ctx, ip, ip == 0 ? ~(ContextAddress)0 : ip + 1); + ELF_File * file = elf_list_first(ctx, (ContextAddress)ip, + ip == 0 ? ~(ContextAddress)0 : (ContextAddress)(ip + 1)); if (file == NULL) error = errno; while (error == 0 && file != NULL) { Trap trap; @@ -358,7 +382,7 @@ int enumerate_symbols(Context * ctx, int frame, EnumerateSymbolsCallBack * call_ ContextAddress addr0 = elf_map_to_run_time_address(ctx, unit->mFile, unit->mLowPC); ContextAddress addr1 = unit->mHighPC - unit->mLowPC + addr0; if (addr0 != 0 && addr0 <= ip && addr1 > ip) { - enumerate_local_vars(ctx, unit->mChildren, ip, 0, call_back, args); + enumerate_local_vars(ctx, frame, unit->mChildren, (ContextAddress)ip, 0, call_back, args); break; } } @@ -465,7 +489,7 @@ int id2symbol(char * id, Symbol * sym) { if (*p == '.') p++; dev = read_hex(&p); if (*p == '.') p++; - ino = read_hex(&p); + ino = (ino_t)read_hex(&p); if (*p == '.') p++; mtime = read_hex(&p); if (*p == '.') p++; @@ -609,14 +633,6 @@ static ObjectInfo * get_object_type(ObjectInfo * obj) { return NULL; } -static int get_num_prop(Context * ctx, int frame, ObjectInfo * obj, int at, U8_T * res) { - PropertyValue v; - - if (read_and_evaluate_dwarf_object_property(ctx, frame, 0, obj, at, &v) < 0) return 0; - *res = get_numeric_property_value(&v); - return 1; -} - static U8_T get_object_length(Context * ctx, int frame, ObjectInfo * obj) { U8_T x, y; @@ -650,6 +666,7 @@ int get_symbol_type(const Symbol * sym, Symbol * type) { } int get_symbol_type_class(const Symbol * sym, int * type_class) { + U8_T x; if (LOC(sym)->pointer) { *type_class = LOC(sym)->size == 0 ? TYPE_CLASS_POINTER : TYPE_CLASS_ARRAY; return 0; @@ -687,25 +704,70 @@ int get_symbol_type_class(const Symbol * sym, int * type_class) { *type_class = TYPE_CLASS_COMPOSITE; return 0; case TAG_base_type: - switch (obj->mEncoding) { - case ATE_address: - *type_class = TYPE_CLASS_POINTER; + if (get_num_prop(sym->ctx, STACK_NO_FRAME, obj, AT_encoding, &x)) { + switch ((int)x) { + case ATE_address: + *type_class = TYPE_CLASS_POINTER; + return 0; + case ATE_boolean: + *type_class = TYPE_CLASS_INTEGER; + return 0; + case ATE_float: + *type_class = TYPE_CLASS_REAL; + return 0; + case ATE_signed: + case ATE_signed_char: + *type_class = TYPE_CLASS_INTEGER; + return 0; + case ATE_unsigned: + case ATE_unsigned_char: + *type_class = TYPE_CLASS_CARDINAL; + return 0; + } + } + *type_class = TYPE_CLASS_UNKNOWN; + return 0; + case TAG_fund_type: + switch (obj->mFundType) { + case FT_boolean: + *type_class = TYPE_CLASS_INTEGER; return 0; - case ATE_boolean: + case FT_char: *type_class = TYPE_CLASS_INTEGER; return 0; - case ATE_float: + case FT_dbl_prec_float: + case FT_ext_prec_float: + case FT_float: *type_class = TYPE_CLASS_REAL; return 0; - case ATE_signed: - case ATE_signed_char: + case FT_signed_char: + case FT_signed_integer: + case FT_signed_long: + case FT_signed_short: + case FT_short: + case FT_integer: + case FT_long: *type_class = TYPE_CLASS_INTEGER; return 0; - case ATE_unsigned: - case ATE_unsigned_char: + case FT_unsigned_char: + case FT_unsigned_integer: + case FT_unsigned_long: + case FT_unsigned_short: + *type_class = TYPE_CLASS_CARDINAL; + return 0; + case FT_pointer: + *type_class = TYPE_CLASS_POINTER; + return 0; + case FT_void: *type_class = TYPE_CLASS_CARDINAL; return 0; + case FT_label: + case FT_complex: + case FT_dbl_prec_complex: + case FT_ext_prec_complex: + break; } + *type_class = TYPE_CLASS_UNKNOWN; return 0; case TAG_subrange_type: case TAG_packed_type: @@ -1006,9 +1068,14 @@ int get_symbol_address(const Symbol * sym, int frame, ContextAddress * address) if (unpack(sym) < 0) return -1; if (obj != NULL && obj->mTag != TAG_member) { U8_T v; - if (!get_num_prop(sym->ctx, frame, obj, AT_location, &v)) return -1; - *address = (ContextAddress)v; - return 0; + if (get_num_prop(sym->ctx, frame, obj, AT_location, &v)) { + *address = (ContextAddress)v; + return 0; + } + if (get_num_prop(sym->ctx, frame, obj, AT_low_pc, &v)) { + *address = (ContextAddress)v; + return 0; + } } if (sym32 != NULL) { switch (ELF32_ST_TYPE(sym32->st_info)) { diff --git a/services/symbols_win32.c b/services/symbols_win32.c index bde98853..ce3752b9 100644 --- a/services/symbols_win32.c +++ b/services/symbols_win32.c @@ -18,7 +18,7 @@ #include "config.h" -#if SERVICE_Symbols && defined(_MSC_VER) +#if SERVICE_Symbols && defined(_MSC_VER) && !ENABLE_ELF #include <errno.h> #include <assert.h> @@ -106,7 +106,7 @@ typedef struct SymbolCacheEntry { int error; } SymbolCacheEntry; -#define SYMBOL_CACHE_SIZE 101 +#define SYMBOL_CACHE_SIZE 153 static SymbolCacheEntry symbol_cache[SYMBOL_CACHE_SIZE]; static char * tmp_buf = NULL; @@ -138,9 +138,11 @@ static size_t add_to_sym_buf(Symbol * sym) { static int get_stack_frame(Context * ctx, int frame, IMAGEHLP_STACK_FRAME * stack_frame) { memset(stack_frame, 0, sizeof(IMAGEHLP_STACK_FRAME)); if (frame != STACK_NO_FRAME && ctx->parent != NULL) { - ContextAddress ip = 0; - if (get_frame_info(ctx, frame, &ip, NULL, NULL) < 0) return -1; - stack_frame->InstructionOffset = ip; + uint64_t v = 0; + StackFrame * frame_info; + if (get_frame_info(ctx, frame, &frame_info) < 0) return -1; + if (read_reg_value(get_PC_definition(), frame_info, &v) < 0) return -1; + stack_frame->InstructionOffset = v; } return 0; } @@ -694,9 +696,9 @@ int get_symbol_address(const Symbol * sym, int frame, ContextAddress * addr) { *addr = (ContextAddress)info->Address; if ((info->Flags & SYMFLAG_FRAMEREL) || (info->Flags & SYMFLAG_REGREL)) { - ContextAddress fp = 0; - if (get_frame_info(sym->ctx, frame, NULL, NULL, &fp) < 0) return -1; - *addr += fp; + StackFrame * frame_info; + if (get_frame_info(sym->ctx, frame, &frame_info) < 0) return -1; + *addr += frame_info->fp - sizeof(ContextAddress) * 2; } return 0; diff --git a/services/sysmon.c b/services/sysmon.c index b371f077..081cc60e 100644 --- a/services/sysmon.c +++ b/services/sysmon.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/services/sysmon.h b/services/sysmon.h index a7b56556..20732caa 100644 --- a/services/sysmon.h +++ b/services/sysmon.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. diff --git a/services/tcf_elf.c b/services/tcf_elf.c index 53694dff..37176b92 100644 --- a/services/tcf_elf.c +++ b/services/tcf_elf.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. @@ -66,12 +66,12 @@ static void elf_dispose(ELF_File * file) { } if (file->fd >= 0) close(file->fd); if (file->sections != NULL) { +#ifdef USE_MMAP for (n = 0; n < file->section_cnt; n++) { ELF_Section * s = file->sections + n; -#ifdef USE_MMAP if (s->mmap_addr != NULL) munmap(s->mmap_addr, s->mmap_size); -#endif } +#endif loc_free(file->sections); } loc_free(file->pheaders); @@ -331,7 +331,7 @@ ELF_File * elf_open(char * file_name) { sec->type = shdr.sh_type; sec->offset = shdr.sh_offset; sec->size = shdr.sh_size; - sec->flags = shdr.sh_flags; + sec->flags = (U4_T)shdr.sh_flags; sec->addr = shdr.sh_addr; sec->link = shdr.sh_link; sec->info = shdr.sh_info; @@ -366,7 +366,7 @@ ELF_File * elf_open(char * file_name) { p->file_size = phdr.p_filesz; p->mem_size = phdr.p_memsz; p->flags = phdr.p_flags; - p->align = phdr.p_align; + p->align = (U4_T)phdr.p_align; cnt++; } } @@ -425,6 +425,21 @@ int elf_load(ELF_Section * s) { #endif } +U8_T elf_read_section(ELF_Section * section, uintptr_t offset, size_t size) { + U1_T buf[8]; + if (section->data == NULL && elf_load(section) < 0) exception(errno); + memcpy(buf, (U1_T *)section->data + offset, size); + if (section->file->byte_swap) swap_bytes(buf, size); + switch (size) { + case 1: return *(U1_T *)buf; + case 2: return *(U2_T *)buf; + case 4: return *(U4_T *)buf; + case 8: return *(U8_T *)buf; + } + exception(ERR_INV_DATA_SIZE); + return 0; +} + void elf_close(ELF_File * file) { assert(file != NULL); assert(file->ref_cnt > 0); diff --git a/services/tcf_elf.h b/services/tcf_elf.h index a16a639b..adaabaf7 100644 --- a/services/tcf_elf.h +++ b/services/tcf_elf.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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. @@ -172,6 +172,8 @@ typedef struct Elf32_Shdr { Elf32_Word sh_entsize; } Elf32_Shdr; +#define SHF_ALLOC 0x00000002 + typedef struct Elf32_Phdr { Elf32_Word p_type; Elf32_Off p_offset; @@ -399,6 +401,12 @@ extern void elf_list_done(Context * ctx); extern int elf_load(ELF_Section * section); /* + * Read a binary value of given size from ELF section, adjust endianness if necessary +. + */ +extern U8_T elf_read_section(ELF_Section * section, uintptr_t offset, size_t size); + +/* * Register ELF file close callback. * The callback is called each time an ELF file data is about to be disposed. * Service implementation can use the callback to deallocate |