Skip to main content
summaryrefslogtreecommitdiffstats
path: root/agent/tcf
diff options
context:
space:
mode:
Diffstat (limited to 'agent/tcf')
-rw-r--r--agent/tcf/framework/cpudefs-ext.h (renamed from agent/tcf/machine/cpudefs-ext.h)2
-rw-r--r--agent/tcf/framework/cpudefs.c3
-rw-r--r--agent/tcf/framework/mdep-threads.h2
-rw-r--r--agent/tcf/framework/pid-hash.h (renamed from agent/tcf/system/pid-hash.h)0
-rw-r--r--agent/tcf/machine/i386/cpudefs-mdep.h1
-rw-r--r--agent/tcf/machine/i386/elf-mdep.h49
-rw-r--r--agent/tcf/machine/i686/cpudefs-mdep.h1
-rw-r--r--agent/tcf/machine/x86_64/cpudefs-mdep.h422
-rw-r--r--agent/tcf/main/test.c2
-rw-r--r--agent/tcf/services/dwarfreloc-ext.h (renamed from agent/tcf/machine/elf-mdep.h)2
-rw-r--r--agent/tcf/services/dwarfreloc.c2
-rw-r--r--agent/tcf/services/linenumbers_win32.c4
-rw-r--r--agent/tcf/services/symbols_win32.c4
-rw-r--r--agent/tcf/system/Cygwin/regset.h23
-rw-r--r--agent/tcf/system/Darwin/context-darwin.c663
-rw-r--r--agent/tcf/system/Darwin/regset.h28
-rw-r--r--agent/tcf/system/FreeBSD/context-freebsd.c659
-rw-r--r--agent/tcf/system/FreeBSD/regset.h24
-rw-r--r--agent/tcf/system/GNU/Linux/context-linux.c1187
-rw-r--r--agent/tcf/system/GNU/Linux/regset.h24
-rw-r--r--agent/tcf/system/MinGW/regset.h23
-rw-r--r--agent/tcf/system/Msys/regset.h23
-rw-r--r--agent/tcf/system/VxWorks/context-vxworks.c782
-rw-r--r--agent/tcf/system/VxWorks/context-vxworks.h28
-rw-r--r--agent/tcf/system/VxWorks/regset.h23
-rw-r--r--agent/tcf/system/Windows/context-win32.c1434
-rw-r--r--agent/tcf/system/Windows/context-win32.h36
-rw-r--r--agent/tcf/system/Windows/pthreads-win32.c311
-rw-r--r--agent/tcf/system/Windows/pthreads-win32.h56
-rw-r--r--agent/tcf/system/Windows/regset.h23
-rw-r--r--agent/tcf/system/Windows/windbgcache.c405
-rw-r--r--agent/tcf/system/Windows/windbgcache.h251
32 files changed, 11 insertions, 6486 deletions
diff --git a/agent/tcf/machine/cpudefs-ext.h b/agent/tcf/framework/cpudefs-ext.h
index ca23b4d5..cc3f788c 100644
--- a/agent/tcf/machine/cpudefs-ext.h
+++ b/agent/tcf/framework/cpudefs-ext.h
@@ -20,7 +20,7 @@
* If it is not the case, this file needs to be substituted with alternative implementation.
*/
-#include <cpudefs-mdep.h>
+#include <tcf/cpudefs-mdep.h>
struct RegisterData {
REG_SET data;
diff --git a/agent/tcf/framework/cpudefs.c b/agent/tcf/framework/cpudefs.c
index 5d9c5f5d..e31d922a 100644
--- a/agent/tcf/framework/cpudefs.c
+++ b/agent/tcf/framework/cpudefs.c
@@ -30,7 +30,8 @@
#include <tcf/framework/myalloc.h>
#include <tcf/framework/exceptions.h>
#include <tcf/services/symbols.h>
-#include <tcf/machine/cpudefs-ext.h>
+
+#include <tcf/framework/cpudefs-ext.h>
int read_reg_value(StackFrame * frame, RegisterDefinition * reg_def, uint64_t * value) {
uint8_t buf[8];
diff --git a/agent/tcf/framework/mdep-threads.h b/agent/tcf/framework/mdep-threads.h
index 1fe0a388..8247d613 100644
--- a/agent/tcf/framework/mdep-threads.h
+++ b/agent/tcf/framework/mdep-threads.h
@@ -26,7 +26,7 @@
#ifdef DISABLE_PTHREADS_WIN32
# include <pthread.h>
#else
-# include <tcf/system/Windows/pthreads-win32.h>
+# include <system/Windows/tcf/pthreads-win32.h>
#endif
#elif defined(_WRS_KERNEL)
diff --git a/agent/tcf/system/pid-hash.h b/agent/tcf/framework/pid-hash.h
index 4843ec8c..4843ec8c 100644
--- a/agent/tcf/system/pid-hash.h
+++ b/agent/tcf/framework/pid-hash.h
diff --git a/agent/tcf/machine/i386/cpudefs-mdep.h b/agent/tcf/machine/i386/cpudefs-mdep.h
deleted file mode 100644
index b51cedb5..00000000
--- a/agent/tcf/machine/i386/cpudefs-mdep.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "tcf/machine/x86_64/cpudefs-mdep.h"
diff --git a/agent/tcf/machine/i386/elf-mdep.h b/agent/tcf/machine/i386/elf-mdep.h
deleted file mode 100644
index 3ab791c7..00000000
--- a/agent/tcf/machine/i386/elf-mdep.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-/*
- * This module provides CPU specific ELF definitions for X86.
- */
-
-#define R_386_NONE 0
-#define R_386_32 1
-#define R_386_PC32 2
-
-static void elf_relocate(void) {
- if (relocs->type == SHT_REL) {
- U4_T x = *(U4_T *)((char *)section->data + reloc_offset);
- if (section->file->type != ET_REL) str_exception(ERR_INV_FORMAT, "Invalid relocation record");
- if (section->file->byte_swap) SWAP(x);
- assert(reloc_addend == 0);
- reloc_addend = x;
- }
- switch (reloc_type) {
- case R_386_NONE:
- *destination_section = NULL;
- break;
- case R_386_32:
- if (data_size < 4) str_exception(ERR_INV_FORMAT, "Invalid relocation record");
- *(U4_T *)data_buf = (U4_T)(sym_value + reloc_addend);
- if (section->file->byte_swap) SWAP(*(U4_T *)data_buf);
- break;
- case R_386_PC32:
- if (data_size < 4) str_exception(ERR_INV_FORMAT, "Invalid relocation record");
- *(U4_T *)data_buf = (U4_T)(section->addr + reloc_offset + sym_value + reloc_addend);
- if (section->file->byte_swap) SWAP(*(U4_T *)data_buf);
- break;
- default:
- str_exception(ERR_INV_FORMAT, "Unsupported relocation type");
- }
-}
diff --git a/agent/tcf/machine/i686/cpudefs-mdep.h b/agent/tcf/machine/i686/cpudefs-mdep.h
deleted file mode 100644
index b51cedb5..00000000
--- a/agent/tcf/machine/i686/cpudefs-mdep.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "tcf/machine/x86_64/cpudefs-mdep.h"
diff --git a/agent/tcf/machine/x86_64/cpudefs-mdep.h b/agent/tcf/machine/x86_64/cpudefs-mdep.h
deleted file mode 100644
index caee888b..00000000
--- a/agent/tcf/machine/x86_64/cpudefs-mdep.h
+++ /dev/null
@@ -1,422 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-/*
- * This module provides CPU specific definitions for X86.
- */
-
-#ifdef _WRS_KERNEL
-# if CPU_FAMILY == SIMNT || CPU_FAMILY == I80X86
-# define __i386__ 1
-# define eip pc
-# undef BREAK_INST
-# endif
-# include <tcf/system/VxWorks/context-vxworks.h>
-#endif
-
-#if defined(__i386__) || defined(__x86_64__)
-
-#include <regset.h>
-
-#define REG_OFFSET(name) offsetof(REG_SET, name)
-
-RegisterDefinition regs_index[] = {
-#if defined(WIN32) && defined(__i386__)
-# define REG_SP Esp
-# define REG_BP Ebp
-# define REG_IP Eip
- { "eax", REG_OFFSET(Eax), 4, 0, 0 },
- { "ebx", REG_OFFSET(Ebx), 4, 3, 3 },
- { "ecx", REG_OFFSET(Ecx), 4, 1, 1 },
- { "edx", REG_OFFSET(Edx), 4, 2, 2 },
- { "esp", REG_OFFSET(Esp), 4, 4, 4 },
- { "ebp", REG_OFFSET(Ebp), 4, 5, 5 },
- { "esi", REG_OFFSET(Esi), 4, 6, 6 },
- { "edi", REG_OFFSET(Edi), 4, 7, 7 },
- { "eip", REG_OFFSET(Eip), 4, 8, 8 },
- { "eflags", REG_OFFSET(EFlags), 4, 9, 9 },
- { "cs", REG_OFFSET(SegCs), 4, -1, -1 },
- { "ss", REG_OFFSET(SegSs), 4, -1, -1 },
-
- { "ax", REG_OFFSET(Eax), 2, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 0 },
- { "al", REG_OFFSET(Eax), 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 12 },
- { "ah", REG_OFFSET(Eax) + 1, 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 12 },
-
- { "bx", REG_OFFSET(Ebx), 2, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 1 },
- { "bl", REG_OFFSET(Ebx), 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 15 },
- { "bh", REG_OFFSET(Ebx) + 1, 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 15 },
-
- { "cx", REG_OFFSET(Ecx), 2, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 2 },
- { "cl", REG_OFFSET(Ecx), 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 18 },
- { "ch", REG_OFFSET(Ecx) + 1, 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 18 },
-
- { "dx", REG_OFFSET(Edx), 2, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 3 },
- { "dl", REG_OFFSET(Edx), 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 21 },
- { "dh", REG_OFFSET(Edx) + 1, 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 21 },
-
- { "fpu", 0, 0, -1, -1, 0, 0, 1, 1 },
-
- { "f0", REG_OFFSET(FloatSave.RegisterArea) + 0, 10, -1, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 24 },
- { "f1", REG_OFFSET(FloatSave.RegisterArea) + 10, 10, -1, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 24 },
- { "f2", REG_OFFSET(FloatSave.RegisterArea) + 20, 10, -1, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 24 },
- { "f3", REG_OFFSET(FloatSave.RegisterArea) + 30, 10, -1, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 24 },
- { "f4", REG_OFFSET(FloatSave.RegisterArea) + 40, 10, -1, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 24 },
- { "f5", REG_OFFSET(FloatSave.RegisterArea) + 50, 10, -1, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 24 },
- { "f6", REG_OFFSET(FloatSave.RegisterArea) + 60, 10, -1, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 24 },
- { "f7", REG_OFFSET(FloatSave.RegisterArea) + 70, 10, -1, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 24 },
-
- { "control", REG_OFFSET(FloatSave.ControlWord), 2, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 24 },
- { "status", REG_OFFSET(FloatSave.StatusWord), 2, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 24 },
- { "tag", REG_OFFSET(FloatSave.TagWord), 2, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, regs_index + 24 },
-
-#elif defined(__APPLE__) && defined(__i386__)
-# define REG_SP __esp
-# define REG_BP __ebp
-# define REG_IP __eip
- { "eax", REG_OFFSET(__eax), 4, 0, 0},
- { "ecx", REG_OFFSET(__ecx), 4, 1, 1},
- { "edx", REG_OFFSET(__edx), 4, 2, 2},
- { "ebx", REG_OFFSET(__ebx), 4, 3, 3},
- { "esp", REG_OFFSET(__esp), 4, 4, 4},
- { "ebp", REG_OFFSET(__ebp), 4, 5, 5},
- { "esi", REG_OFFSET(__esi), 4, 6, 6},
- { "edi", REG_OFFSET(__edi), 4, 7, 7},
- { "eip", REG_OFFSET(__eip), 4, 8, 8},
- { "eflags", REG_OFFSET(__eflags), 4, 9, 9},
-
-#elif defined(__APPLE__) && defined(__x86_64__)
-# define REG_SP __rsp
-# define REG_BP __rbp
-# define REG_IP __rip
- { "rax", REG_OFFSET(__rax), 8, 0, 0},
- { "rdx", REG_OFFSET(__rdx), 8, 1, 1},
- { "rcx", REG_OFFSET(__rcx), 8, 2, 2},
- { "rbx", REG_OFFSET(__rbx), 8, 3, 3},
- { "rsi", REG_OFFSET(__rsi), 8, 4, 4},
- { "rdi", REG_OFFSET(__rdi), 8, 5, 5},
- { "rbp", REG_OFFSET(__rbp), 8, 6, 6},
- { "rsp", REG_OFFSET(__rsp), 8, 7, 7},
- { "r8", REG_OFFSET(__r8), 8, 8, 8},
- { "r9", REG_OFFSET(__r9), 8, 9, 9},
- { "r10", REG_OFFSET(__r10), 8, 10, 10},
- { "r11", REG_OFFSET(__r11), 8, 11, 11},
- { "r12", REG_OFFSET(__r12), 8, 12, 12},
- { "r13", REG_OFFSET(__r13), 8, 13, 13},
- { "r14", REG_OFFSET(__r14), 8, 14, 14},
- { "r15", REG_OFFSET(__r15), 8, 15, 15},
- { "rip", REG_OFFSET(__rip), 8, 16, 16},
- { "eflags", REG_OFFSET(__rflags), 4, 49, -1},
-
-#elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(__i386__)
-# define REG_SP r_esp
-# define REG_BP r_ebp
-# define REG_IP r_eip
- { "eax", REG_OFFSET(r_eax), 4, 0, 0},
- { "ecx", REG_OFFSET(r_ecx), 4, 1, 1},
- { "edx", REG_OFFSET(r_edx), 4, 2, 2},
- { "ebx", REG_OFFSET(r_ebx), 4, 3, 3},
- { "esp", REG_OFFSET(r_esp), 4, 4, 4},
- { "ebp", REG_OFFSET(r_ebp), 4, 5, 5},
- { "esi", REG_OFFSET(r_esi), 4, 6, 6},
- { "edi", REG_OFFSET(r_edi), 4, 7, 7},
- { "eip", REG_OFFSET(r_eip), 4, 8, 8},
- { "eflags", REG_OFFSET(r_eflags), 4, 9, 9},
-
-#elif defined(__x86_64__)
-# define REG_SP rsp
-# define REG_BP rbp
-# define REG_IP rip
- { "rax", REG_OFFSET(rax), 8, 0, 0},
- { "rdx", REG_OFFSET(rdx), 8, 1, 1},
- { "rcx", REG_OFFSET(rcx), 8, 2, 2},
- { "rbx", REG_OFFSET(rbx), 8, 3, 3},
- { "rsi", REG_OFFSET(rsi), 8, 4, 4},
- { "rdi", REG_OFFSET(rdi), 8, 5, 5},
- { "rbp", REG_OFFSET(rbp), 8, 6, 6},
- { "rsp", REG_OFFSET(rsp), 8, 7, 7},
- { "r8", REG_OFFSET(r8), 8, 8, 8},
- { "r9", REG_OFFSET(r9), 8, 9, 9},
- { "r10", REG_OFFSET(r10), 8, 10, 10},
- { "r11", REG_OFFSET(r11), 8, 11, 11},
- { "r12", REG_OFFSET(r12), 8, 12, 12},
- { "r13", REG_OFFSET(r13), 8, 13, 13},
- { "r14", REG_OFFSET(r14), 8, 14, 14},
- { "r15", REG_OFFSET(r15), 8, 15, 15},
- { "rip", REG_OFFSET(rip), 8, 16, 16},
- { "eflags", REG_OFFSET(eflags), 4, 49, -1},
- { "es", REG_OFFSET(es), 4, 50, -1},
- { "cs", REG_OFFSET(cs), 4, 51, -1},
- { "ss", REG_OFFSET(ss), 4, 52, -1},
- { "ds", REG_OFFSET(ds), 4, 53, -1},
- { "fs", REG_OFFSET(fs), 4, 54, -1},
- { "gs", REG_OFFSET(gs), 4, 55, -1},
- { "fs_base", REG_OFFSET(fs_base), 4, 58, -1},
- { "gs_base", REG_OFFSET(gs_base), 4, 59, -1},
-
-#else
-# define REG_SP esp
-# define REG_BP ebp
-# define REG_IP eip
- { "eax", REG_OFFSET(eax), 4, 0, 0},
- { "ecx", REG_OFFSET(ecx), 4, 1, 1},
- { "edx", REG_OFFSET(edx), 4, 2, 2},
- { "ebx", REG_OFFSET(ebx), 4, 3, 3},
- { "esp", REG_OFFSET(esp), 4, 4, 4},
- { "ebp", REG_OFFSET(ebp), 4, 5, 5},
- { "esi", REG_OFFSET(esi), 4, 6, 6},
- { "edi", REG_OFFSET(edi), 4, 7, 7},
- { "eip", REG_OFFSET(eip), 4, 8, 8},
- { "eflags", REG_OFFSET(eflags), 4, 9, 9},
-
-#endif
-
- { NULL, 0, 0, 0, 0},
-};
-
-#ifndef _WRS_KERNEL
-#define JMPD08 0xeb
-#define JMPD32 0xe9
-#define PUSH_EBP 0x55
-#define ENTER 0xc8
-#define RET 0xc3
-#define RETADD 0xc2
-#endif
-#define GRP5 0xff
-#define JMPN 0x25
-#define MOVE_mr 0x89
-#define MOVE_rm 0x8b
-#define REXW 0x48
-
-static int read_stack(Context * ctx, ContextAddress addr, void * buf, size_t size) {
- if (addr == 0) {
- errno = ERR_INV_ADDRESS;
- return -1;
- }
-#ifdef _WRS_KERNEL
- {
- WIND_TCB * tcb = taskTcb(get_context_task_id(ctx));
- if (addr < (ContextAddress)tcb->pStackEnd || addr > (ContextAddress)tcb->pStackBase) {
- errno = ERR_INV_ADDRESS;
- return -1;
- }
- }
-#endif
- return context_read_mem(ctx, addr, buf, size);
-}
-
-static int read_reg(StackFrame * frame, RegisterDefinition * def, ContextAddress * addr) {
- uint64_t v = 0;
- int r = read_reg_value(frame, def, &v);
- *addr = (ContextAddress)v;
- return r;
-}
-
-/*
- * 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 (context_read_mem(ctx, addr, &instr, 1) < 0) break;
-
- /* If instruction is a JMP, get destination adrs */
- if (instr == JMPD08) {
- signed char disp08;
- if (context_read_mem(ctx, addr + 1, &disp08, 1) < 0) break;
- dest = addr + 2 + disp08;
- }
- else if (instr == JMPD32) {
- int32_t disp32 = 0;
- if (context_read_mem(ctx, addr + 1, &disp32, 4) < 0) break;
- dest = addr + 5 + disp32;
- }
- else if (instr == GRP5) {
- ContextAddress ptr;
- if (context_read_mem(ctx, addr + 1, &instr, 1) < 0) break;
- if (instr != JMPN) break;
- if (context_read_mem(ctx, addr + 2, &ptr, sizeof(ptr)) < 0) break;
- if (context_read_mem(ctx, ptr, &dest, sizeof(dest)) < 0) break;
- }
- else if (instr == MOVE_rm) {
- unsigned char modrm = 0;
- if (context_read_mem(ctx, addr + 1, &modrm, 1) < 0) break;
- if (modrm == 0xff) {
- dest = addr + 2;
- }
- else {
- 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] == MOVE_mr && code[1] == 0xe5) return 1;
- if (code[0] == MOVE_rm && code[1] == 0xec) return 1;
- return 0;
-}
-
-int crawl_stack_frame(StackFrame * frame, StackFrame * down) {
-
- static RegisterDefinition * pc_def = NULL;
- static RegisterDefinition * sp_def = NULL;
- static RegisterDefinition * bp_def = NULL;
-
- ContextAddress reg_pc = 0;
- ContextAddress reg_bp = 0;
-
- ContextAddress dwn_pc = 0;
- ContextAddress dwn_sp = 0;
- ContextAddress dwn_bp = 0;
-
- Context * ctx = frame->ctx;
-
- if (pc_def == NULL) {
- RegisterDefinition * r;
- for (r = get_reg_definitions(ctx); r->name != NULL; r++) {
- if (r->offset == offsetof(REG_SET, REG_IP)) pc_def = r;
- if (r->offset == offsetof(REG_SET, REG_SP)) sp_def = r;
- if (r->offset == offsetof(REG_SET, REG_BP)) bp_def = r;
- }
- }
-
- if (read_reg(frame, pc_def, &reg_pc) < 0) return 0;
- if (read_reg(frame, bp_def, &reg_bp) < 0) return 0;
-
- if (frame->is_top_frame) {
- /* Top frame */
- ContextAddress reg_sp = 0;
- ContextAddress addr = trace_jump(ctx, reg_pc);
-#if ENABLE_Symbols
- ContextAddress plt = is_plt_section(ctx, addr);
-#else
- ContextAddress plt = 0;
-#endif
-
- if (read_reg(frame, sp_def, &reg_sp) < 0) return 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 at 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 (context_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 if (reg_bp != 0) {
- dwn_sp = reg_bp + sizeof(ContextAddress) * 2;
- if (read_stack(ctx, reg_bp, &dwn_bp, sizeof(ContextAddress)) < 0) dwn_bp = 0;
- }
- }
- }
- else {
- if (read_stack(ctx, reg_bp, &dwn_bp, sizeof(ContextAddress)) < 0) dwn_bp = 0;
- else dwn_sp = reg_bp + sizeof(ContextAddress) * 2;
- }
-
- if (read_stack(ctx, dwn_sp - sizeof(ContextAddress), &dwn_pc, sizeof(ContextAddress)) < 0) dwn_pc = 0;
-
- if (dwn_bp < reg_bp) dwn_bp = 0;
-
- if (dwn_pc != 0) {
- if (write_reg_value(down, pc_def, dwn_pc) < 0) return -1;
- if (dwn_sp != 0 && write_reg_value(down, sp_def, dwn_sp) < 0) return -1;
- if (dwn_bp != 0 && write_reg_value(down, bp_def, dwn_bp) < 0) return -1;
- frame->fp = dwn_sp;
- }
-
- return 0;
-}
-
-RegisterDefinition * get_PC_definition(Context * ctx) {
- static RegisterDefinition * reg_def = NULL;
- if (reg_def == NULL) {
- RegisterDefinition * r;
- for (r = get_reg_definitions(ctx); r->name != NULL; r++) {
- if (r->offset == offsetof(REG_SET, REG_IP)) {
- reg_def = r;
- break;
- }
- }
- }
- return reg_def;
-}
-
-unsigned char BREAK_INST[] = { 0xcc };
-
-#else
-
-# error "Unknown CPU"
-
-#endif
diff --git a/agent/tcf/main/test.c b/agent/tcf/main/test.c
index 1c5df005..4b236850 100644
--- a/agent/tcf/main/test.c
+++ b/agent/tcf/main/test.c
@@ -33,7 +33,7 @@
#include <tcf/services/diagnostics.h>
#include <tcf/main/test.h>
#if defined(WIN32)
-# include <tcf/system/Windows/context-win32.h>
+# include <system/Windows/tcf/context-win32.h>
#endif
#ifdef __cplusplus
diff --git a/agent/tcf/machine/elf-mdep.h b/agent/tcf/services/dwarfreloc-ext.h
index 3f7d9f51..4a397112 100644
--- a/agent/tcf/machine/elf-mdep.h
+++ b/agent/tcf/services/dwarfreloc-ext.h
@@ -15,7 +15,7 @@
#define elf_relocate elf_relocate_i386
-#include <tcf/machine/i386/elf-mdep.h>
+#include <machine/i386/tcf/dwarfreloc-mdep.h>
#undef elf_relocate
static ElfRelocateFunc elf_relocate_funcs[] = {
diff --git a/agent/tcf/services/dwarfreloc.c b/agent/tcf/services/dwarfreloc.c
index 00d4d5cf..de933a2d 100644
--- a/agent/tcf/services/dwarfreloc.c
+++ b/agent/tcf/services/dwarfreloc.c
@@ -46,7 +46,7 @@ typedef struct ElfRelocateFunc {
void (*func)(void);
} ElfRelocateFunc;
-#include <tcf/machine/elf-mdep.h>
+#include <tcf/services/dwarfreloc-ext.h>
static void relocate(void * r) {
ElfRelocateFunc * func;
diff --git a/agent/tcf/services/linenumbers_win32.c b/agent/tcf/services/linenumbers_win32.c
index efdbf578..830beac5 100644
--- a/agent/tcf/services/linenumbers_win32.c
+++ b/agent/tcf/services/linenumbers_win32.c
@@ -31,8 +31,8 @@
#include <tcf/framework/context.h>
#include <tcf/framework/exceptions.h>
#include <tcf/services/linenumbers.h>
-#include <tcf/system/Windows/windbgcache.h>
-#include <tcf/system/Windows/context-win32.h>
+#include <system/Windows/tcf/windbgcache.h>
+#include <system/Windows/tcf/context-win32.h>
int line_to_address(Context * ctx, char * file, int line, int column,
LineNumbersCallBack * callback, void * user_args) {
diff --git a/agent/tcf/services/symbols_win32.c b/agent/tcf/services/symbols_win32.c
index 53ce1d60..56632517 100644
--- a/agent/tcf/services/symbols_win32.c
+++ b/agent/tcf/services/symbols_win32.c
@@ -33,8 +33,8 @@
#include <tcf/services/symbols.h>
#include <tcf/services/stacktrace.h>
#include <tcf/services/memorymap.h>
-#include <tcf/system/Windows/windbgcache.h>
-#include <tcf/system/Windows/context-win32.h>
+#include <system/Windows/tcf/windbgcache.h>
+#include <system/Windows/tcf/context-win32.h>
#if ENABLE_RCBP_TEST
# include <tcf/main/test.h>
#endif
diff --git a/agent/tcf/system/Cygwin/regset.h b/agent/tcf/system/Cygwin/regset.h
deleted file mode 100644
index 08e2895d..00000000
--- a/agent/tcf/system/Cygwin/regset.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-/*
- * This header file provides definition of REG_SET - a structure that can
- * hold values of target CPU registers.
- */
-
-#if defined(__CYGWIN__)
- typedef CONTEXT REG_SET;
-#endif
diff --git a/agent/tcf/system/Darwin/context-darwin.c b/agent/tcf/system/Darwin/context-darwin.c
deleted file mode 100644
index 50464b77..00000000
--- a/agent/tcf/system/Darwin/context-darwin.c
+++ /dev/null
@@ -1,663 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-/*
- * This module handles process/thread OS contexts and their state machine.
- */
-
-#include <tcf/config.h>
-
-#if defined(__APPLE__)
-
-#if ENABLE_DebugContext && !ENABLE_ContextProxy
-
-#include <stdlib.h>
-#include <assert.h>
-#include <errno.h>
-#include <signal.h>
-#include <sched.h>
-#include <sys/syscall.h>
-#include <sys/ptrace.h>
-#include <mach/thread_status.h>
-#include <tcf/framework/context.h>
-#include <tcf/framework/events.h>
-#include <tcf/framework/errors.h>
-#include <tcf/framework/trace.h>
-#include <tcf/framework/myalloc.h>
-#include <tcf/framework/waitpid.h>
-#include <tcf/framework/signames.h>
-#include <tcf/services/breakpoints.h>
-#include <tcf/system/Darwin/regset.h>
-
-#define WORD_SIZE 4
-
-typedef struct ContextExtensionDarwin {
- pid_t pid;
- ContextAttachCallBack * attach_callback;
- void * attach_data;
- int ptrace_flags;
- int ptrace_event;
- int syscall_enter;
- int syscall_exit;
- int syscall_id;
- ContextAddress syscall_pc;
- ContextAddress loader_state;
- int end_of_step;
- REG_SET * regs; /* copy of context registers, updated when context stops */
- ErrorReport * regs_error; /* if not NULL, 'regs' is invalid */
- int regs_dirty; /* if not 0, 'regs' is modified and needs to be saved before context is continued */
- int pending_step;
-} ContextExtensionDarwin;
-
-static size_t context_extension_offset = 0;
-
-#define EXT(ctx) ((ContextExtensionDarwin *)((char *)(ctx) + context_extension_offset))
-
-#include <tcf/system/pid-hash.h>
-
-static LINK pending_list = TCF_LIST_INIT(pending_list);
-
-static MemoryErrorInfo mem_err_info;
-
-const char * context_suspend_reason(Context * ctx) {
- static char reason[128];
-
- if (EXT(ctx)->end_of_step) return REASON_STEP;
- if (EXT(ctx)->syscall_enter) return "System Call";
- if (EXT(ctx)->syscall_exit) return "System Return";
- if (ctx->signal == SIGSTOP || ctx->signal == SIGTRAP) return REASON_USER_REQUEST;
- snprintf(reason, sizeof(reason), "Signal %d", ctx->signal);
- return reason;
-}
-
-int context_attach_self(void) {
- if (ptrace(PT_TRACE_ME, 0, 0, 0) < 0) {
- int err = errno;
- trace(LOG_ALWAYS, "error: ptrace(PT_TRACE_ME) failed: pid %d, error %d %s",
- getpid(), err, errno_to_str(err));
- errno = err;
- return -1;
- }
- return 0;
-}
-
-int context_attach(pid_t pid, ContextAttachCallBack * done, void * data, int mode) {
- Context * ctx = NULL;
-
- assert(done != NULL);
- trace(LOG_CONTEXT, "context: attaching pid %d", pid);
- if ((mode & CONTEXT_ATTACH_SELF) == 0 && ptrace(PT_ATTACH, pid, 0, 0) < 0) {
- int err = errno;
- trace(LOG_ALWAYS, "error: ptrace(PT_ATTACH) failed: pid %d, error %d %s",
- pid, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- add_waitpid_process(pid);
- ctx = create_context(pid2id(pid, 0));
- ctx->mem = ctx;
- ctx->mem_access |= MEM_ACCESS_INSTRUCTION;
- ctx->mem_access |= MEM_ACCESS_DATA;
- ctx->mem_access |= MEM_ACCESS_USER;
- ctx->big_endian = big_endian_host();
- EXT(ctx)->pid = pid;
- EXT(ctx)->attach_callback = done;
- EXT(ctx)->attach_data = data;
- list_add_first(&ctx->ctxl, &pending_list);
- /* TODO: context_attach works only for main task in a process */
- return 0;
-}
-
-int context_has_state(Context * ctx) {
- return ctx != NULL && ctx->parent != NULL;
-}
-
-int context_stop(Context * ctx) {
- trace(LOG_CONTEXT, "context:%s suspending ctx %#lx, id %s",
- ctx->pending_intercept ? "" : " temporary", ctx, ctx->id);
- assert(is_dispatch_thread());
- assert(!ctx->exited);
- assert(!ctx->stopped);
- assert(!EXT(ctx)->regs_dirty);
- if (kill(EXT(ctx)->pid, SIGSTOP) < 0) {
- int err = errno;
- if (err == ESRCH) {
- ctx->exiting = 1;
- return 0;
- }
- trace(LOG_ALWAYS, "error: tkill(SIGSTOP) failed: ctx %#lx, id %s, error %d %s",
- ctx, ctx->id, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- return 0;
-}
-
-static int syscall_never_returns(Context * ctx) {
- if (EXT(ctx)->syscall_enter) {
- switch (EXT(ctx)->syscall_id) {
- case SYS_sigreturn:
- return 1;
- }
- }
- return 0;
-}
-
-int context_continue(Context * ctx) {
- int signal = 0;
-
- assert(is_dispatch_thread());
- assert(ctx->stopped);
- assert(!ctx->exited);
- assert(!ctx->pending_intercept);
- assert(!EXT(ctx)->pending_step);
-
- if (skip_breakpoint(ctx, 0)) return 0;
-
- if (!EXT(ctx)->syscall_enter) {
- while (ctx->pending_signals != 0) {
- while ((ctx->pending_signals & (1 << signal)) == 0) signal++;
- if (ctx->sig_dont_pass & (1 << signal)) {
- ctx->pending_signals &= ~(1 << signal);
- signal = 0;
- }
- else {
- break;
- }
- }
- assert(signal != SIGSTOP);
- assert(signal != SIGTRAP);
- }
-
- trace(LOG_CONTEXT, "context: resuming ctx %#lx, id %s, with signal %d", ctx, ctx->id, signal);
-#if defined(__i386__)
- if (EXT(ctx)->regs->__eflags & 0x100) {
- EXT(ctx)->regs->__eflags &= ~0x100;
- EXT(ctx)->regs_dirty = 1;
- }
-#elif defined(__x86_64__)
- if (EXT(ctx)->regs->__rflags & 0x100) {
- EXT(ctx)->regs->__rflags &= ~0x100;
- EXT(ctx)->regs_dirty = 1;
- }
-#endif
- if (EXT(ctx)->regs_dirty) {
- unsigned int state_count;
- if (thread_set_state(EXT(ctx)->pid, x86_THREAD_STATE32, EXT(ctx)->regs, &state_count) != KERN_SUCCESS) {
- int err = errno;
- trace(LOG_ALWAYS, "error: thread_set_state failed: ctx %#lx, id %s, error %d %s",
- ctx, ctx->id, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- EXT(ctx)->regs_dirty = 0;
- }
- if (ptrace(PT_CONTINUE, EXT(ctx)->pid, 0, signal) < 0) {
- int err = errno;
- if (err == ESRCH) {
- send_context_started_event(ctx);
- return 0;
- }
- trace(LOG_ALWAYS, "error: ptrace(PT_CONTINUE, ...) failed: ctx %#lx, id %s, error %d %s",
- ctx, ctx->id, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- ctx->pending_signals &= ~(1 << signal);
- if (syscall_never_returns(ctx)) {
- EXT(ctx)->syscall_enter = 0;
- EXT(ctx)->syscall_exit = 0;
- EXT(ctx)->syscall_id = 0;
- }
- send_context_started_event(ctx);
- return 0;
-}
-
-int context_single_step(Context * ctx) {
- assert(is_dispatch_thread());
- assert(context_has_state(ctx));
- assert(ctx->stopped);
- assert(!ctx->exited);
- assert(!EXT(ctx)->pending_step);
-
- if (skip_breakpoint(ctx, 1)) return 0;
-
- if (syscall_never_returns(ctx)) return context_continue(ctx);
- trace(LOG_CONTEXT, "context: single step ctx %#lx, id %S", ctx, ctx->id);
- if (EXT(ctx)->regs_dirty) {
- unsigned int state_count;
- if (thread_set_state(EXT(ctx)->pid, x86_THREAD_STATE32, EXT(ctx)->regs, &state_count) != KERN_SUCCESS) {
- int err = errno;
- trace(LOG_ALWAYS, "error: thread_set_state failed: ctx %#lx, id %s, error %d %s",
- ctx, ctx->id, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- EXT(ctx)->regs_dirty = 0;
- }
- if (ptrace(PT_STEP, EXT(ctx)->pid, 0, 0) < 0) {
- int err = errno;
- if (err == ESRCH) {
- EXT(ctx)->pending_step = 1;
- send_context_started_event(ctx);
- return 0;
- }
- trace(LOG_ALWAYS, "error: ptrace(PT_STEP, ...) failed: ctx %#lx, id %s, error %d %s",
- ctx, ctx->id, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- EXT(ctx)->pending_step = 1;
- send_context_started_event(ctx);
- return 0;
-}
-
-int context_resume(Context * ctx, int mode, ContextAddress range_start, ContextAddress range_end) {
- switch (mode) {
- case RM_RESUME:
- return context_continue(ctx);
- case RM_STEP_INTO:
- return context_single_step(ctx);
- case RM_TERMINATE:
- ctx->pending_signals |= 1 << SIGKILL;
- return context_continue(ctx);
- }
- errno = ERR_UNSUPPORTED;
- return -1;
-}
-
-int context_can_resume(Context * ctx, int mode) {
- switch (mode) {
- case RM_RESUME:
- return 1;
- case RM_STEP_INTO:
- case RM_TERMINATE:
- return context_has_state(ctx);
- }
- return 0;
-}
-
-int context_write_mem(Context * ctx, ContextAddress address, void * buf, size_t size) {
- /*
- ContextAddress word_addr;
- assert(is_dispatch_thread());
- assert(!ctx->exited);
- trace(LOG_CONTEXT, "context: write memory ctx %#lx, id %s, address %#lx, size %zu",
- ctx, ctx->id, address, size);
- assert(WORD_SIZE == sizeof(unsigned));
- check_breakpoints_on_memory_write(ctx, address, buf, size);
- for (word_addr = address & ~(WORD_SIZE - 1); word_addr < address + size; word_addr += WORD_SIZE) {
- unsigned word = 0;
- if (word_addr < address || word_addr + WORD_SIZE > address + size) {
- int i;
- errno = 0;
- word = ptrace(PT_PEEKDATA, EXT(ctx)->pid, word_addr, 0);
- if (errno != 0) {
- int err = errno;
- trace(LOG_CONTEXT, "error: ptrace(PT_PEEKDATA, ...) failed: ctx %#lx, id %s, error %d %s",
- ctx, ctx->id, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- for (i = 0; i < WORD_SIZE; i++) {
- if (word_addr + i >= address && word_addr + i < address + size) {
- ((char *)&word)[i] = ((char *)buf)[word_addr + i - address];
- }
- }
- }
- else {
- word = *(unsigned *)((char *)buf + (word_addr - address));
- }
- if (ptrace(PT_POKEDATA, EXT(ctx)->pid, word_addr, word) < 0) {
- int err = errno;
- trace(LOG_ALWAYS, "error: ptrace(PT_POKEDATA, ...) failed: ctx %#lx, id %s, error %d %s",
- ctx, ctx->id, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- }
- */
- return 0;
-}
-
-int context_read_mem(Context * ctx, ContextAddress address, void * buf, size_t size) {
- /*
- ContextAddress word_addr;
- assert(is_dispatch_thread());
- assert(!ctx->exited);
- trace(LOG_CONTEXT, "context: read memory ctx %#lx, id %s, address %#lx, size %zu",
- ctx, ctx->id, address, size);
- assert(WORD_SIZE == sizeof(unsigned));
- for (word_addr = address & ~(WORD_SIZE - 1); word_addr < address + size; word_addr += WORD_SIZE) {
- unsigned word = 0;
- errno = 0;
- word = ptrace(PT_PEEKDATA, EXT(ctx)->pid, word_addr, 0);
- if (errno != 0) {
- int err = errno;
- trace(LOG_CONTEXT, "error: ptrace(PT_PEEKDATA, ...) failed: ctx %#lx, id %s, error %d %s",
- ctx, ctx->id, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- if (word_addr < address || word_addr + WORD_SIZE > address + size) {
- int i;
- for (i = 0; i < WORD_SIZE; i++) {
- if (word_addr + i >= address && word_addr + i < address + size) {
- ((char *)buf)[word_addr + i - address] = ((char *)&word)[i];
- }
- }
- }
- else {
- *(unsigned *)((char *)buf + (word_addr - address)) = word;
- }
- }
- check_breakpoints_on_memory_read(ctx, address, buf, size);
- */
- return 0;
-}
-
-#if ENABLE_ExtendedMemoryErrorReports
-int context_get_mem_error_info(MemoryErrorInfo * info) {
- if (mem_err_info.error == 0) {
- set_errno(ERR_OTHER, "Extended memory error info not available");
- return -1;
- }
- *info = mem_err_info;
- return 0;
-}
-#endif
-
-int context_write_reg(Context * ctx, RegisterDefinition * def, unsigned offs, unsigned size, void * buf) {
- ContextExtensionDarwin * ext = EXT(ctx);
-
- assert(is_dispatch_thread());
- assert(context_has_state(ctx));
- assert(ctx->stopped);
- assert(!ctx->exited);
- assert(offs + size <= def->size);
-
- if (ext->regs_error) {
- set_error_report_errno(ext->regs_error);
- return -1;
- }
- memcpy((uint8_t *)ext->regs + def->offset + offs, buf, size);
- ext->regs_dirty = 1;
- return 0;
-}
-
-int context_read_reg(Context * ctx, RegisterDefinition * def, unsigned offs, unsigned size, void * buf) {
- ContextExtensionDarwin * ext = EXT(ctx);
-
- assert(is_dispatch_thread());
- assert(context_has_state(ctx));
- assert(ctx->stopped);
- assert(!ctx->exited);
- assert(offs + size <= def->size);
-
- if (ext->regs_error) {
- set_error_report_errno(ext->regs_error);
- return -1;
- }
- memcpy(buf, (uint8_t *)ext->regs + def->offset + offs, size);
- return 0;
-}
-
-unsigned context_word_size(Context * ctx) {
- return sizeof(void *);
-}
-
-int context_get_canonical_addr(Context * ctx, ContextAddress addr,
- Context ** canonical_ctx, ContextAddress * canonical_addr,
- ContextAddress * block_addr, ContextAddress * block_size) {
- /* Direct mapping, page size is irrelevant */
- ContextAddress page_size = 0x100000;
- assert(is_dispatch_thread());
- *canonical_ctx = ctx->mem;
- if (canonical_addr != NULL) *canonical_addr = addr;
- if (block_addr != NULL) *block_addr = addr & ~(page_size - 1);
- if (block_size != NULL) *block_size = page_size;
- return 0;
-}
-
-Context * context_get_group(Context * ctx, int group) {
- static Context * cpu_group = NULL;
- switch (group) {
- case CONTEXT_GROUP_INTERCEPT:
- return ctx;
- case CONTEXT_GROUP_CPU:
- if (cpu_group == NULL) cpu_group = create_context("CPU");
- return cpu_group;
- }
- return ctx->mem;
-}
-
-int context_get_supported_bp_access_types(Context * ctx) {
- return 0;
-}
-
-int context_plant_breakpoint(ContextBreakpoint * bp) {
- errno = ERR_UNSUPPORTED;
- return -1;
-}
-
-int context_unplant_breakpoint(ContextBreakpoint * bp) {
- errno = ERR_UNSUPPORTED;
- return -1;
-}
-
-int context_get_memory_map(Context * ctx, MemoryMap * map) {
- ctx = ctx->mem;
- assert(!ctx->exited);
- return 0;
-}
-
-static Context * find_pending(pid_t pid) {
- LINK * l = pending_list.next;
- while (l != &pending_list) {
- Context * c = ctxl2ctxp(l);
- if (EXT(c)->pid == pid) {
- list_remove(&c->ctxl);
- return c;
- }
- l = l->next;
- }
- return NULL;
-}
-
-static void event_pid_exited(pid_t pid, int status, int signal) {
- Context * ctx;
-
- ctx = context_find_from_pid(pid, 1);
- if (ctx == NULL) {
- ctx = find_pending(pid);
- if (ctx == NULL) {
- trace(LOG_EVENTS, "event: ctx not found, pid %d, exit status %d, term signal %d", pid, status, signal);
- }
- else {
- assert(ctx->ref_count == 0);
- if (EXT(ctx)->attach_callback != NULL) {
- if (status == 0) status = EINVAL;
- EXT(ctx)->attach_callback(status, ctx, EXT(ctx)->attach_data);
- }
- assert(list_is_empty(&ctx->children));
- assert(ctx->parent == NULL);
- ctx->exited = 1;
- ctx->ref_count = 1;
- context_unlock(ctx);
- }
- }
- else {
- /* Note: ctx->exiting should be 1 here. However, PTRACE_EVENT_EXIT can be lost by PTRACE because of racing
- * between PTRACE_CONT (or PTRACE_SYSCALL) and SIGTRAP/PTRACE_EVENT_EXIT. So, ctx->exiting can be 0.
- */
- if (EXT(ctx->parent)->pid == pid) ctx = ctx->parent;
- assert(EXT(ctx)->attach_callback == NULL);
- if (ctx->exited) {
- trace(LOG_EVENTS, "event: ctx %#lx, pid %d, exit status %d unexpected, stopped %d, exited %d",
- ctx, pid, status, ctx->stopped, ctx->exited);
- }
- else {
- trace(LOG_EVENTS, "event: ctx %#lx, pid %d, exit status %d, term signal %d", ctx, pid, status, signal);
- ctx->exiting = 1;
- if (ctx->stopped) send_context_started_event(ctx);
- if (!list_is_empty(&ctx->children)) {
- LINK * l = ctx->children.next;
- while (l != &ctx->children) {
- Context * c = cldl2ctxp(l);
- l = l->next;
- assert(c->parent == ctx);
- if (!c->exited) {
- c->exiting = 1;
- if (c->stopped) send_context_started_event(c);
- release_error_report(EXT(c)->regs_error);
- loc_free(EXT(c)->regs);
- EXT(c)->regs_error = NULL;
- EXT(c)->regs = NULL;
- send_context_exited_event(c);
- }
- }
- }
- release_error_report(EXT(ctx)->regs_error);
- loc_free(EXT(ctx)->regs);
- EXT(ctx)->regs_error = NULL;
- EXT(ctx)->regs = NULL;
- send_context_exited_event(ctx);
- }
- }
-}
-
-static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) {
- int stopped_by_exception = 0;
- unsigned long msg = 0;
- Context * ctx = NULL;
- Context * ctx2 = NULL;
-
- trace(LOG_EVENTS, "event: pid %d stopped, signal %d", pid, signal);
-
- ctx = context_find_from_pid(pid, 1);
-
- if (ctx == NULL) {
- ctx = find_pending(pid);
- if (ctx != NULL) {
- Context * prs = ctx;
- assert(prs->ref_count == 0);
- ctx = create_context(pid2id(pid, pid));
- EXT(ctx)->pid = pid;
- EXT(ctx)->regs = (REG_SET *)loc_alloc(sizeof(REG_SET));
- ctx->pending_intercept = 1;
- ctx->mem = prs;
- ctx->parent = prs;
- ctx->big_endian = prs->big_endian;
- prs->ref_count++;
- list_add_last(&ctx->cldl, &prs->children);
- link_context(prs);
- link_context(ctx);
- send_context_created_event(prs);
- send_context_created_event(ctx);
- if (EXT(prs)->attach_callback) {
- EXT(prs)->attach_callback(0, prs, EXT(prs)->attach_data);
- EXT(prs)->attach_callback = NULL;
- EXT(prs)->attach_data = NULL;
- }
- }
- }
-
- if (ctx == NULL) return;
-
- assert(!ctx->exited);
- assert(!EXT(ctx)->attach_callback);
-
- if (signal != SIGSTOP && signal != SIGTRAP) {
- assert(signal < 32);
- ctx->pending_signals |= 1 << signal;
- if ((ctx->sig_dont_stop & (1 << signal)) == 0) {
- ctx->pending_intercept = 1;
- stopped_by_exception = 1;
- }
- }
-
- if (ctx->stopped) {
- send_context_changed_event(ctx);
- }
- else {
- thread_state_t state;
- unsigned int state_count;
- ContextAddress pc0 = 0;
- ContextAddress pc1 = 0;
-
- assert(!EXT(ctx)->regs_dirty);
-
- EXT(ctx)->end_of_step = 0;
- EXT(ctx)->ptrace_event = event;
- ctx->signal = signal;
- ctx->stopped_by_bp = 0;
- ctx->stopped_by_exception = stopped_by_exception;
- ctx->stopped = 1;
-
- if (EXT(ctx)->regs_error) {
- release_error_report(EXT(ctx)->regs_error);
- EXT(ctx)->regs_error = NULL;
- }
- else {
- pc0 = get_regs_PC(ctx);
- }
-
- if (thread_get_state(EXT(ctx)->pid, x86_THREAD_STATE32, EXT(ctx)->regs, &state_count) != KERN_SUCCESS) {
- assert(errno != 0);
- EXT(ctx)->regs_error = get_error_report(errno);
- trace(LOG_ALWAYS, "error: thread_get_state failed; id %s, error %d %s",
- ctx->id, errno, errno_to_str(errno));
- }
- else {
- pc1 = get_regs_PC(ctx);
- }
-
- if (!EXT(ctx)->syscall_enter || EXT(ctx)->regs_error || pc0 != pc1) {
- EXT(ctx)->syscall_enter = 0;
- EXT(ctx)->syscall_exit = 0;
- EXT(ctx)->syscall_id = 0;
- EXT(ctx)->syscall_pc = 0;
- }
- trace(LOG_EVENTS, "event: pid %d stopped at PC = %#lx", pid, pc1);
-
- if (signal == SIGTRAP && event == 0 && !syscall) {
- size_t break_size = 0;
- get_break_instruction(ctx, &break_size);
- ctx->stopped_by_bp = !EXT(ctx)->regs_error && is_breakpoint_address(ctx, pc1 - break_size);
- EXT(ctx)->end_of_step = !ctx->stopped_by_bp && EXT(ctx)->pending_step;
- if (ctx->stopped_by_bp) set_regs_PC(ctx, pc1 - break_size);
- }
- EXT(ctx)->pending_step = 0;
- send_context_stopped_event(ctx);
- }
-}
-
-static void waitpid_listener(int pid, int exited, int exit_code, int signal, int event_code, int syscall, void * args) {
- if (exited) {
- event_pid_exited(pid, exit_code, signal);
- }
- else {
- event_pid_stopped(pid, signal, event_code, syscall);
- }
-}
-
-void init_contexts_sys_dep(void) {
- context_extension_offset = context_extension(sizeof(ContextExtensionDarwin));
- add_waitpid_listener(waitpid_listener, NULL);
- ini_context_pid_hash();
-}
-
-#endif /* if ENABLE_DebugContext */
-#endif /* __APPLE__ */
diff --git a/agent/tcf/system/Darwin/regset.h b/agent/tcf/system/Darwin/regset.h
deleted file mode 100644
index 0422799e..00000000
--- a/agent/tcf/system/Darwin/regset.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-/*
- * This header file provides definition of REG_SET - a structure that can
- * hold values of target CPU registers.
- */
-
-#if defined(__APPLE__)
-# include <mach/thread_status.h>
-# if defined(__i386__)
- typedef x86_thread_state32_t REG_SET;
-# else
- typedef x86_thread_state64_t REG_SET;
-# endif
-#endif
diff --git a/agent/tcf/system/FreeBSD/context-freebsd.c b/agent/tcf/system/FreeBSD/context-freebsd.c
deleted file mode 100644
index 9f01aaa0..00000000
--- a/agent/tcf/system/FreeBSD/context-freebsd.c
+++ /dev/null
@@ -1,659 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-/*
- * This module handles process/thread OS contexts and their state machine.
- */
-
-#include <tcf/config.h>
-
-#if defined(__FreeBSD__)
-
-#if ENABLE_DebugContext && !ENABLE_ContextProxy
-
-#include <stdlib.h>
-#include <assert.h>
-#include <errno.h>
-#include <signal.h>
-#include <sched.h>
-#include <sys/ptrace.h>
-#include <tcf/framework/context.h>
-#include <tcf/framework/events.h>
-#include <tcf/framework/errors.h>
-#include <tcf/framework/trace.h>
-#include <tcf/framework/myalloc.h>
-#include <tcf/framework/waitpid.h>
-#include <tcf/framework/signames.h>
-#include <tcf/services/breakpoints.h>
-#include <tcf/system/FreeBSD/regset.h>
-
-#define PTRACE_TRACEME PT_TRACE_ME
-#define PTRACE_ATTACH PT_ATTACH
-#define PTRACE_GETREGS PT_GETREGS
-#define PTRACE_SETREGS PT_SETREGS
-#define PTRACE_PEEKDATA PT_READ_D
-#define PTRACE_POKEDATA PT_WRITE_D
-#define PTRACE_CONT PT_CONTINUE
-#define PTRACE_SINGLESTEP PT_STEP
-
-#define USE_PTRACE_SYSCALL 0
-
-typedef struct ContextExtensionBSD {
- pid_t pid;
- ContextAttachCallBack * attach_callback;
- void * attach_data;
- int ptrace_flags;
- int ptrace_event;
- int syscall_enter;
- int syscall_exit;
- int syscall_id;
- ContextAddress syscall_pc;
- ContextAddress loader_state;
- int end_of_step;
- REG_SET * regs; /* copy of context registers, updated when context stops */
- ErrorReport * regs_error; /* if not NULL, 'regs' is invalid */
- int regs_dirty; /* if not 0, 'regs' is modified and needs to be saved before context is continued */
- int pending_step;
-} ContextExtensionBSD;
-
-static size_t context_extension_offset = 0;
-
-#define EXT(ctx) ((ContextExtensionBSD *)((char *)(ctx) + context_extension_offset))
-
-#include <tcf/system/pid-hash.h>
-
-static LINK pending_list = TCF_LIST_INIT(pending_list);
-
-static MemoryErrorInfo mem_err_info;
-
-static const char * event_name(int event) {
- trace(LOG_ALWAYS, "event_name(): unexpected event code %d", event);
- return "unknown";
-}
-
-const char * context_suspend_reason(Context * ctx) {
- static char reason[128];
-
- if (EXT(ctx)->end_of_step) return REASON_STEP;
- if (EXT(ctx)->ptrace_event != 0) {
- assert(ctx->signal == SIGTRAP);
- snprintf(reason, sizeof(reason), "Event: %s", event_name(EXT(ctx)->ptrace_event));
- return reason;
- }
- if (ctx->signal == SIGSTOP || ctx->signal == SIGTRAP) return REASON_USER_REQUEST;
- snprintf(reason, sizeof(reason), "Signal %d", ctx->signal);
- return reason;
-}
-
-int context_attach_self(void) {
- if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {
- int err = errno;
- trace(LOG_ALWAYS, "error: ptrace(PTRACE_TRACEME) failed: pid %d, error %d %s",
- getpid(), err, errno_to_str(err));
- errno = err;
- return -1;
- }
- return 0;
-}
-
-int context_attach(pid_t pid, ContextAttachCallBack * done, void * data, int mode) {
- Context * ctx = NULL;
-
- assert(done != NULL);
- trace(LOG_CONTEXT, "context: attaching pid %d", pid);
- if ((mode & CONTEXT_ATTACH_SELF) == 0 && ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) {
- int err = errno;
- trace(LOG_ALWAYS, "error: ptrace(PTRACE_ATTACH) failed: pid %d, error %d %s",
- pid, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- add_waitpid_process(pid);
- ctx = create_context(pid2id(pid, 0));
- ctx->mem = ctx;
- ctx->mem_access |= MEM_ACCESS_INSTRUCTION;
- ctx->mem_access |= MEM_ACCESS_DATA;
- ctx->mem_access |= MEM_ACCESS_USER;
- ctx->big_endian = big_endian_host();
- EXT(ctx)->pid = pid;
- EXT(ctx)->attach_callback = done;
- EXT(ctx)->attach_data = data;
- list_add_first(&ctx->ctxl, &pending_list);
- /* TODO: context_attach works only for main task in a process */
- return 0;
-}
-
-int context_has_state(Context * ctx) {
- return ctx != NULL && ctx->parent != NULL;
-}
-
-int context_stop(Context * ctx) {
- trace(LOG_CONTEXT, "context:%s suspending ctx %#lx id %s",
- ctx->pending_intercept ? "" : " temporary", ctx, ctx->id);
- assert(is_dispatch_thread());
- assert(!ctx->exited);
- assert(!ctx->stopped);
- assert(!EXT(ctx)->regs_dirty);
- if (tkill(EXT(ctx)->pid, SIGSTOP) < 0) {
- int err = errno;
- if (err == ESRCH) {
- ctx->exiting = 1;
- return 0;
- }
- trace(LOG_ALWAYS, "error: tkill(SIGSTOP) failed: ctx %#lx, id %s, error %d %s",
- ctx, ctx->id, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- return 0;
-}
-
-int context_continue(Context * ctx) {
- int signal = 0;
-
- assert(is_dispatch_thread());
- assert(ctx->stopped);
- assert(!ctx->pending_intercept);
- assert(!EXT(ctx)->pending_step);
- assert(!ctx->exited);
-
- if (skip_breakpoint(ctx, 0)) return 0;
-
- if (!EXT(ctx)->ptrace_event) {
- while (ctx->pending_signals != 0) {
- while ((ctx->pending_signals & (1 << signal)) == 0) signal++;
- if (ctx->sig_dont_pass & (1 << signal)) {
- ctx->pending_signals &= ~(1 << signal);
- signal = 0;
- }
- else {
- break;
- }
- }
- assert(signal != SIGSTOP);
- assert(signal != SIGTRAP);
- }
-
- trace(LOG_CONTEXT, "context: resuming ctx %#lx, id %s, with signal %d", ctx, ctx->id, signal);
- if (EXT(ctx)->regs_dirty) {
- if (ptrace(PTRACE_SETREGS, EXT(ctx)->pid, 0, (int)EXT(ctx)->regs) < 0) {
- int err = errno;
- if (err == ESRCH) {
- EXT(ctx)->regs_dirty = 0;
- send_context_started_event(ctx);
- return 0;
- }
- trace(LOG_ALWAYS, "error: ptrace(PTRACE_SETREGS) failed: ctx %#lx, id %s, error %d %s",
- ctx, ctx->id, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- EXT(ctx)->regs_dirty = 0;
- }
- if (ptrace(PTRACE_CONT, EXT(ctx)->pid, 0, signal) < 0) {
- int err = errno;
- if (err == ESRCH) {
- send_context_started_event(ctx);
- return 0;
- }
- trace(LOG_ALWAYS, "error: ptrace(PTRACE_CONT, ...) failed: ctx %#lx, id %s, error %d %s",
- ctx, ctx->id, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- ctx->pending_signals &= ~(1 << signal);
- send_context_started_event(ctx);
- return 0;
-}
-
-int context_single_step(Context * ctx) {
- assert(is_dispatch_thread());
- assert(context_has_state(ctx));
- assert(ctx->stopped);
- assert(!ctx->exited);
- assert(!EXT(ctx)->pending_step);
-
- if (skip_breakpoint(ctx, 1)) return 0;
-
- trace(LOG_CONTEXT, "context: single step ctx %#lx, id %s", ctx, ctx->id);
- if (EXT(ctx)->regs_dirty) {
- if (ptrace(PTRACE_SETREGS, EXT(ctx)->pid, 0, (int)EXT(ctx)->regs) < 0) {
- int err = errno;
- if (err == ESRCH) {
- EXT(ctx)->regs_dirty = 0;
- EXT(ctx)->pending_step = 1;
- send_context_started_event(ctx);
- return 0;
- }
- trace(LOG_ALWAYS, "error: ptrace(PTRACE_SETREGS) failed: ctx %#lx, id %s, error %d %s",
- ctx, ctx->id, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- EXT(ctx)->regs_dirty = 0;
- }
- if (ptrace(PTRACE_SINGLESTEP, EXT(ctx)->pid, 0, 0) < 0) {
- int err = errno;
- if (err == ESRCH) {
- EXT(ctx)->pending_step = 1;
- send_context_started_event(ctx);
- return 0;
- }
- trace(LOG_ALWAYS, "error: ptrace(PTRACE_SINGLESTEP, ...) failed: ctx %#lx, id %s, error %d %s",
- ctx, ctx->id, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- EXT(ctx)->pending_step = 1;
- send_context_started_event(ctx);
- return 0;
-}
-
-int context_resume(Context * ctx, int mode, ContextAddress range_start, ContextAddress range_end) {
- switch (mode) {
- case RM_RESUME:
- return context_continue(ctx);
- case RM_STEP_INTO:
- return context_single_step(ctx);
- case RM_TERMINATE:
- ctx->pending_signals |= 1 << SIGKILL;
- return context_continue(ctx);
- }
- errno = ERR_UNSUPPORTED;
- return -1;
-}
-
-int context_can_resume(Context * ctx, int mode) {
- switch (mode) {
- case RM_RESUME:
- return 1;
- case RM_STEP_INTO:
- case RM_TERMINATE:
- return context_has_state(ctx);
- }
- return 0;
-}
-
-int context_write_mem(Context * ctx, ContextAddress address, void * buf, size_t size) {
- ContextAddress word_addr;
- unsigned word_size = context_word_size(ctx);
- assert(is_dispatch_thread());
- assert(!ctx->exited);
- trace(LOG_CONTEXT, "context: write memory ctx %#lx, id %s, address %#lx, size %zu",
- ctx, ctx->id, address, size);
- assert(word_size <= sizeof(unsigned long));
- if (check_breakpoints_on_memory_write(ctx, address, buf, size) < 0) return -1;
- for (word_addr = address & ~((ContextAddress)word_size - 1); word_addr < address + size; word_addr += word_size) {
- unsigned long word = 0;
- if (word_addr < address || word_addr + word_size > address + size) {
- size_t i;
- errno = 0;
- word = ptrace(PTRACE_PEEKDATA, EXT(ctx)->pid, (char *)word_addr, 0);
- if (errno != 0) {
- int err = errno;
- trace(LOG_CONTEXT, "error: ptrace(PTRACE_PEEKDATA, ...) failed: ctx %#lx, id %s, addr %#lx, error %d %s",
- ctx, ctx->id, word_addr, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- for (i = 0; i < word_size; i++) {
- if (word_addr + i >= address && word_addr + i < address + size) {
- ((char *)&word)[i] = ((char *)buf)[word_addr + i - address];
- }
- }
- }
- else {
- memcpy(&word, (char *)buf + (word_addr - address), word_size);
- }
- if (ptrace(PTRACE_POKEDATA, EXT(ctx)->pid, (char *)word_addr, word) < 0) {
- int err = errno;
- trace(LOG_ALWAYS, "error: ptrace(PTRACE_POKEDATA, ...) failed: ctx %#lx, id %s, addr %#lx, error %d %s",
- ctx, ctx->id, word_addr, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- }
- return 0;
-}
-
-int context_read_mem(Context * ctx, ContextAddress address, void * buf, size_t size) {
- ContextAddress word_addr;
- unsigned word_size = context_word_size(ctx);
- assert(is_dispatch_thread());
- assert(!ctx->exited);
- trace(LOG_CONTEXT, "context: read memory ctx %#lx, id %s, address %#lx, size %zu",
- ctx, ctx->id, address, size);
- assert(word_size <= sizeof(unsigned long));
- for (word_addr = address & ~((ContextAddress)word_size - 1); word_addr < address + size; word_addr += word_size) {
- unsigned long word = 0;
- errno = 0;
- word = ptrace(PTRACE_PEEKDATA, EXT(ctx)->pid, (char *)word_addr, 0);
- if (errno != 0) {
- int err = errno;
- trace(LOG_CONTEXT, "error: ptrace(PTRACE_PEEKDATA, ...) failed: ctx %#lx, id %s, addr %#lx, error %d %s",
- ctx, ctx->id, word_addr, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- if (word_addr < address || word_addr + word_size > address + size) {
- size_t i;
- for (i = 0; i < word_size; i++) {
- if (word_addr + i >= address && word_addr + i < address + size) {
- ((char *)buf)[word_addr + i - address] = ((char *)&word)[i];
- }
- }
- }
- else {
- memcpy((char *)buf + (word_addr - address), &word, word_size);
- }
- }
- return check_breakpoints_on_memory_read(ctx, address, buf, size);
-}
-
-#if ENABLE_ExtendedMemoryErrorReports
-int context_get_mem_error_info(MemoryErrorInfo * info) {
- if (mem_err_info.error == 0) {
- set_errno(ERR_OTHER, "Extended memory error info not available");
- return -1;
- }
- *info = mem_err_info;
- return 0;
-}
-#endif
-
-int context_write_reg(Context * ctx, RegisterDefinition * def, unsigned offs, unsigned size, void * buf) {
- ContextExtensionBSD * ext = EXT(ctx);
-
- assert(is_dispatch_thread());
- assert(context_has_state(ctx));
- assert(ctx->stopped);
- assert(!ctx->exited);
- assert(offs + size <= def->size);
-
- if (ext->regs_error) {
- set_error_report_errno(ext->regs_error);
- return -1;
- }
- memcpy((uint8_t *)ext->regs + def->offset + offs, buf, size);
- ext->regs_dirty = 1;
- return 0;
-}
-
-int context_read_reg(Context * ctx, RegisterDefinition * def, unsigned offs, unsigned size, void * buf) {
- ContextExtensionBSD * ext = EXT(ctx);
-
- assert(is_dispatch_thread());
- assert(context_has_state(ctx));
- assert(ctx->stopped);
- assert(!ctx->exited);
- assert(offs + size <= def->size);
-
- if (ext->regs_error) {
- set_error_report_errno(ext->regs_error);
- return -1;
- }
- memcpy(buf, (uint8_t *)ext->regs + def->offset + offs, size);
- return 0;
-}
-
-unsigned context_word_size(Context * ctx) {
- return sizeof(void *);
-}
-
-int context_get_canonical_addr(Context * ctx, ContextAddress addr,
- Context ** canonical_ctx, ContextAddress * canonical_addr,
- ContextAddress * block_addr, ContextAddress * block_size) {
- /* Direct mapping, page size is irrelevant */
- ContextAddress page_size = 0x100000;
- assert(is_dispatch_thread());
- *canonical_ctx = ctx->mem;
- if (canonical_addr != NULL) *canonical_addr = addr;
- if (block_addr != NULL) *block_addr = addr & ~(page_size - 1);
- if (block_size != NULL) *block_size = page_size;
- return 0;
-}
-
-Context * context_get_group(Context * ctx, int group) {
- static Context * cpu_group = NULL;
- switch (group) {
- case CONTEXT_GROUP_INTERCEPT:
- return ctx;
- case CONTEXT_GROUP_CPU:
- if (cpu_group == NULL) cpu_group = create_context("CPU");
- return cpu_group;
- }
- return ctx->mem;
-}
-
-int context_get_supported_bp_access_types(Context * ctx) {
- return 0;
-}
-
-int context_plant_breakpoint(ContextBreakpoint * bp) {
- errno = ERR_UNSUPPORTED;
- return -1;
-}
-
-int context_unplant_breakpoint(ContextBreakpoint * bp) {
- errno = ERR_UNSUPPORTED;
- return -1;
-}
-
-int context_get_memory_map(Context * ctx, MemoryMap * map) {
- ctx = ctx->mem;
- assert(!ctx->exited);
- return 0;
-}
-
-static Context * find_pending(pid_t pid) {
- LINK * l = pending_list.next;
- while (l != &pending_list) {
- Context * c = ctxl2ctxp(l);
- if (EXT(c)->pid == pid) {
- list_remove(&c->ctxl);
- return c;
- }
- l = l->next;
- }
- return NULL;
-}
-
-static void event_pid_exited(pid_t pid, int status, int signal) {
- Context * ctx;
-
- ctx = context_find_from_pid(pid, 1);
- if (ctx == NULL) {
- ctx = find_pending(pid);
- if (ctx == NULL) {
- trace(LOG_EVENTS, "event: ctx not found, pid %d, exit status %d, term signal %d", pid, status, signal);
- }
- else {
- assert(ctx->ref_count == 0);
- if (EXT(ctx)->attach_callback != NULL) {
- if (status == 0) status = EINVAL;
- EXT(ctx)->attach_callback(status, ctx, EXT(ctx)->attach_data);
- }
- assert(list_is_empty(&ctx->children));
- assert(ctx->parent == NULL);
- ctx->exited = 1;
- ctx->ref_count = 1;
- context_unlock(ctx);
- }
- }
- else {
- /* Note: ctx->exiting should be 1 here. However, PTRACE_EVENT_EXIT can be lost by PTRACE because of racing
- * between PTRACE_CONT (or PTRACE_SYSCALL) and SIGTRAP/PTRACE_EVENT_EXIT. So, ctx->exiting can be 0.
- */
- if (EXT(ctx->parent)->pid == pid) ctx = ctx->parent;
- assert(EXT(ctx)->attach_callback == NULL);
- if (ctx->exited) {
- trace(LOG_EVENTS, "event: ctx %#lx, pid %d, exit status %d unexpected, stopped %d, exited %d",
- ctx, pid, status, ctx->stopped, ctx->exited);
- }
- else {
- trace(LOG_EVENTS, "event: ctx %#lx, pid %d, exit status %d, term signal %d", ctx, pid, status, signal);
- ctx->exiting = 1;
- if (ctx->stopped) send_context_started_event(ctx);
- if (!list_is_empty(&ctx->children)) {
- LINK * l = ctx->children.next;
- while (l != &ctx->children) {
- Context * c = cldl2ctxp(l);
- l = l->next;
- assert(c->parent == ctx);
- if (!c->exited) {
- c->exiting = 1;
- if (c->stopped) send_context_started_event(c);
- release_error_report(EXT(c)->regs_error);
- loc_free(EXT(c)->regs);
- EXT(c)->regs_error = NULL;
- EXT(c)->regs = NULL;
- send_context_exited_event(c);
- }
- }
- }
- release_error_report(EXT(ctx)->regs_error);
- loc_free(EXT(ctx)->regs);
- EXT(ctx)->regs_error = NULL;
- EXT(ctx)->regs = NULL;
- send_context_exited_event(ctx);
- }
- }
-}
-
-static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) {
- int stopped_by_exception = 0;
- Context * ctx = NULL;
-
- trace(LOG_EVENTS, "event: pid %d stopped, signal %d, event %s", pid, signal, event_name(event));
-
- ctx = context_find_from_pid(pid, 1);
-
- if (ctx == NULL) {
- ctx = find_pending(pid);
- if (ctx != NULL) {
- Context * prs = ctx;
- assert(prs->ref_count == 0);
- ctx = create_context(pid2id(pid, pid));
- EXT(ctx)->pid = pid;
- EXT(ctx)->regs = (REG_SET *)loc_alloc(sizeof(REG_SET));
- ctx->pending_intercept = 1;
- ctx->mem = prs;
- ctx->parent = prs;
- ctx->big_endian = prs->big_endian;
- prs->ref_count++;
- list_add_last(&ctx->cldl, &prs->children);
- link_context(prs);
- link_context(ctx);
- send_context_created_event(prs);
- send_context_created_event(ctx);
- if (EXT(prs)->attach_callback) {
- EXT(prs)->attach_callback(0, prs, EXT(prs)->attach_data);
- EXT(prs)->attach_callback = NULL;
- EXT(prs)->attach_data = NULL;
- }
- }
- }
-
- if (ctx == NULL) return;
-
- assert(!ctx->exited);
- assert(!EXT(ctx)->attach_callback);
-
- if (signal != SIGSTOP && signal != SIGTRAP) {
- assert(signal < 32);
- ctx->pending_signals |= 1 << signal;
- if ((ctx->sig_dont_stop & (1 << signal)) == 0) {
- ctx->pending_intercept = 1;
- stopped_by_exception = 1;
- }
- }
-
- if (ctx->stopped) {
- send_context_changed_event(ctx);
- }
- else {
- ContextAddress pc0 = 0;
- ContextAddress pc1 = 0;
-
- assert(!EXT(ctx)->regs_dirty);
-
- EXT(ctx)->end_of_step = 0;
- EXT(ctx)->ptrace_event = event;
- ctx->signal = signal;
- ctx->stopped_by_bp = 0;
- ctx->stopped_by_exception = stopped_by_exception;
- ctx->stopped = 1;
-
- if (EXT(ctx)->regs_error) {
- release_error_report(EXT(ctx)->regs_error);
- EXT(ctx)->regs_error = NULL;
- }
- else {
- pc0 = get_regs_PC(ctx);
- }
-
- if (ptrace(PTRACE_GETREGS, EXT(ctx)->pid, 0, (int)EXT(ctx)->regs) < 0) {
- assert(errno != 0);
- if (errno == ESRCH) {
- /* Racing condition: somebody resumed this context while we are handling stop event.
- *
- * One possible cause: main thread has exited forcing children to exit too.
- * I beleive it is a bug in PTRACE implementation - PTRACE should delay exiting of
- * a context while it is stopped, but it does not, which causes a nasty racing.
- *
- * Workaround: Ignore current event, assume context is running.
- */
- ctx->stopped = 0;
- return;
- }
- EXT(ctx)->regs_error = get_error_report(errno);
- trace(LOG_ALWAYS, "error: ptrace(PTRACE_GETREGS) failed; id %s, error %d %s",
- ctx->id, errno, errno_to_str(errno));
- }
- else {
- pc1 = get_regs_PC(ctx);
- }
-
- trace(LOG_EVENTS, "event: pid %d stopped at PC = %#lx", pid, pc1);
-
- if (signal == SIGTRAP && event == 0 && !syscall) {
- size_t break_size = 0;
- get_break_instruction(ctx, &break_size);
- ctx->stopped_by_bp = !EXT(ctx)->regs_error && is_breakpoint_address(ctx, pc1 - break_size);
- EXT(ctx)->end_of_step = !ctx->stopped_by_bp && EXT(ctx)->pending_step;
- if (ctx->stopped_by_bp) set_regs_PC(ctx, pc1 - break_size);
- }
- EXT(ctx)->pending_step = 0;
- send_context_stopped_event(ctx);
- }
-}
-
-static void waitpid_listener(int pid, int exited, int exit_code, int signal, int event_code, int syscall, void * args) {
- if (exited) {
- event_pid_exited(pid, exit_code, signal);
- }
- else {
- event_pid_stopped(pid, signal, event_code, syscall);
- }
-}
-
-void init_contexts_sys_dep(void) {
- context_extension_offset = context_extension(sizeof(ContextExtensionBSD));
- add_waitpid_listener(waitpid_listener, NULL);
- ini_context_pid_hash();
-}
-
-#endif /* if ENABLE_DebugContext */
-#endif /* __FreeBSD__ */
diff --git a/agent/tcf/system/FreeBSD/regset.h b/agent/tcf/system/FreeBSD/regset.h
deleted file mode 100644
index add029bd..00000000
--- a/agent/tcf/system/FreeBSD/regset.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-/*
- * This header file provides definition of REG_SET - a structure that can
- * hold values of target CPU registers.
- */
-
-#if defined(__FreeBSD__)
-# include <machine/reg.h>
- typedef struct reg REG_SET;
-#endif
diff --git a/agent/tcf/system/GNU/Linux/context-linux.c b/agent/tcf/system/GNU/Linux/context-linux.c
deleted file mode 100644
index b8b5b198..00000000
--- a/agent/tcf/system/GNU/Linux/context-linux.c
+++ /dev/null
@@ -1,1187 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-/*
- * This module handles process/thread OS contexts and their state machine.
- */
-
-#include <tcf/config.h>
-
-#if defined(__linux__)
-
-#if ENABLE_DebugContext && !ENABLE_ContextProxy
-
-#include <stdlib.h>
-#include <assert.h>
-#include <errno.h>
-#include <signal.h>
-#include <sched.h>
-#include <dirent.h>
-#include <asm/unistd.h>
-#include <sys/ptrace.h>
-#include <linux/kdev_t.h>
-#include <tcf/framework/context.h>
-#include <tcf/framework/events.h>
-#include <tcf/framework/errors.h>
-#include <tcf/framework/trace.h>
-#include <tcf/framework/myalloc.h>
-#include <tcf/framework/waitpid.h>
-#include <tcf/framework/signames.h>
-#include <tcf/services/breakpoints.h>
-#include <tcf/services/expressions.h>
-#include <tcf/services/memorymap.h>
-#include <tcf/services/runctrl.h>
-#include <tcf/services/tcf_elf.h>
-#include <tcf/system/GNU/Linux/regset.h>
-
-#if !defined(PTRACE_SETOPTIONS)
-#define PTRACE_SETOPTIONS 0x4200
-#define PTRACE_GETEVENTMSG 0x4201
-#define PTRACE_GETSIGINFO 0x4202
-#define PTRACE_SETSIGINFO 0x4203
-
-#define PTRACE_O_TRACESYSGOOD 0x00000001
-#define PTRACE_O_TRACEFORK 0x00000002
-#define PTRACE_O_TRACEVFORK 0x00000004
-#define PTRACE_O_TRACECLONE 0x00000008
-#define PTRACE_O_TRACEEXEC 0x00000010
-#define PTRACE_O_TRACEVFORKDONE 0x00000020
-#define PTRACE_O_TRACEEXIT 0x00000040
-
-#define PTRACE_EVENT_FORK 1
-#define PTRACE_EVENT_VFORK 2
-#define PTRACE_EVENT_CLONE 3
-#define PTRACE_EVENT_EXEC 4
-#define PTRACE_EVENT_VFORK_DONE 5
-#define PTRACE_EVENT_EXIT 6
-#endif
-
-#define USE_PTRACE_SYSCALL 0
-
-static const int PTRACE_FLAGS =
-#if USE_PTRACE_SYSCALL
- PTRACE_O_TRACESYSGOOD |
-#endif
- PTRACE_O_TRACECLONE |
- PTRACE_O_TRACEEXEC |
- PTRACE_O_TRACEFORK |
- PTRACE_O_TRACEVFORK |
- PTRACE_O_TRACEVFORKDONE |
- PTRACE_O_TRACEEXIT;
-
-typedef struct ContextExtensionLinux {
- pid_t pid;
- ContextAttachCallBack * attach_callback;
- void * attach_data;
- int attach_children;
- int ptrace_flags;
- int ptrace_event;
- int syscall_enter;
- int syscall_exit;
- int syscall_id;
- ContextAddress syscall_pc;
- ContextAddress loader_state;
- int end_of_step;
- REG_SET * regs; /* copy of context registers, updated when context stops */
- ErrorReport * regs_error; /* if not NULL, 'regs' is invalid */
- int regs_dirty; /* if not 0, 'regs' is modified and needs to be saved before context is continued */
- int pending_step;
- int tkill_cnt;
-} ContextExtensionLinux;
-
-static size_t context_extension_offset = 0;
-
-#define EXT(ctx) ((ContextExtensionLinux *)((char *)(ctx) + context_extension_offset))
-
-#include <tcf/system/pid-hash.h>
-
-static LINK pending_list = TCF_LIST_INIT(pending_list);
-static LINK detach_list = TCF_LIST_INIT(detach_list);
-
-static MemoryErrorInfo mem_err_info;
-
-static const char * event_name(int event) {
- switch (event) {
- case 0: return "none";
- case PTRACE_EVENT_FORK: return "fork";
- case PTRACE_EVENT_VFORK: return "vfork";
- case PTRACE_EVENT_CLONE: return "clone";
- case PTRACE_EVENT_EXEC: return "exec";
- case PTRACE_EVENT_VFORK_DONE: return "vfork-done";
- case PTRACE_EVENT_EXIT: return "exit";
- }
- trace(LOG_ALWAYS, "event_name(): unexpected event code %d", event);
- return "unknown";
-}
-
-const char * context_suspend_reason(Context * ctx) {
- static char reason[128];
-
- if (EXT(ctx)->end_of_step) return REASON_STEP;
- if (EXT(ctx)->ptrace_event != 0) {
- assert(ctx->signal == SIGTRAP);
- snprintf(reason, sizeof(reason), "Event: %s", event_name(EXT(ctx)->ptrace_event));
- return reason;
- }
- if (EXT(ctx)->syscall_enter) return "System Call";
- if (EXT(ctx)->syscall_exit) return "System Return";
- if (ctx->signal == SIGSTOP || ctx->signal == SIGTRAP) return REASON_USER_REQUEST;
- snprintf(reason, sizeof(reason), "Signal %d", ctx->signal);
- return reason;
-}
-
-int context_attach_self(void) {
- if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {
- int err = errno;
- trace(LOG_ALWAYS, "error: ptrace(PTRACE_TRACEME) failed: pid %d, error %d %s",
- getpid(), err, errno_to_str(err));
- errno = err;
- return -1;
- }
- return 0;
-}
-
-int context_attach(pid_t pid, ContextAttachCallBack * done, void * data, int mode) {
- Context * ctx = NULL;
- ContextExtensionLinux * ext = NULL;
-
- assert(done != NULL);
- trace(LOG_CONTEXT, "context: attaching pid %d", pid);
- if ((mode & CONTEXT_ATTACH_SELF) == 0 && ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) {
- int err = errno;
- trace(LOG_ALWAYS, "error: ptrace(PTRACE_ATTACH) failed: pid %d, error %d %s",
- pid, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- add_waitpid_process(pid);
- ctx = create_context(pid2id(pid, 0));
- ctx->mem = ctx;
- ctx->mem_access |= MEM_ACCESS_INSTRUCTION;
- ctx->mem_access |= MEM_ACCESS_DATA;
- ctx->mem_access |= MEM_ACCESS_USER;
- ctx->big_endian = big_endian_host();
- ext = EXT(ctx);
- ext->pid = pid;
- ext->attach_callback = done;
- ext->attach_data = data;
- ext->attach_children = (mode & CONTEXT_ATTACH_CHILDREN) != 0;
- list_add_first(&ctx->ctxl, &pending_list);
- /* TODO: context_attach works only for main task in a process */
- return 0;
-}
-
-int context_has_state(Context * ctx) {
- return ctx != NULL && ctx->parent != NULL;
-}
-
-int context_stop(Context * ctx) {
- ContextExtensionLinux * ext = EXT(ctx);
- trace(LOG_CONTEXT, "context:%s suspending ctx %#lx id %s",
- ctx->pending_intercept ? "" : " temporary", ctx, ctx->id);
- assert(is_dispatch_thread());
- assert(context_has_state(ctx));
- assert(!ctx->exited);
- assert(!ctx->exiting);
- assert(!ctx->stopped);
- assert(!ext->regs_dirty);
- if (ext->tkill_cnt > 4) {
- /* Check for zombies */
- int ch = 0;
- FILE * file = NULL;
- char file_name[FILE_PATH_SIZE];
- snprintf(file_name, sizeof(file_name), "/proc/%d/stat", ext->pid);
- if ((file = fopen(file_name, "r")) == NULL) return -1;
- while (ch != EOF && ch != ')') ch = fgetc(file);
- if (ch == EOF || fgetc(file) != ' ' || fgetc(file) == 'Z') {
- /* Zombie found */
- fclose(file);
- ctx->exiting = 1;
- return 0;
- }
- fclose(file);
- ext->tkill_cnt = 0;
- }
- if (tkill(ext->pid, SIGSTOP) < 0) {
- int err = errno;
- if (err == ESRCH) {
- ctx->exiting = 1;
- return 0;
- }
- trace(LOG_ALWAYS, "error: tkill(SIGSTOP) failed: ctx %#lx, id %s, error %d %s",
- ctx, ctx->id, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- ext->tkill_cnt++;
- return 0;
-}
-
-static int syscall_never_returns(Context * ctx) {
- if (EXT(ctx)->syscall_enter) {
- switch (EXT(ctx)->syscall_id) {
-#ifdef __NR_sigreturn
- case __NR_sigreturn:
- return 1;
-#endif
- }
- }
- return 0;
-}
-
-int context_continue(Context * ctx) {
- int signal = 0;
- ContextExtensionLinux * ext = EXT(ctx);
-
- assert(is_dispatch_thread());
- assert(ctx->stopped);
- assert(!ctx->pending_intercept);
- assert(!ext->pending_step);
- assert(!ctx->exited);
-
- if (skip_breakpoint(ctx, 0)) return 0;
-
- if (!ext->syscall_enter && !ext->ptrace_event) {
- while (ctx->pending_signals != 0) {
- while ((ctx->pending_signals & (1 << signal)) == 0) signal++;
- if (ctx->sig_dont_pass & (1 << signal)) {
- ctx->pending_signals &= ~(1 << signal);
- signal = 0;
- }
- else {
- break;
- }
- }
- assert(signal != SIGSTOP);
- assert(signal != SIGTRAP);
- }
-
- trace(LOG_CONTEXT, "context: resuming ctx %#lx, id %s, with signal %d", ctx, ctx->id, signal);
-#if defined(__i386__) || defined(__x86_64__)
- if (ext->regs->eflags & 0x100) {
- ext->regs->eflags &= ~0x100;
- ext->regs_dirty = 1;
- }
-#endif
- if (ext->regs_dirty) {
- if (ptrace(PTRACE_SETREGS, ext->pid, 0, ext->regs) < 0) {
- int err = errno;
- if (err == ESRCH) {
- ext->regs_dirty = 0;
- ctx->exiting = 1;
- send_context_started_event(ctx);
- return 0;
- }
- trace(LOG_ALWAYS, "error: ptrace(PTRACE_SETREGS) failed: ctx %#lx, id %s, error %d %s",
- ctx, ctx->id, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- ext->regs_dirty = 0;
- }
-#if USE_PTRACE_SYSCALL
- if (ptrace(PTRACE_SYSCALL, ext->pid, 0, signal) < 0) {
-#else
- if (ptrace(PTRACE_CONT, ext->pid, 0, signal) < 0) {
-#endif
- int err = errno;
- if (err == ESRCH) {
- ctx->exiting = 1;
- send_context_started_event(ctx);
- return 0;
- }
- trace(LOG_ALWAYS, "error: ptrace(PTRACE_CONT, ...) failed: ctx %#lx, id %s, error %d %s",
- ctx, ctx->id, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- ctx->pending_signals &= ~(1 << signal);
- if (syscall_never_returns(ctx)) {
- ext->syscall_enter = 0;
- ext->syscall_exit = 0;
- ext->syscall_id = 0;
- }
- send_context_started_event(ctx);
- return 0;
-}
-
-int context_single_step(Context * ctx) {
- ContextExtensionLinux * ext = EXT(ctx);
-
- assert(is_dispatch_thread());
- assert(context_has_state(ctx));
- assert(ctx->stopped);
- assert(!ctx->exited);
- assert(!ext->pending_step);
-
- if (skip_breakpoint(ctx, 1)) return 0;
-
- if (syscall_never_returns(ctx)) return context_continue(ctx);
- trace(LOG_CONTEXT, "context: single step ctx %#lx, id %s", ctx, ctx->id);
- if (ext->regs_dirty) {
- if (ptrace(PTRACE_SETREGS, ext->pid, 0, ext->regs) < 0) {
- int err = errno;
- if (err == ESRCH) {
- ext->regs_dirty = 0;
- ctx->exiting = 1;
- send_context_started_event(ctx);
- return 0;
- }
- trace(LOG_ALWAYS, "error: ptrace(PTRACE_SETREGS) failed: ctx %#lx, id %s, error %d %s",
- ctx, ctx->id, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- ext->regs_dirty = 0;
- }
- if (ptrace(PTRACE_SINGLESTEP, ext->pid, 0, 0) < 0) {
- int err = errno;
- if (err == ESRCH) {
- ctx->exiting = 1;
- send_context_started_event(ctx);
- return 0;
- }
- trace(LOG_ALWAYS, "error: ptrace(PTRACE_SINGLESTEP, ...) failed: ctx %#lx, id %s, error %d %s",
- ctx, ctx->id, err, errno_to_str(err));
- errno = err;
- return -1;
- }
- ext->pending_step = 1;
- send_context_started_event(ctx);
- return 0;
-}
-
-int context_resume(Context * ctx, int mode, ContextAddress range_start, ContextAddress range_end) {
- switch (mode) {
- case RM_RESUME:
- return context_continue(ctx);
- case RM_STEP_INTO:
- return context_single_step(ctx);
- case RM_TERMINATE:
- ctx->pending_signals |= 1 << SIGKILL;
- return context_continue(ctx);
- }
- errno = ERR_UNSUPPORTED;
- return -1;
-}
-
-int context_can_resume(Context * ctx, int mode) {
- switch (mode) {
- case RM_RESUME:
- return 1;
- case RM_STEP_INTO:
- case RM_TERMINATE:
- return context_has_state(ctx);
- }
- return 0;
-}
-
-int context_write_mem(Context * ctx, ContextAddress address, void * buf, size_t size) {
- ContextAddress word_addr;
- unsigned word_size = context_word_size(ctx);
- ContextExtensionLinux * ext = EXT(ctx);
- int error = 0;
-
- assert(word_size <= sizeof(unsigned long));
- assert(is_dispatch_thread());
- assert(!ctx->exited);
- trace(LOG_CONTEXT,
- "context: write memory ctx %#lx, id %s, address %#lx, size %zu",
- ctx, ctx->id, address, size);
- mem_err_info.error = 0;
- if (size == 0) return 0;
- if (check_breakpoints_on_memory_write(ctx, address, buf, size) < 0) return -1;
- for (word_addr = address & ~((ContextAddress)word_size - 1); word_addr < address + size; word_addr += word_size) {
- unsigned long word = 0;
- if (word_addr < address || word_addr + word_size > address + size) {
- unsigned i = 0;
- errno = 0;
- word = ptrace(PTRACE_PEEKDATA, ext->pid, (void *)word_addr, 0);
- if (errno != 0) {
- error = errno;
- trace(LOG_CONTEXT,
- "error: ptrace(PTRACE_PEEKDATA, ...) failed: ctx %#lx, id %s, addr %#lx, error %d %s",
- ctx, ctx->id, word_addr, error, errno_to_str(error));
- break;
- }
- for (i = 0; i < word_size; i++) {
- if (word_addr + i >= address && word_addr + i < address + size) {
- ((char *)&word)[i] = ((char *)buf)[word_addr + i - address];
- }
- }
- }
- else {
- memcpy(&word, (char *)buf + (word_addr - address), word_size);
- }
- if (ptrace(PTRACE_POKEDATA, ext->pid, (void *)word_addr, word) < 0) {
- error = errno;
- trace(LOG_ALWAYS,
- "error: ptrace(PTRACE_POKEDATA, ...) failed: ctx %#lx, id %s, addr %#lx, error %d %s",
- ctx, ctx->id, word_addr, error, errno_to_str(error));
- break;
- }
- }
- if (error) {
-#if ENABLE_ExtendedMemoryErrorReports
- size_t size_valid = 0;
- size_t size_error = word_size;
- if (word_addr > address) size_valid = (size_t)(word_addr - address);
- /* Find number of invalid bytes */
- /* Note: cannot write memory here, read instead */
- while (size_error < 0x1000 && size_valid + size_error < size) {
- errno = 0;
- ptrace(PTRACE_PEEKDATA, ext->pid, (void *)(word_addr + size_error), 0);
- if (errno != error) break;
- size_error += word_size;
- }
- mem_err_info.error = error;
- mem_err_info.size_valid = size_valid;
- mem_err_info.size_error = size_error;
-#endif
- errno = error;
- return -1;
- }
- return 0;
-}
-
-int context_read_mem(Context * ctx, ContextAddress address, void * buf, size_t size) {
- ContextAddress word_addr;
- unsigned word_size = context_word_size(ctx);
- ContextExtensionLinux * ext = EXT(ctx);
- size_t size_valid = 0;
- int error = 0;
-
- assert(word_size <= sizeof(unsigned long));
- assert(is_dispatch_thread());
- assert(!ctx->exited);
- trace(LOG_CONTEXT,
- "context: read memory ctx %#lx, id %s, address %#lx, size %zu",
- ctx, ctx->id, address, size);
- mem_err_info.error = 0;
- if (size == 0) return 0;
- for (word_addr = address & ~((ContextAddress)word_size - 1); word_addr < address + size; word_addr += word_size) {
- unsigned long word = 0;
- errno = 0;
- word = ptrace(PTRACE_PEEKDATA, ext->pid, (void *)word_addr, 0);
- if (errno != 0) {
- error = errno;
- trace(LOG_CONTEXT,
- "error: ptrace(PTRACE_PEEKDATA, ...) failed: ctx %#lx, id %s, addr %#lx, error %d %s",
- ctx, ctx->id, word_addr, error, errno_to_str(error));
- break;
- }
- if (word_addr < address || word_addr + word_size > address + size) {
- unsigned i = 0;
- for (i = 0; i < word_size; i++) {
- if (word_addr + i >= address && word_addr + i < address + size) {
- ((char *)buf)[word_addr + i - address] = ((char *)&word)[i];
- }
- }
- }
- else {
- memcpy((char *)buf + (word_addr - address), &word, word_size);
- }
- }
- if (word_addr > address) size_valid = (size_t)(word_addr - address);
- if (size_valid > size) size_valid = size;
- if (check_breakpoints_on_memory_read(ctx, address, buf, size_valid) < 0) return -1;
- if (error) {
-#if ENABLE_ExtendedMemoryErrorReports
- size_t size_error = word_size;
- /* Find number of unreadable bytes */
- while (size_error < 0x1000 && size_valid + size_error < size) {
- errno = 0;
- ptrace(PTRACE_PEEKDATA, ext->pid, (void *)(word_addr + size_error), 0);
- if (errno != error) break;
- size_error += word_size;
- }
- mem_err_info.error = error;
- mem_err_info.size_valid = size_valid;
- mem_err_info.size_error = size_error;
-#endif
- errno = error;
- return -1;
- }
- return 0;
-}
-
-#if ENABLE_ExtendedMemoryErrorReports
-int context_get_mem_error_info(MemoryErrorInfo * info) {
- if (mem_err_info.error == 0) {
- set_errno(ERR_OTHER, "Extended memory error info not available");
- return -1;
- }
- *info = mem_err_info;
- return 0;
-}
-#endif
-
-int context_write_reg(Context * ctx, RegisterDefinition * def, unsigned offs, unsigned size, void * buf) {
- ContextExtensionLinux * ext = EXT(ctx);
-
- assert(is_dispatch_thread());
- assert(context_has_state(ctx));
- assert(ctx->stopped);
- assert(!ctx->exited);
- assert(offs + size <= def->size);
-
- if (ext->regs_error) {
- set_error_report_errno(ext->regs_error);
- return -1;
- }
- memcpy((uint8_t *)ext->regs + def->offset + offs, buf, size);
- ext->regs_dirty = 1;
- return 0;
-}
-
-int context_read_reg(Context * ctx, RegisterDefinition * def, unsigned offs, unsigned size, void * buf) {
- ContextExtensionLinux * ext = EXT(ctx);
-
- assert(is_dispatch_thread());
- assert(context_has_state(ctx));
- assert(ctx->stopped);
- assert(!ctx->exited);
- assert(offs + size <= def->size);
-
- if (ext->regs_error) {
- set_error_report_errno(ext->regs_error);
- return -1;
- }
- memcpy(buf, (uint8_t *)ext->regs + def->offset + offs, size);
- return 0;
-}
-
-unsigned context_word_size(Context * ctx) {
- return sizeof(void *);
-}
-
-int context_get_canonical_addr(Context * ctx, ContextAddress addr,
- Context ** canonical_ctx, ContextAddress * canonical_addr,
- ContextAddress * block_addr, ContextAddress * block_size) {
- /* Direct mapping, page size is irrelevant */
- ContextAddress page_size = 0x100000;
- assert(is_dispatch_thread());
- *canonical_ctx = ctx->mem;
- if (canonical_addr != NULL) *canonical_addr = addr;
- if (block_addr != NULL) *block_addr = addr & ~(page_size - 1);
- if (block_size != NULL) *block_size = page_size;
- return 0;
-}
-
-Context * context_get_group(Context * ctx, int group) {
- static Context * cpu_group = NULL;
- switch (group) {
- case CONTEXT_GROUP_INTERCEPT:
- return ctx;
- case CONTEXT_GROUP_CPU:
- if (cpu_group == NULL) cpu_group = create_context("CPU");
- return cpu_group;
- }
- return ctx->mem;
-}
-
-int context_get_supported_bp_access_types(Context * ctx) {
- return 0;
-}
-
-int context_plant_breakpoint(ContextBreakpoint * bp) {
- errno = ERR_UNSUPPORTED;
- return -1;
-}
-
-int context_unplant_breakpoint(ContextBreakpoint * bp) {
- errno = ERR_UNSUPPORTED;
- return -1;
-}
-
-int context_get_memory_map(Context * ctx, MemoryMap * map) {
- char maps_file_name[FILE_PATH_SIZE];
- FILE * file = NULL;
-
- ctx = ctx->mem;
- assert(!ctx->exited);
- assert(map->region_cnt == 0);
-
- snprintf(maps_file_name, sizeof(maps_file_name), "/proc/%d/maps", EXT(ctx)->pid);
- if ((file = fopen(maps_file_name, "r")) == NULL) return -1;
- for (;;) {
- MemoryRegion * prev = NULL;
- unsigned long addr0 = 0;
- unsigned long addr1 = 0;
- unsigned long offset = 0;
- unsigned long dev_ma = 0;
- unsigned long dev_mi = 0;
- unsigned long inode = 0;
- char permissions[16];
- char file_name[FILE_PATH_SIZE];
- unsigned i = 0;
- int flags = 0;
-
- int cnt = fscanf(file, "%lx-%lx %s %lx %lx:%lx %ld",
- &addr0, &addr1, permissions, &offset, &dev_ma, &dev_mi, &inode);
- if (cnt == 0 || cnt == EOF) break;
-
- for (;;) {
- int ch = fgetc(file);
- if (ch == '\n' || ch == EOF) break;
- if (i < FILE_PATH_SIZE - 1 && (ch != ' ' || i > 0)) {
- file_name[i++] = ch;
- }
- }
- file_name[i++] = 0;
-
- if (map->region_cnt >= map->region_max) {
- map->region_max = map->region_max < 8 ? 8 : map->region_max * 2;
- map->regions = (MemoryRegion *)loc_realloc(map->regions, sizeof(MemoryRegion) * map->region_max);
- }
-
- for (i = 0; permissions[i]; i++) {
- switch (permissions[i]) {
- case 'r': flags |= MM_FLAG_R; break;
- case 'w': flags |= MM_FLAG_W; break;
- case 'x': flags |= MM_FLAG_X; break;
- }
- }
-
- if (map->region_cnt > 0) prev = map->regions + (map->region_cnt - 1);
-
- if (inode != 0 && file_name[0] && file_name[0] != '[') {
- MemoryRegion * r = map->regions + map->region_cnt++;
- memset(r, 0, sizeof(MemoryRegion));
- r->addr = addr0;
- r->size = addr1 - addr0;
- r->flags = flags;
- r->file_offs = offset;
- r->dev = MKDEV(dev_ma, dev_mi);
- r->ino = (ino_t)inode;
- r->file_name = loc_strdup(file_name);
- }
- else if (file_name[0] == 0 && prev != NULL && prev->addr + prev->size == addr0) {
- MemoryRegion * r = map->regions + map->region_cnt++;
- memset(r, 0, sizeof(MemoryRegion));
- r->bss = 1;
- r->addr = addr0;
- r->size = addr1 - addr0;
- r->flags = flags;
- r->file_offs = prev->file_offs + prev->size;
- r->dev = prev->dev;
- r->ino = prev->ino;
- r->file_name = loc_strdup(prev->file_name);
- }
- }
- fclose(file);
- return 0;
-}
-
-static Context * find_pending(pid_t pid) {
- LINK * l = pending_list.next;
- while (l != &pending_list) {
- Context * c = ctxl2ctxp(l);
- if (EXT(c)->pid == pid) {
- list_remove(&c->ctxl);
- return c;
- }
- l = l->next;
- }
- return NULL;
-}
-
-static void event_pid_exited(pid_t pid, int status, int signal) {
- Context * ctx;
-
- ctx = context_find_from_pid(pid, 1);
- if (ctx == NULL) {
- ctx = find_pending(pid);
- if (ctx == NULL) {
- trace(LOG_EVENTS, "event: ctx not found, pid %d, exit status %d, term signal %d", pid, status, signal);
- }
- else {
- assert(ctx->ref_count == 0);
- if (EXT(ctx)->attach_callback != NULL) {
- if (status == 0) status = EINVAL;
- EXT(ctx)->attach_callback(status, ctx, EXT(ctx)->attach_data);
- }
- assert(list_is_empty(&ctx->children));
- assert(ctx->parent == NULL);
- ctx->exited = 1;
- ctx->ref_count = 1;
- context_unlock(ctx);
- }
- }
- else {
- /* Note: ctx->exiting should be 1 here. However, PTRACE_EVENT_EXIT can be lost by PTRACE because of racing
- * between PTRACE_CONT (or PTRACE_SYSCALL) and SIGTRAP/PTRACE_EVENT_EXIT. So, ctx->exiting can be 0.
- */
- if (EXT(ctx->parent)->pid == pid) ctx = ctx->parent;
- trace(LOG_EVENTS, "event: ctx %#lx, pid %d, exit status %d, term signal %d", ctx, pid, status, signal);
- assert(EXT(ctx)->attach_callback == NULL);
- assert(!ctx->exited);
- ctx->exiting = 1;
- if (ctx->stopped) send_context_started_event(ctx);
- if (!list_is_empty(&ctx->children)) {
- LINK * l = ctx->children.next;
- while (l != &ctx->children) {
- Context * c = cldl2ctxp(l);
- l = l->next;
- assert(c->parent == ctx);
- if (!c->exited) {
- c->exiting = 1;
- if (c->stopped) send_context_started_event(c);
- release_error_report(EXT(c)->regs_error);
- loc_free(EXT(c)->regs);
- EXT(c)->regs_error = NULL;
- EXT(c)->regs = NULL;
- send_context_exited_event(c);
- }
- }
- }
- release_error_report(EXT(ctx)->regs_error);
- loc_free(EXT(ctx)->regs);
- EXT(ctx)->regs_error = NULL;
- EXT(ctx)->regs = NULL;
- send_context_exited_event(ctx);
- }
- assert(context_find_from_pid(pid, 1) == NULL);
- assert(context_find_from_pid(pid, 0) == NULL);
-}
-
-#if !USE_PTRACE_SYSCALL
-# define get_syscall_id(ctx) 0
-#elif defined(__x86_64__)
-# define get_syscall_id(ctx) (EXT(ctx)->regs->orig_rax)
-#elif defined(__i386__)
-# define get_syscall_id(ctx) (EXT(ctx)->regs->orig_eax)
-#else
-# error "get_syscall_id() is not implemented for CPU other then X86"
-#endif
-
-static unsigned long get_child_pid(pid_t parent_pid) {
- unsigned long child_pid = 0;
- DIR * dir = NULL;
- char task_file_name[FILE_PATH_SIZE];
- snprintf(task_file_name, sizeof(task_file_name), "/proc/%d/task", parent_pid);
- dir = opendir(task_file_name);
- if (dir == NULL) {
- trace(LOG_ALWAYS, "error: opendir(%s) failed; error %d %s",
- task_file_name, errno, errno_to_str(errno));
- }
- else {
- struct dirent * e;
- for (;;) {
- int n = 0;
- e = readdir(dir);
- if (e == NULL) break;
- n = atoi(e->d_name);
- if (n != 0 && context_find_from_pid(n, 1) == NULL) {
- child_pid = n;
- break;
- }
- }
- closedir(dir);
- }
- return child_pid;
-}
-
-static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) {
- int stopped_by_exception = 0;
- unsigned long msg = 0;
- Context * ctx = NULL;
- ContextExtensionLinux * ext = NULL;
-
- trace(LOG_EVENTS, "event: pid %d stopped, signal %d, event %s", pid, signal, event_name(event));
-
- ctx = context_find_from_pid(pid, 1);
-
- if (ctx == NULL) {
- ctx = find_pending(pid);
- if (ctx != NULL) {
- Context * prs = ctx;
- assert(prs->ref_count == 0);
- ctx = create_context(pid2id(pid, pid));
- EXT(ctx)->pid = pid;
- EXT(ctx)->regs = (REG_SET *)loc_alloc(sizeof(REG_SET));
- ctx->pending_intercept = 1;
- ctx->mem = prs;
- ctx->big_endian = prs->big_endian;
- EXT(ctx)->attach_children = EXT(prs)->attach_children;
- (ctx->parent = prs)->ref_count++;
- list_add_last(&ctx->cldl, &prs->children);
- link_context(prs);
- link_context(ctx);
- send_context_created_event(prs);
- send_context_created_event(ctx);
- if (EXT(prs)->attach_callback) {
- EXT(prs)->attach_callback(0, prs, EXT(prs)->attach_data);
- EXT(prs)->attach_callback = NULL;
- EXT(prs)->attach_data = NULL;
- }
- }
- }
-
- if (ctx == NULL) {
- ctx = context_find_from_pid(pid, 0);
- if (ctx != NULL) {
- /* Fork child that we don't want to attach */
- unplant_breakpoints(ctx);
- assert(ctx->ref_count == 1);
- ctx->exited = 1;
- if (ptrace((enum __ptrace_request)PTRACE_DETACH, pid, 0, 0) < 0) {
- trace(LOG_ALWAYS, "error: ptrace(PTRACE_DETACH) failed: pid %d, error %d %s",
- pid, errno, errno_to_str(errno));
- }
- list_remove(ctx2pidlink(ctx));
- context_unlock(ctx);
- }
- detach_waitpid_process();
- return;
- }
-
- ext = EXT(ctx);
- assert(!ctx->exited);
- assert(!ext->attach_callback);
- ext->tkill_cnt = 0;
- if (ext->ptrace_flags == 0) {
- if (ptrace((enum __ptrace_request)PTRACE_SETOPTIONS, ext->pid, 0, PTRACE_FLAGS) < 0 && errno != ESRCH) {
- int err = errno;
- trace(LOG_ALWAYS, "error: ptrace(PTRACE_SETOPTIONS) failed: pid %d, error %d %s",
- ext->pid, err, errno_to_str(err));
- }
- else {
- ext->ptrace_flags = PTRACE_FLAGS;
- }
- }
-
- switch (event) {
- case PTRACE_EVENT_FORK:
- case PTRACE_EVENT_VFORK:
- case PTRACE_EVENT_CLONE:
- if (ptrace((enum __ptrace_request)PTRACE_GETEVENTMSG, pid, 0, &msg) < 0) {
- if (errno == ESRCH) {
- msg = SIGKILL;
- }
- else {
- trace(LOG_ALWAYS, "error: ptrace(PTRACE_GETEVENTMSG) failed; pid %d, error %d %s",
- pid, errno, errno_to_str(errno));
- break;
- }
- }
- {
- Context * prs2 = NULL;
- Context * ctx2 = NULL;
- /* Check the thread is not killed already by SIGKILL */
- if (msg == SIGKILL) {
- unsigned long child_pid = get_child_pid(EXT(ctx->parent)->pid);
- if (child_pid) {
- msg = child_pid;
- }
- else {
- trace(LOG_ALWAYS, "cannot trace %s - aborted by SIGKILL", event_name(event));
- break;
- }
- }
- assert(msg != 0);
- add_waitpid_process(msg);
- if (event == PTRACE_EVENT_CLONE) {
- /* TODO: using the PTRACE_EVENT_CLONE to determine if the new context is a thread is not correct.
- * The only way I know of is to look at the Tgid field of /proc/<pid>/status */
- prs2 = ctx->parent;
- }
- else {
- prs2 = create_context(pid2id(msg, 0));
- EXT(prs2)->pid = msg;
- EXT(prs2)->attach_children = ext->attach_children;
- prs2->mem = prs2;
- prs2->mem_access |= MEM_ACCESS_INSTRUCTION;
- prs2->mem_access |= MEM_ACCESS_DATA;
- prs2->mem_access |= MEM_ACCESS_USER;
- prs2->big_endian = ctx->parent->big_endian;
- (prs2->creator = ctx)->ref_count++;
- prs2->sig_dont_stop = ctx->sig_dont_stop;
- prs2->sig_dont_pass = ctx->sig_dont_pass;
- link_context(prs2);
- clone_breakpoints_on_process_fork(ctx, prs2);
- if (!ext->attach_children) {
- list_remove(&prs2->ctxl);
- list_add_first(&prs2->ctxl, &detach_list);
- break;
- }
- send_context_created_event(prs2);
- }
-
- ctx2 = create_context(pid2id(msg, EXT(prs2)->pid));
- EXT(ctx2)->pid = msg;
- EXT(ctx2)->attach_children = EXT(prs2)->attach_children;
- EXT(ctx2)->regs = (REG_SET *)loc_alloc(sizeof(REG_SET));
- ctx2->mem = prs2;
- ctx2->big_endian = prs2->big_endian;
- ctx2->sig_dont_stop = ctx->sig_dont_stop;
- ctx2->sig_dont_pass = ctx->sig_dont_pass;
- (ctx2->creator = ctx)->ref_count++;
- (ctx2->parent = prs2)->ref_count++;
- list_add_last(&ctx2->cldl, &prs2->children);
- link_context(ctx2);
- trace(LOG_EVENTS, "event: new context 0x%x, id %s", ctx2, ctx2->id);
- send_context_created_event(ctx2);
- }
- break;
- case PTRACE_EVENT_EXEC:
- send_context_changed_event(ctx);
- memory_map_event_mapping_changed(ctx->mem);
- break;
- case PTRACE_EVENT_EXIT:
- {
- /* SIGKILL can override PTRACE_EVENT_CLONE event with PTRACE_EVENT_EXIT */
- unsigned long child_pid = get_child_pid(EXT(ctx->parent)->pid);
- if (child_pid) {
- Context * prs = ctx->parent;
- Context * ctx2 = create_context(pid2id(child_pid, EXT(prs)->pid));
- EXT(ctx2)->pid = child_pid;
- EXT(ctx2)->attach_children = EXT(prs)->attach_children;
- EXT(ctx2)->regs = (REG_SET *)loc_alloc(sizeof(REG_SET));
- ctx2->mem = prs;
- ctx2->big_endian = prs->big_endian;
- ctx2->sig_dont_stop = ctx->sig_dont_stop;
- ctx2->sig_dont_pass = ctx->sig_dont_pass;
- ctx2->exiting = 1;
- (ctx2->creator = ctx)->ref_count++;
- (ctx2->parent = prs)->ref_count++;
- list_add_last(&ctx2->cldl, &prs->children);
- link_context(ctx2);
- trace(LOG_EVENTS, "event: new context 0x%x, id %s", ctx2, ctx2->id);
- send_context_created_event(ctx2);
- event_pid_stopped(child_pid, SIGTRAP, 0, 0);
- add_waitpid_process(child_pid);
- }
- }
- ctx->exiting = 1;
- ext->regs_dirty = 0;
- break;
- }
-
- if (signal != SIGSTOP && signal != SIGTRAP) {
- assert(signal < 32);
- ctx->pending_signals |= 1 << signal;
- if ((ctx->sig_dont_stop & (1 << signal)) == 0) {
- ctx->pending_intercept = 1;
- stopped_by_exception = 1;
- }
- }
-
- if (ctx->stopped) {
- if (event != PTRACE_EVENT_EXEC) send_context_changed_event(ctx);
- }
- else {
- ContextAddress pc0 = 0;
- ContextAddress pc1 = 0;
-
- assert(!ext->regs_dirty);
-
- ext->end_of_step = 0;
- ext->ptrace_event = event;
- ctx->signal = signal;
- ctx->stopped_by_bp = 0;
- ctx->stopped_by_exception = stopped_by_exception;
- ctx->stopped = 1;
-
- if (ext->regs_error) {
- release_error_report(ext->regs_error);
- ext->regs_error = NULL;
- }
- else {
- pc0 = get_regs_PC(ctx);
- }
-
- if (ptrace(PTRACE_GETREGS, ext->pid, 0, ext->regs) < 0) {
- assert(errno != 0);
- if (errno == ESRCH) {
- ctx->stopped = 0;
- ctx->exiting = 1;
- return;
- }
- ext->regs_error = get_error_report(errno);
- trace(LOG_ALWAYS, "error: ptrace(PTRACE_GETREGS) failed; pid %d, error %d %s",
- ext->pid, errno, errno_to_str(errno));
- }
- else {
- pc1 = get_regs_PC(ctx);
- }
-
- if (syscall && !ext->regs_error) {
- if (!ext->syscall_enter) {
- ext->syscall_id = get_syscall_id(ctx);
- ext->syscall_pc = pc1;
- ext->syscall_enter = 1;
- ext->syscall_exit = 0;
- trace(LOG_EVENTS, "event: pid %d enter sys call %d, PC = %#lx",
- pid, ext->syscall_id, ext->syscall_pc);
- }
- else {
- if (ext->syscall_pc != pc1) {
- trace(LOG_ALWAYS, "Invalid PC at sys call exit: pid %d, sys call %d, PC %#lx, expected PC %#lx",
- ext->pid, ext->syscall_id, pc1, ext->syscall_pc);
- }
- trace(LOG_EVENTS, "event: pid %d exit sys call %d, PC = %#lx",
- pid, ext->syscall_id, pc1);
- switch (ext->syscall_id) {
- case __NR_mmap:
- case __NR_munmap:
-#ifdef __NR_mmap2
- case __NR_mmap2:
-#endif
- case __NR_mremap:
- case __NR_remap_file_pages:
- memory_map_event_mapping_changed(ctx->mem);
- break;
- }
- ext->syscall_enter = 0;
- ext->syscall_exit = 1;
- }
- }
- else {
- if (!ext->syscall_enter || ext->regs_error || pc0 != pc1) {
- ext->syscall_enter = 0;
- ext->syscall_exit = 0;
- ext->syscall_id = 0;
- ext->syscall_pc = 0;
- }
- trace(LOG_EVENTS, "event: pid %d stopped at PC = %#lx", pid, pc1);
- }
-
- if (signal == SIGTRAP && event == 0 && !syscall) {
- size_t break_size = 0;
- get_break_instruction(ctx, &break_size);
- ctx->stopped_by_bp = !ext->regs_error && is_breakpoint_address(ctx, pc1 - break_size);
- ext->end_of_step = !ctx->stopped_by_bp && ext->pending_step;
- if (ctx->stopped_by_bp) set_regs_PC(ctx, pc1 - break_size);
- }
- ext->pending_step = 0;
- send_context_stopped_event(ctx);
- }
-}
-
-static void waitpid_listener(int pid, int exited, int exit_code, int signal, int event_code, int syscall, void * args) {
- if (exited) {
- event_pid_exited(pid, exit_code, signal);
- }
- else {
- event_pid_stopped(pid, signal, event_code, syscall);
- }
-}
-
-#if SERVICE_Expressions && ENABLE_ELF
-
-static int expression_identifier_callback(Context * ctx, int frame, char * name, Value * v) {
- if (ctx == NULL) return 0;
- if (strcmp(name, "$loader_brk") == 0) {
- v->address = elf_get_debug_structure_address(ctx, NULL);
- v->type_class = TYPE_CLASS_POINTER;
- v->size = context_word_size(ctx);
- if (v->address != 0) {
- v->big_endian = ctx->big_endian;
- switch (v->size) {
- case 4: v->address += 8; break;
- case 8: v->address += 16; break;
- default: assert(0);
- }
- v->remote = 1;
- }
- else {
- set_value(v, NULL, v->size, 0);
- }
- return 1;
- }
- if (strcmp(name, "$loader_state") == 0) {
- v->address = elf_get_debug_structure_address(ctx, NULL);
- v->type_class = TYPE_CLASS_CARDINAL;
- v->size = context_word_size(ctx);
- if (v->address != 0) {
- switch (v->size) {
- case 4: v->address += 12; break;
- case 8: v->address += 24; break;
- default: assert(0);
- }
- }
- v->remote = 1;
- return 1;
- }
- return 0;
-}
-
-static void eventpoint_at_loader(Context * ctx, void * args) {
- typedef enum { RT_CONSISTENT, RT_ADD, RT_DELETE } r_state;
- ELF_File * file = NULL;
- ContextAddress addr = elf_get_debug_structure_address(ctx, &file);
- unsigned size = context_word_size(ctx);
- ContextAddress state = 0;
- ContextExtensionLinux * ext = NULL;
-
-
- if (ctx->parent != NULL) ctx = ctx->parent;
- ext = EXT(ctx);
-
- if (addr != 0) {
- switch (size) {
- case 4: addr += 12; break;
- case 8: addr += 24; break;
- default: assert(0);
- }
- if (elf_read_memory_word(ctx, file, addr, &state) < 0) {
- int error = errno;
- trace(LOG_ALWAYS, "Can't read loader state flag: %d %s", error, errno_to_str(error));
- ctx->pending_intercept = 1;
- ext->loader_state = 0;
- return;
- }
- }
-
- switch (state) {
- case RT_CONSISTENT:
- if (ext->loader_state == RT_ADD) {
- memory_map_event_module_loaded(ctx);
- }
- else if (ext->loader_state == RT_DELETE) {
- memory_map_event_module_unloaded(ctx);
- }
- break;
- case RT_ADD:
- break;
- case RT_DELETE:
- /* TODO: need to call memory_map_event_code_section_ummapped() */
- break;
- }
- ext->loader_state = state;
-}
-
-#endif /* SERVICE_Expressions && ENABLE_ELF */
-
-static void eventpoint_at_main(Context * ctx, void * args) {
- send_context_changed_event(ctx->mem);
- memory_map_event_mapping_changed(ctx->mem);
- suspend_debug_context(ctx);
-}
-
-void init_contexts_sys_dep(void) {
- context_extension_offset = context_extension(sizeof(ContextExtensionLinux));
- add_waitpid_listener(waitpid_listener, NULL);
- ini_context_pid_hash();
-#if SERVICE_Expressions && ENABLE_ELF
- add_identifier_callback(expression_identifier_callback);
- create_eventpoint("$loader_brk", NULL, eventpoint_at_loader, NULL);
-#endif /* SERVICE_Expressions && ENABLE_ELF */
- create_eventpoint("main", NULL, eventpoint_at_main, NULL);
-}
-
-#endif /* if ENABLE_DebugContext */
-#endif /* __linux__ */
diff --git a/agent/tcf/system/GNU/Linux/regset.h b/agent/tcf/system/GNU/Linux/regset.h
deleted file mode 100644
index 9c6474e3..00000000
--- a/agent/tcf/system/GNU/Linux/regset.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-/*
- * This header file provides definition of REG_SET - a structure that can
- * hold values of target CPU registers.
- */
-
-#if defined(__linux__)
-# include <sys/user.h>
- typedef struct user_regs_struct REG_SET;
-#endif
diff --git a/agent/tcf/system/MinGW/regset.h b/agent/tcf/system/MinGW/regset.h
deleted file mode 100644
index fb4eab83..00000000
--- a/agent/tcf/system/MinGW/regset.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-/*
- * This header file provides definition of REG_SET - a structure that can
- * hold values of target CPU registers.
- */
-
-#if defined(WIN32)
- typedef CONTEXT REG_SET;
-#endif
diff --git a/agent/tcf/system/Msys/regset.h b/agent/tcf/system/Msys/regset.h
deleted file mode 100644
index fb4eab83..00000000
--- a/agent/tcf/system/Msys/regset.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-/*
- * This header file provides definition of REG_SET - a structure that can
- * hold values of target CPU registers.
- */
-
-#if defined(WIN32)
- typedef CONTEXT REG_SET;
-#endif
diff --git a/agent/tcf/system/VxWorks/context-vxworks.c b/agent/tcf/system/VxWorks/context-vxworks.c
deleted file mode 100644
index 18fb927d..00000000
--- a/agent/tcf/system/VxWorks/context-vxworks.c
+++ /dev/null
@@ -1,782 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-/*
- * This module handles process/thread OS contexts and their state machine.
- */
-
-#include <tcf/config.h>
-
-#if defined(_WRS_KERNEL)
-
-#if ENABLE_DebugContext && !ENABLE_ContextProxy
-
-#include <stdlib.h>
-#include <assert.h>
-#include <errno.h>
-#include <signal.h>
-#include <tcf/framework/mdep-threads.h>
-#include <tcf/framework/events.h>
-#include <tcf/framework/errors.h>
-#include <tcf/framework/trace.h>
-#include <tcf/framework/myalloc.h>
-#include <tcf/framework/waitpid.h>
-#include <tcf/framework/signames.h>
-#include <tcf/services/breakpoints.h>
-#include <tcf/services/memorymap.h>
-#include <tcf/system/VxWorks/context-vxworks.h>
-
-/* TODO: VxWorks RTP support */
-
-#include <moduleLib.h>
-#include <taskHookLib.h>
-#include <spinLockLib.h>
-#include <private/vxdbgLibP.h>
-
-#define TRACE_EVENT_STEP 2
-
-typedef struct ContextExtensionVxWorks {
- pid_t pid;
- VXDBG_BP_INFO bp_info; /* breakpoint information */
- pid_t bp_pid; /* process or thread that hit breakpoint */
- int event;
- REG_SET * regs; /* copy of context registers, updated when context stops */
- ErrorReport * regs_error; /* if not NULL, 'regs' is invalid */
- int regs_dirty; /* if not 0, 'regs' is modified and needs to be saved before context is continued */
-} ContextExtensionVxWorks;
-
-static size_t context_extension_offset = 0;
-
-#define EXT(ctx) ((ContextExtensionVxWorks *)((char *)(ctx) + context_extension_offset))
-
-#include <tcf/system/pid-hash.h>
-
-#define EVENT_HOOK_BREAKPOINT 2
-#define EVENT_HOOK_STEP_DONE 3
-#define EVENT_HOOK_STOP 4
-#define EVENT_HOOK_TASK_ADD 5
-
-struct event_info {
- int event;
- VXDBG_CTX current_ctx; /* context that hit breakpoint */
- VXDBG_CTX stopped_ctx; /* context stopped by the breakpoint */
- REG_SET regs; /* task registers before exception */
- UINT32 addr; /* breakpoint addr */
- int bp_info_ok; /* breakpoint information available */
- VXDBG_BP_INFO bp_info; /* breakpoint information */
-};
-
-static VXDBG_CLNT_ID vxdbg_clnt_id = 0;
-
-#define MAX_EVENTS 64
-static struct event_info events[MAX_EVENTS];
-static int events_cnt = 0;
-static int events_inp = 0;
-static int events_out = 0;
-static int events_buf_overflow = 0;
-static spinlockIsr_t events_lock;
-static VX_COUNTING_SEMAPHORE(events_signal_mem);
-static SEM_ID events_signal;
-static pthread_t events_thread;
-static Context * parent_ctx = NULL;
-static MemoryErrorInfo mem_err_info;
-
-const char * context_suspend_reason(Context * ctx) {
- if (EXT(ctx)->event == TRACE_EVENT_STEP) return REASON_STEP;
- return REASON_USER_REQUEST;
-}
-
-static struct event_info * event_info_alloc(int event) {
- int nxt;
- struct event_info * info;
- SPIN_LOCK_ISR_TAKE(&events_lock);
- if (events_buf_overflow) {
- SPIN_LOCK_ISR_GIVE(&events_lock);
- return NULL;
- }
- info = events + events_inp;
- nxt = (events_inp + 1) % MAX_EVENTS;
- if (nxt == events_out) {
- events_buf_overflow = 1;
- semGive(events_signal);
- SPIN_LOCK_ISR_GIVE(&events_lock);
- return NULL;
- }
- memset(info, 0, sizeof(struct event_info));
- info->event = event;
- events_inp = nxt;
- events_cnt++;
- return info;
-}
-
-static void event_info_post(struct event_info * info) {
- assert(info != NULL);
- semGive(events_signal);
- SPIN_LOCK_ISR_GIVE(&events_lock);
-}
-
-typedef struct AttachDoneArgs {
- pid_t pid;
- ContextAttachCallBack * done;
- void * data;
-} AttachDoneArgs;
-
-static void event_attach_done(void * x) {
- AttachDoneArgs * args = (AttachDoneArgs *)x;
- if (context_find_from_pid(args->pid, 0) != NULL) {
- args->done(ERR_ALREADY_ATTACHED, NULL, args->data);
- }
- else {
- Context * ctx = NULL;
- if (parent_ctx == NULL) {
- pid_t pid = taskIdSelf();
- parent_ctx = create_context(pid2id(pid, 0));
- EXT(parent_ctx)->pid = pid;
- parent_ctx->mem = parent_ctx;
- parent_ctx->mem_access |= MEM_ACCESS_INSTRUCTION;
- parent_ctx->mem_access |= MEM_ACCESS_DATA;
- parent_ctx->big_endian = big_endian_host();
- link_context(parent_ctx);
- send_context_created_event(parent_ctx);
- }
- assert(parent_ctx->ref_count > 0);
- ctx = create_context(pid2id(args->pid, EXT(parent_ctx)->pid));
- EXT(ctx)->pid = args->pid;
- EXT(ctx)->regs = (REG_SET *)loc_alloc(sizeof(REG_SET));
- ctx->mem = parent_ctx;
- ctx->big_endian = parent_ctx->big_endian;
- (ctx->parent = parent_ctx)->ref_count++;
- list_add_last(&ctx->cldl, &parent_ctx->children);
- link_context(ctx);
- trace(LOG_CONTEXT, "context: attached: ctx %#lx, id %#x", ctx, EXT(ctx)->pid);
- send_context_created_event(ctx);
- args->done(0, ctx, args->data);
- if (taskIsStopped(args->pid)) {
- struct event_info * info;
- ctx->pending_intercept = 1;
- info = event_info_alloc(EVENT_HOOK_STOP);
- if (info != NULL) {
- info->stopped_ctx.ctxId = args->pid;
- event_info_post(info);
- }
- }
- }
- loc_free(x);
-}
-
-int context_attach(pid_t pid, ContextAttachCallBack * done, void * data, int mode) {
- AttachDoneArgs * args = (AttachDoneArgs *)loc_alloc(sizeof(AttachDoneArgs));
-
- assert(done != NULL);
- assert((mode & CONTEXT_ATTACH_SELF) == 0);
- args->pid = pid;
- args->done = done;
- args->data = data;
- post_event(event_attach_done, args);
-
- return 0;
-}
-
-int context_has_state(Context * ctx) {
- return ctx != NULL && ctx->parent != NULL;
-}
-
-int context_stop(Context * ctx) {
- ContextExtensionVxWorks * ext = EXT(ctx);
- struct event_info * info;
- VXDBG_CTX vxdbg_ctx;
-
- assert(is_dispatch_thread());
- assert(ctx->parent != NULL);
- assert(!ctx->stopped);
- assert(!ctx->exited);
- assert(!ext->regs_dirty);
- if (ctx->pending_intercept) {
- trace(LOG_CONTEXT, "context: stop ctx %#lx, id %#x", ctx, ext->pid);
- }
- else {
- trace(LOG_CONTEXT, "context: temporary stop ctx %#lx, id %#x", ctx, ext->pid);
- }
-
- taskLock();
- if (taskIsStopped(ext->pid)) {
- /* Workaround for situation when a task was stopped without notifying TCF agent */
- int n = 0;
- SPIN_LOCK_ISR_TAKE(&events_lock);
- n = events_cnt;
- SPIN_LOCK_ISR_GIVE(&events_lock);
- if (n > 0) {
- trace(LOG_CONTEXT, "context: already stopped ctx %#lx, id %#x", ctx, ext->pid);
- taskUnlock();
- return 0;
- }
- }
- else {
- vxdbg_ctx.ctxId = ext->pid;
- vxdbg_ctx.ctxType = VXDBG_CTX_TASK;
- if (vxdbgStop(vxdbg_clnt_id, &vxdbg_ctx) != OK) {
- int error = errno;
- taskUnlock();
- if (error == S_vxdbgLib_INVALID_CTX) return 0;
- trace(LOG_ALWAYS, "context: can't stop ctx %#lx, id %#x: %s",
- ctx, ext->pid, errno_to_str(error));
- return -1;
- }
- }
- assert(taskIsStopped(ext->pid));
- info = event_info_alloc(EVENT_HOOK_STOP);
- if (info != NULL) {
- info->stopped_ctx.ctxId = ext->pid;
- event_info_post(info);
- }
- taskUnlock();
- return 0;
-}
-
-static int kill_context(Context * ctx) {
- ContextExtensionVxWorks * ext = EXT(ctx);
-
- assert(ctx->stopped);
- assert(ctx->parent != NULL);
-
- if (taskDelete(ext->pid) != OK) {
- int error = errno;
- trace(LOG_ALWAYS, "context: can't kill ctx %#lx, id %#x: %s",
- ctx, ext->pid, errno_to_str(error));
- return -1;
- }
- send_context_started_event(ctx);
- trace(LOG_CONTEXT, "context: killed ctx %#lx, id %#x", ctx, ext->pid);
- release_error_report(ext->regs_error);
- loc_free(ext->regs);
- ext->regs_error = NULL;
- ext->regs = NULL;
- send_context_exited_event(ctx);
- return 0;
-}
-
-int context_continue(Context * ctx) {
- ContextExtensionVxWorks * ext = EXT(ctx);
- VXDBG_CTX vxdbg_ctx;
-
- assert(is_dispatch_thread());
- assert(ctx->parent != NULL);
- assert(ctx->stopped);
- assert(!ctx->pending_intercept);
- assert(!ctx->exited);
- assert(taskIsStopped(ext->pid));
-
- trace(LOG_CONTEXT, "context: continue ctx %#lx, id %#x", ctx, ext->pid);
-
- if (ext->regs_dirty) {
- if (taskRegsSet(ext->pid, ext->regs) != OK) {
- int error = errno;
- trace(LOG_ALWAYS, "context: can't set regs ctx %#lx, id %#x: %s",
- ctx, ext->pid, errno_to_str(error));
- return -1;
- }
- ext->regs_dirty = 0;
- }
-
- vxdbg_ctx.ctxId = ext->pid;
- vxdbg_ctx.ctxType = VXDBG_CTX_TASK;
- taskLock();
- if (vxdbgCont(vxdbg_clnt_id, &vxdbg_ctx) != OK) {
- int error = errno;
- taskUnlock();
- trace(LOG_ALWAYS, "context: can't continue ctx %#lx, id %#x: %s",
- ctx, ext->pid, errno_to_str(error));
- return -1;
- }
- assert(!taskIsStopped(ext->pid));
- taskUnlock();
- send_context_started_event(ctx);
- return 0;
-}
-
-int context_single_step(Context * ctx) {
- ContextExtensionVxWorks * ext = EXT(ctx);
- VXDBG_CTX vxdbg_ctx;
-
- assert(is_dispatch_thread());
- assert(context_has_state(ctx));
- assert(ctx->parent != NULL);
- assert(ctx->stopped);
- assert(!ctx->exited);
- assert(taskIsStopped(ext->pid));
-
- trace(LOG_CONTEXT, "context: single step ctx %#lx, id %#x", ctx, ext->pid);
-
- if (ext->regs_dirty) {
- if (taskRegsSet(ext->pid, ext->regs) != OK) {
- int error = errno;
- trace(LOG_ALWAYS, "context: can't set regs ctx %#lx, id %#x: %s",
- ctx, ext->pid, errno_to_str(error));
- return -1;
- }
- ext->regs_dirty = 0;
- }
-
- vxdbg_ctx.ctxId = ext->pid;
- vxdbg_ctx.ctxType = VXDBG_CTX_TASK;
- taskLock();
- if (vxdbgStep(vxdbg_clnt_id, &vxdbg_ctx, NULL, NULL) != OK) {
- int error = errno;
- taskUnlock();
- trace(LOG_ALWAYS, "context: can't step ctx %#lx, id %#x: %d",
- ctx, ext->pid, errno_to_str(error));
- return -1;
- }
- taskUnlock();
- send_context_started_event(ctx);
- return 0;
-}
-
-static int context_terminate(Context * ctx) {
- ContextExtensionVxWorks * ext = EXT(ctx);
- VXDBG_CTX vxdbg_ctx;
-
- assert(is_dispatch_thread());
- assert(ctx->parent != NULL);
- assert(ctx->stopped);
- assert(!ctx->pending_intercept);
- assert(!ctx->exited);
- assert(taskIsStopped(ext->pid));
-
- trace(LOG_CONTEXT, "context: terminate ctx %#lx, id %#x", ctx, ext->pid);
-
- if (ext->regs_dirty) {
- taskRegsSet(ext->pid, ext->regs);
- ext->regs_dirty = 0;
- }
-
- return kill_context(ctx);
-}
-
-int context_resume(Context * ctx, int mode, ContextAddress range_start, ContextAddress range_end) {
- switch (mode) {
- case RM_RESUME:
- return context_continue(ctx);
- case RM_STEP_INTO:
- return context_single_step(ctx);
- case RM_TERMINATE:
- return context_terminate(ctx);
- }
- errno = ERR_UNSUPPORTED;
- return -1;
-}
-
-int context_can_resume(Context * ctx, int mode) {
- switch (mode) {
- case RM_RESUME:
- return 1;
- case RM_STEP_INTO:
- case RM_TERMINATE:
- return context_has_state(ctx);
- }
- return 0;
-}
-
-int context_read_mem(Context * ctx, ContextAddress address, void * buf, size_t size) {
- if (address < 0x100) {
- /* TODO: need proper handling of Access Violation exception in VxWorks version of context_read_mem() */
- errno = ERR_INV_ADDRESS;
- return -1;
- }
-#ifdef _WRS_PERSISTENT_SW_BP
- vxdbgMemRead((void *)address, buf, size);
-#else
- bcopy((void *)address, buf, size);
-#endif
- if (check_breakpoints_on_memory_read(ctx, address, buf, size) < 0) return -1;
- return 0;
-}
-
-int context_write_mem(Context * ctx, ContextAddress address, void * buf, size_t size) {
- if (address < 0x100) {
- errno = ERR_INV_ADDRESS;
- return -1;
- }
- if (check_breakpoints_on_memory_write(ctx, address, buf, size) < 0) return -1;
-#ifdef _WRS_PERSISTENT_SW_BP
- vxdbgMemWrite((void *)address, buf, size);
-#else
- bcopy(buf, (void *)address, size);
-#endif
- return 0;
-}
-
-#if ENABLE_ExtendedMemoryErrorReports
-int context_get_mem_error_info(MemoryErrorInfo * info) {
- if (mem_err_info.error == 0) {
- set_errno(ERR_OTHER, "Extended memory error info not available");
- return -1;
- }
- *info = mem_err_info;
- return 0;
-}
-#endif
-
-int context_write_reg(Context * ctx, RegisterDefinition * def, unsigned offs, unsigned size, void * buf) {
- ContextExtensionVxWorks * ext = EXT(ctx);
-
- assert(is_dispatch_thread());
- assert(context_has_state(ctx));
- assert(ctx->stopped);
- assert(!ctx->exited);
- assert(offs + size <= def->size);
-
- if (ext->regs_error) {
- set_error_report_errno(ext->regs_error);
- return -1;
- }
- memcpy((uint8_t *)ext->regs + def->offset + offs, buf, size);
- ext->regs_dirty = 1;
- return 0;
-}
-
-int context_read_reg(Context * ctx, RegisterDefinition * def, unsigned offs, unsigned size, void * buf) {
- ContextExtensionVxWorks * ext = EXT(ctx);
-
- assert(is_dispatch_thread());
- assert(context_has_state(ctx));
- assert(ctx->stopped);
- assert(!ctx->exited);
- assert(offs + size <= def->size);
-
- if (ext->regs_error) {
- set_error_report_errno(ext->regs_error);
- return -1;
- }
- memcpy(buf, (uint8_t *)ext->regs + def->offset + offs, size);
- return 0;
-}
-
-int context_get_canonical_addr(Context * ctx, ContextAddress addr,
- Context ** canonical_ctx, ContextAddress * canonical_addr,
- ContextAddress * block_addr, ContextAddress * block_size) {
- /* Direct mapping, page size is irrelevant */
- ContextAddress page_size = 0x100000;
- assert(is_dispatch_thread());
- *canonical_ctx = parent_ctx;
- if (canonical_addr != NULL) *canonical_addr = addr;
- if (block_addr != NULL) *block_addr = addr & ~(page_size - 1);
- if (block_size != NULL) *block_size = page_size;
- return 0;
-}
-
-Context * context_get_group(Context * ctx, int group) {
- switch (group) {
- case CONTEXT_GROUP_INTERCEPT:
- return ctx;
- }
- return parent_ctx;
-}
-
-int context_get_supported_bp_access_types(Context * ctx) {
- return 0;
-}
-
-int context_plant_breakpoint(ContextBreakpoint * bp) {
- VXDBG_CTX vxdbg_ctx;
- VXDBG_BP_ID bp_id = 0;
- if (bp->access_types != CTX_BP_ACCESS_INSTRUCTION) {
- errno = ERR_INV_FORMAT;
- return -1;
- }
- if (bp->length != 1) {
- errno = ERR_INV_FORMAT;
- return -1;
- }
- memset(&vxdbg_ctx, 0, sizeof(vxdbg_ctx));
- vxdbg_ctx.ctxType = VXDBG_CTX_TASK;
- if (vxdbgBpAdd(vxdbg_clnt_id,
- &vxdbg_ctx, 0, BP_ACTION_STOP | BP_ACTION_NOTIFY,
- 0, 0, (INSTR *)bp->address, 0, 0, &bp_id) != OK) return -1;
- bp->id = bp_id;
- return 0;
-}
-
-int context_unplant_breakpoint(ContextBreakpoint * bp) {
- VXDBG_BP_DEL_INFO info;
- memset(&info, 0, sizeof(info));
- info.pClnt = vxdbg_clnt_id;
- info.type = BP_BY_ID_DELETE;
- info.info.id.bpId = bp->id;
- if (vxdbgBpDelete(info) != OK) return -1;
- return 0;
-}
-
-static void add_map_region(MemoryMap * map, void * addr, int size, unsigned flags, char * file, char * sect) {
- MemoryRegion * r = NULL;
- if (map->region_cnt >= map->region_max) {
- map->region_max += 8;
- map->regions = (MemoryRegion *)loc_realloc(map->regions, sizeof(MemoryRegion) * map->region_max);
- }
- r = map->regions + map->region_cnt++;
- memset(r, 0, sizeof(MemoryRegion));
- r->addr = (ContextAddress)addr;
- r->size = (ContextAddress)size;
- r->flags = flags;
- if (file != NULL) r->file_name = loc_strdup(file);
- if (sect != NULL) r->sect_name = loc_strdup(sect);
-}
-
-static int module_list_proc(MODULE_ID id, int args) {
- MODULE_INFO info;
- MemoryMap * map = (MemoryMap *)args;
-
- memset(&info, 0, sizeof(info));
- if (moduleInfoGet(id, &info) == OK) {
- char * file = id->nameWithPath;
- if (info.segInfo.textAddr != NULL && info.segInfo.textSize > 0) {
- add_map_region(map, info.segInfo.textAddr, info.segInfo.textSize, MM_FLAG_R | MM_FLAG_X, file, ".text");
- }
- if (info.segInfo.dataAddr != NULL && info.segInfo.dataSize > 0) {
- add_map_region(map, info.segInfo.dataAddr, info.segInfo.dataSize, MM_FLAG_R | MM_FLAG_W, file, ".data");
- }
- if (info.segInfo.bssAddr != NULL && info.segInfo.bssSize > 0) {
- add_map_region(map, info.segInfo.bssAddr, info.segInfo.bssSize, MM_FLAG_R | MM_FLAG_W, file, ".bss");
- }
- }
- return 0;
-}
-
-static void module_create_event(void * args) {
- memory_map_event_module_loaded(parent_ctx);
-}
-
-static int module_create_func(MODULE_ID id) {
- post_event(module_create_event, NULL);
- return 0;
-}
-
-int context_get_memory_map(Context * ctx, MemoryMap * map) {
- static int hooks_done = 0;
- if (!hooks_done) {
- hooks_done = 1;
- moduleCreateHookAdd(module_create_func);
- }
- moduleEach(module_list_proc, (int)map);
- return 0;
-}
-
-unsigned context_word_size(Context * ctx) {
- return sizeof(void *);
-}
-
-int get_context_task_id(Context * ctx) {
- return EXT(ctx)->pid;
-}
-
-static void event_handler(void * arg) {
- struct event_info * info = (struct event_info *)arg;
- Context * current_ctx = context_find_from_pid(info->current_ctx.ctxId, 1);
- Context * stopped_ctx = context_find_from_pid(info->stopped_ctx.ctxId, 1);
-
- switch (info->event) {
- case EVENT_HOOK_BREAKPOINT:
- if (stopped_ctx == NULL) break;
- assert(!stopped_ctx->stopped);
- assert(!EXT(stopped_ctx)->regs_dirty);
- if (EXT(stopped_ctx)->regs_error) {
- release_error_report(EXT(stopped_ctx)->regs_error);
- EXT(stopped_ctx)->regs_error = NULL;
- }
- memcpy(EXT(stopped_ctx)->regs, &info->regs, sizeof(REG_SET));
- EXT(stopped_ctx)->event = 0;
- stopped_ctx->signal = SIGTRAP;
- stopped_ctx->stopped = 1;
- stopped_ctx->stopped_by_bp = info->bp_info_ok;
- stopped_ctx->stopped_by_exception = 0;
- assert(get_regs_PC(stopped_ctx) == info->addr);
- if (stopped_ctx->stopped_by_bp && !is_breakpoint_address(stopped_ctx, info->addr)) {
- /* Break instruction that is not planted by us */
- stopped_ctx->stopped_by_bp = 0;
- stopped_ctx->pending_intercept = 1;
- }
- EXT(stopped_ctx)->bp_info = info->bp_info;
- if (current_ctx != NULL) EXT(stopped_ctx)->bp_pid = EXT(current_ctx)->pid;
- assert(taskIsStopped(EXT(stopped_ctx)->pid));
- trace(LOG_CONTEXT, "context: stopped by breakpoint: ctx %#lx, id %#x",
- stopped_ctx, EXT(stopped_ctx)->pid);
- send_context_stopped_event(stopped_ctx);
- break;
- case EVENT_HOOK_STEP_DONE:
- if (current_ctx == NULL) break;
- assert(!current_ctx->stopped);
- assert(!EXT(current_ctx)->regs_dirty);
- if (EXT(current_ctx)->regs_error) {
- release_error_report(EXT(current_ctx)->regs_error);
- EXT(current_ctx)->regs_error = NULL;
- }
- memcpy(EXT(current_ctx)->regs, &info->regs, sizeof(REG_SET));
- EXT(current_ctx)->event = TRACE_EVENT_STEP;
- current_ctx->signal = SIGTRAP;
- current_ctx->stopped = 1;
- current_ctx->stopped_by_bp = 0;
- current_ctx->stopped_by_exception = 0;
- assert(taskIsStopped(EXT(current_ctx)->pid));
- trace(LOG_CONTEXT, "context: stopped by end of step: ctx %#lx, id %#x",
- current_ctx, EXT(current_ctx)->pid);
- send_context_stopped_event(current_ctx);
- break;
- case EVENT_HOOK_STOP:
- if (stopped_ctx == NULL) break;
- assert(!stopped_ctx->exited);
- if (stopped_ctx->stopped) break;
- if (EXT(stopped_ctx)->regs_error) {
- release_error_report(EXT(stopped_ctx)->regs_error);
- EXT(stopped_ctx)->regs_error = NULL;
- }
- if (taskRegsGet(EXT(stopped_ctx)->pid, EXT(stopped_ctx)->regs) != OK) {
- EXT(stopped_ctx)->regs_error = get_error_report(errno);
- assert(EXT(stopped_ctx)->regs_error != NULL);
- }
- EXT(stopped_ctx)->event = 0;
- stopped_ctx->signal = SIGSTOP;
- stopped_ctx->stopped = 1;
- stopped_ctx->stopped_by_bp = 0;
- stopped_ctx->stopped_by_exception = 0;
- assert(taskIsStopped(EXT(stopped_ctx)->pid));
- trace(LOG_CONTEXT, "context: stopped by sofware request: ctx %#lx, id %#x",
- stopped_ctx, EXT(stopped_ctx)->pid);
- send_context_stopped_event(stopped_ctx);
- break;
- case EVENT_HOOK_TASK_ADD:
- if (current_ctx == NULL) break;
- assert(stopped_ctx == NULL);
- stopped_ctx = create_context(pid2id((pid_t)info->stopped_ctx.ctxId, EXT(current_ctx->parent)->pid));
- EXT(stopped_ctx)->pid = (pid_t)info->stopped_ctx.ctxId;
- EXT(stopped_ctx)->regs = (REG_SET *)loc_alloc(sizeof(REG_SET));
- stopped_ctx->mem = current_ctx->mem;
- stopped_ctx->big_endian = current_ctx->mem->big_endian;
- (stopped_ctx->creator = current_ctx)->ref_count++;
- (stopped_ctx->parent = current_ctx->parent)->ref_count++;
- assert(stopped_ctx->mem == stopped_ctx->parent->mem);
- list_add_last(&stopped_ctx->cldl, &stopped_ctx->parent->children);
- link_context(stopped_ctx);
- trace(LOG_CONTEXT, "context: created: ctx %#lx, id %#x",
- stopped_ctx, EXT(stopped_ctx)->pid);
- send_context_created_event(stopped_ctx);
- break;
- default:
- assert(0);
- break;
- }
- loc_free(info);
- SPIN_LOCK_ISR_TAKE(&events_lock);
- events_cnt--;
- SPIN_LOCK_ISR_GIVE(&events_lock);
-}
-
-static void event_error(void * arg) {
- trace(LOG_ALWAYS, "Fatal error: VXDBG events buffer overflow");
- exit(1);
-}
-
-static void * event_thread_func(void * arg) {
- taskPrioritySet(0, VX_TASK_PRIORITY_MIN);
- for (;;) {
- struct event_info * info = loc_alloc(sizeof(struct event_info));
- semTake(events_signal, WAIT_FOREVER);
-
- SPIN_LOCK_ISR_TAKE(&events_lock);
- if (events_buf_overflow && events_inp == events_out) {
- SPIN_LOCK_ISR_GIVE(&events_lock);
- loc_free(info);
- break;
- }
- assert(events_inp != events_out);
- *info = events[events_out];
- events_out = (events_out + 1) % MAX_EVENTS;
- SPIN_LOCK_ISR_GIVE(&events_lock);
-
- post_event(event_handler, info);
- }
- post_event(event_error, NULL);
- return NULL;
-}
-
-static void vxdbg_event_hook(
- VXDBG_CTX * current_ctx, /* context that hit breakpoint */
- VXDBG_CTX * stopped_ctx, /* context stopped by the breakpoint */
- REG_SET * regs, /* task registers before exception */
- UINT32 addr, /* breakpoint addr */
- VXDBG_BP_INFO * bp_info) { /* breakpoint information */
-
- struct event_info * info = event_info_alloc(EVENT_HOOK_BREAKPOINT);
- if (info != NULL) {
- if (stopped_ctx == NULL) info->event = EVENT_HOOK_STEP_DONE;
- if (current_ctx != NULL) info->current_ctx = *current_ctx;
- if (stopped_ctx != NULL) info->stopped_ctx = *stopped_ctx;
- if (regs != NULL) info->regs = *regs;
- info->addr = addr;
- if (bp_info != NULL) {
- info->bp_info_ok = 1;
- info->bp_info = *bp_info;
- }
- event_info_post(info);
- }
-}
-
-static void task_create_hook(WIND_TCB * tcb) {
- struct event_info * info = event_info_alloc(EVENT_HOOK_TASK_ADD);
- if (info != NULL) {
- info->current_ctx.ctxId = taskIdSelf();
- info->stopped_ctx.ctxId = (UINT32)tcb;
- event_info_post(info);
- }
-}
-
-static void waitpid_listener(int pid, int exited, int exit_code, int signal, int event_code, int syscall, void * args) {
- if (exited) {
- Context * stopped_ctx = context_find_from_pid(pid, 1);
- if (stopped_ctx != NULL) {
- /* TODO: need call back for vxdbgCont()
- * assert(!stopped_ctx->stopped) can fail if a task is resumed outside TCF agent.
- */
- assert(!stopped_ctx->stopped);
- assert(!stopped_ctx->exited);
- trace(LOG_CONTEXT, "context: exited ctx %#lx, id %#x", stopped_ctx, EXT(stopped_ctx)->pid);
- release_error_report(EXT(stopped_ctx)->regs_error);
- loc_free(EXT(stopped_ctx)->regs);
- EXT(stopped_ctx)->regs_error = NULL;
- EXT(stopped_ctx)->regs = NULL;
- send_context_exited_event(stopped_ctx);
- }
- }
-}
-
-void init_contexts_sys_dep(void) {
- SPIN_LOCK_ISR_INIT(&events_lock, 0);
- if ((events_signal = semCInitialize(events_signal_mem, SEM_Q_FIFO, 0)) == NULL) {
- check_error(errno);
- }
- vxdbg_clnt_id = vxdbgClntRegister(EVT_BP);
- if (vxdbg_clnt_id == NULL) {
- check_error(errno);
- }
- context_extension_offset = context_extension(sizeof(ContextExtensionVxWorks));
- taskCreateHookAdd((FUNCPTR)task_create_hook);
- vxdbgHookAdd(vxdbg_clnt_id, EVT_BP, vxdbg_event_hook);
- vxdbgHookAdd(vxdbg_clnt_id, EVT_TRACE, vxdbg_event_hook);
- check_error(pthread_create(&events_thread, &pthread_create_attr, event_thread_func, NULL));
- add_waitpid_listener(waitpid_listener, NULL);
- ini_context_pid_hash();
-}
-
-#endif /* if ENABLE_DebugContext */
-#endif /* _WRS_KERNEL */
diff --git a/agent/tcf/system/VxWorks/context-vxworks.h b/agent/tcf/system/VxWorks/context-vxworks.h
deleted file mode 100644
index 0fd81105..00000000
--- a/agent/tcf/system/VxWorks/context-vxworks.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-/*
- * This module handles process/thread OS contexts and their state machine.
- */
-
-#ifndef D_context_vxworks
-#define D_context_vxworks
-
-#include <tcf/config.h>
-#include <tcf/framework/context.h>
-
-extern int get_context_task_id(Context * ctx);
-
-#endif /* D_context_vxworks */
diff --git a/agent/tcf/system/VxWorks/regset.h b/agent/tcf/system/VxWorks/regset.h
deleted file mode 100644
index 0a12cb92..00000000
--- a/agent/tcf/system/VxWorks/regset.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-/*
- * This header file provides definition of REG_SET - a structure that can
- * hold values of target CPU registers.
- */
-
-#if defined(_WRS_KERNEL)
-# include <regs.h>
-#endif
diff --git a/agent/tcf/system/Windows/context-win32.c b/agent/tcf/system/Windows/context-win32.c
deleted file mode 100644
index e85cbb11..00000000
--- a/agent/tcf/system/Windows/context-win32.c
+++ /dev/null
@@ -1,1434 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-/*
- * This module handles process/thread OS contexts and their state machine.
- */
-
-#include <tcf/config.h>
-
-#if defined(WIN32)
-
-#if ENABLE_DebugContext && !ENABLE_ContextProxy
-
-#include <stdlib.h>
-#include <assert.h>
-#include <errno.h>
-#include <signal.h>
-#include <tcf/framework/context.h>
-#include <tcf/framework/events.h>
-#include <tcf/framework/errors.h>
-#include <tcf/framework/trace.h>
-#include <tcf/framework/myalloc.h>
-#include <tcf/framework/waitpid.h>
-#include <tcf/framework/signames.h>
-#include <tcf/services/breakpoints.h>
-#include <tcf/services/memorymap.h>
-#include <tcf/services/runctrl.h>
-#include <tcf/system/Windows/context-win32.h>
-#include <tcf/system/Windows/regset.h>
-#include <tcf/system/Windows/windbgcache.h>
-
-#if !defined(USE_HW_BPS)
-# define USE_HW_BPS 1
-#endif
-#if USE_HW_BPS
-# define MAX_HW_BPS 4
-#endif
-
-typedef struct ContextExtensionWin32 {
- pid_t pid;
- HANDLE handle;
- DEBUG_EVENT debug_event;
- EXCEPTION_DEBUG_INFO suspend_reason;
- int stop_pending;
- int start_pending;
- REG_SET * regs; /* copy of context registers, updated when context stops */
- ErrorReport * regs_error; /* if not NULL, 'regs' is invalid */
- int regs_dirty; /* if not 0, 'regs' is modified and needs to be saved before context is continued */
- int trace_flag;
- uint8_t step_opcodes[4];
- SIZE_T step_opcodes_len;
- ContextAddress step_opcodes_addr;
- struct DebugState * debug_state;
-#if USE_HW_BPS
- ContextBreakpoint * triggered_hw_bps[MAX_HW_BPS + 1];
- unsigned hw_bps_regs_generation;
- DWORD skip_hw_bp_addr;
-#endif
-} ContextExtensionWin32;
-
-static size_t context_extension_offset = 0;
-
-#define EXT(ctx) ((ContextExtensionWin32 *)((char *)(ctx) + context_extension_offset))
-
-typedef struct DebugState {
- int error;
- int state;
- DWORD process_id;
- DWORD debug_thread_id;
- HANDLE debug_thread;
- HANDLE debug_thread_semaphore;
- HANDLE debug_event_inp;
- HANDLE debug_event_out;
- DWORD ini_thread_id;
- HANDLE ini_thread_handle;
- DWORD main_thread_id;
- HANDLE main_thread_handle;
- int reporting_debug_event;
- int break_posted;
- HANDLE break_thread;
- LPVOID break_thread_code;
- DWORD break_thread_id;
- HANDLE file_handle;
- DWORD64 base_address;
- HANDLE module_handle;
- DWORD64 module_address;
- ContextAttachCallBack * attach_callback;
- void * attach_data;
-#if USE_HW_BPS
- int ok_to_use_hw_bp; /* NtContinue() changes Dr6 and Dr7, so HW breakpoints should be disabled until NtContinue() is done */
- ContextBreakpoint * hw_bps[MAX_HW_BPS];
- unsigned hw_bps_generation;
-#endif
-} DebugState;
-
-#define DEBUG_STATE_INIT 0
-#define DEBUG_STATE_PRS_CREATED 1
-#define DEBUG_STATE_PRS_ATTACHED 2
-
-typedef struct DebugEvent {
- DebugState * debug_state;
- DEBUG_EVENT win32_event;
- DWORD continue_status;
-} DebugEvent;
-
-static OSVERSIONINFOEX os_version;
-
-#define MAX_EXCEPTION_HANDLERS 8
-static ContextExceptionHandler * exception_handlers[MAX_EXCEPTION_HANDLERS];
-static unsigned exception_handler_cnt = 0;
-
-static MemoryErrorInfo mem_err_info;
-
-#include <tcf/system/pid-hash.h>
-
-#define EXCEPTION_DEBUGGER_IO 0x406D1388
-
-const char * context_suspend_reason(Context * ctx) {
- ContextExtensionWin32 * ext = EXT(ctx);
- DWORD exception_code = ext->suspend_reason.ExceptionRecord.ExceptionCode;
- static char buf[64];
-
- if (exception_code == 0) return REASON_USER_REQUEST;
- if (ext->suspend_reason.dwFirstChance) {
- if (exception_code == EXCEPTION_SINGLE_STEP) return REASON_STEP;
- if (exception_code == EXCEPTION_BREAKPOINT) return "Break Instruction";
- snprintf(buf, sizeof(buf), "Exception %#lx", exception_code);
- }
- else {
- snprintf(buf, sizeof(buf), "Unhandled exception %#lx", exception_code);
- }
- return buf;
-}
-
-static int get_signal_index(Context * ctx) {
- ContextExtensionWin32 * ext = EXT(ctx);
- DWORD exception_code = ext->suspend_reason.ExceptionRecord.ExceptionCode;
-
- if (exception_code == 0) return 0;
- return get_signal_from_code(exception_code);
-}
-
-static const char * win32_debug_event_name(int event) {
- switch (event) {
- case CREATE_PROCESS_DEBUG_EVENT:
- return "CREATE_PROCESS_DEBUG_EVENT";
- case CREATE_THREAD_DEBUG_EVENT:
- return "CREATE_THREAD_DEBUG_EVENT";
- case EXCEPTION_DEBUG_EVENT:
- return "EXCEPTION_DEBUG_EVENT";
- case EXIT_PROCESS_DEBUG_EVENT:
- return "EXIT_PROCESS_DEBUG_EVENT";
- case EXIT_THREAD_DEBUG_EVENT:
- return "EXIT_THREAD_DEBUG_EVENT";
- case LOAD_DLL_DEBUG_EVENT:
- return "LOAD_DLL_DEBUG_EVENT";
- case OUTPUT_DEBUG_STRING_EVENT:
- return "OUTPUT_DEBUG_STRING_EVENT";
- case UNLOAD_DLL_DEBUG_EVENT:
- return "UNLOAD_DLL_DEBUG_EVENT";
- }
- return "Unknown";
-}
-
-static int log_error(const char * fn, int ok) {
- int err;
- if (ok) return 0;
- assert(is_dispatch_thread());
- err = set_win32_errno(GetLastError());
- trace(LOG_ALWAYS, "context: %s: %s", fn, errno_to_str(errno));
- return err;
-}
-
-static void event_win32_context_exited(Context * ctx);
-
-static void get_registers(Context * ctx) {
- ContextExtensionWin32 * ext = EXT(ctx);
-
- if (ext->regs->ContextFlags) return;
-
- assert(!ctx->exited);
- assert(context_has_state(ctx));
- assert(ctx->stopped);
-
- ext->regs->ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT;
-#if USE_HW_BPS
- ext->regs->ContextFlags |= CONTEXT_DEBUG_REGISTERS;
-#endif
- if (GetThreadContext(ext->handle, ext->regs) == 0) {
- ext->regs_error = get_error_report(log_error("GetThreadContext", 0));
- }
- else {
- ext->trace_flag = (ext->regs->EFlags & 0x100) != 0;
- trace(LOG_CONTEXT, "context: get regs OK: ctx %#lx, id %s, PC %#lx",
- ctx, ctx->id, ext->regs->Eip);
- }
-}
-
-static DWORD event_win32_context_stopped(Context * ctx) {
- ContextExtensionWin32 * ext = EXT(ctx);
- DebugState * debug_state = EXT(ctx->mem)->debug_state;
- ContextAddress exception_addr = (ContextAddress)ext->suspend_reason.ExceptionRecord.ExceptionAddress;
- DWORD exception_code = ext->suspend_reason.ExceptionRecord.ExceptionCode;
- DWORD continue_status = DBG_CONTINUE;
-
- assert(is_dispatch_thread());
- assert(!ctx->exited);
- assert(!ctx->stopped);
- assert(ext->handle != NULL);
- assert(ctx->parent != NULL);
-
- ext->stop_pending = 0;
- ext->start_pending = 0;
-
- trace(LOG_CONTEXT, "context: stopped: ctx %#lx, id %s, exception %#lx",
- ctx, ctx->id, exception_code);
-
- if (SuspendThread(ext->handle) == (DWORD)-1) {
- DWORD err = GetLastError();
- ctx->exiting = 1;
- if (err == ERROR_ACCESS_DENIED) {
- /* Already exited */
- return DBG_CONTINUE;
- }
- log_error("SuspendThread", 0);
- return DBG_EXCEPTION_NOT_HANDLED;
- }
-
- if (ext->regs_error) {
- release_error_report(ext->regs_error);
- ext->regs_error = NULL;
- }
- memset(ext->regs, 0, sizeof(REG_SET));
-
- ctx->signal = get_signal_index(ctx);
- ctx->pending_signals = 0;
- ctx->stopped = 1;
- ctx->stopped_by_bp = 0;
- ctx->stopped_by_cb = NULL;
- if (exception_code == 0) {
- ctx->stopped_by_exception = 0;
- }
- else if (ext->suspend_reason.dwFirstChance) {
- ctx->stopped_by_exception = 0;
- switch (exception_code) {
- case EXCEPTION_SINGLE_STEP:
- get_registers(ctx);
- if (!ext->regs_error) {
-#if USE_HW_BPS
- if (ext->regs->Eip != ext->skip_hw_bp_addr) ext->skip_hw_bp_addr = 0;
- if (ext->regs->Dr6 & 0xfu) {
- int i, j = 0;
- for (i = 0; i < MAX_HW_BPS; i++) {
- if (ext->regs->Dr6 & (1u << i)) {
- ContextBreakpoint * bp = debug_state->hw_bps[i];
- if (bp == NULL) continue;
- if (bp->address == ext->regs->Eip && (bp->access_types & CTX_BP_ACCESS_INSTRUCTION)) {
- ext->skip_hw_bp_addr = ext->regs->Eip;
- }
- ctx->stopped_by_cb = ext->triggered_hw_bps;
- ctx->stopped_by_cb[j++] = bp;
- ctx->stopped_by_cb[j] = NULL;
- }
- }
- }
-#endif
- if (ext->step_opcodes_len > 0 && ext->step_opcodes[0] == 0x9c && ext->step_opcodes_addr != ext->regs->Eip) {
- /* PUSHF instruction: need to clear trace flag from top of the stack */
- SIZE_T bcnt = 0;
- ContextAddress buf = 0;
- assert(ext->regs->EFlags & 0x100);
- assert(ext->step_opcodes_addr == ext->regs->Eip - 1);
- if (!ReadProcessMemory(EXT(ctx->mem)->handle, (LPCVOID)ext->regs->Esp, &buf, sizeof(ContextAddress), &bcnt) || bcnt != sizeof(ContextAddress)) {
- log_error("ReadProcessMemory", 0);
- }
- else {
- assert(buf & 0x100);
- buf &= ~0x100;
- if (!WriteProcessMemory(EXT(ctx->mem)->handle, (LPVOID)ext->regs->Esp, &buf, sizeof(ContextAddress), &bcnt) || bcnt != sizeof(ContextAddress)) {
- log_error("WriteProcessMemory", 0);
- }
- }
- }
- }
- if ((!ctx->stopped_by_cb && ext->step_opcodes_len == 0) || ext->regs_error) {
- continue_status = DBG_EXCEPTION_NOT_HANDLED;
- }
- ext->step_opcodes_len = 0;
- ext->step_opcodes_addr = 0;
- break;
- case EXCEPTION_BREAKPOINT:
- get_registers(ctx);
- if (!ext->regs_error) {
- if (is_breakpoint_address(ctx, exception_addr)) {
- ext->regs->Eip = exception_addr;
- ext->regs_dirty = 1;
- ctx->stopped_by_bp = 1;
-#if USE_HW_BPS
- if (!debug_state->ok_to_use_hw_bp) {
- debug_state->ok_to_use_hw_bp = 1;
- send_context_changed_event(ctx->mem);
- memory_map_event_mapping_changed(ctx->mem);
- }
-#endif
- }
- else {
- ext->regs->Eip = exception_addr;
- ext->regs_dirty = 1;
- }
- }
- else {
- continue_status = DBG_EXCEPTION_NOT_HANDLED;
- }
- break;
- case EXCEPTION_DEBUGGER_IO:
- trace(LOG_ALWAYS, "Debugger IO request %#lx",
- ext->suspend_reason.ExceptionRecord.ExceptionInformation[0]);
- break;
- default:
- continue_status = DBG_EXCEPTION_NOT_HANDLED;
- break;
- }
- if (continue_status == DBG_EXCEPTION_NOT_HANDLED) {
- unsigned i;
- for (i = 0; i < exception_handler_cnt; i++) {
- if (exception_handlers[i](ctx, &ext->suspend_reason)) {
- continue_status = DBG_CONTINUE;
- }
- }
- }
- if (continue_status == DBG_EXCEPTION_NOT_HANDLED) {
- int intercept = 1;
- ctx->stopped_by_exception = 1;
- if (ctx->signal) {
- ctx->pending_signals |= 1 << ctx->signal;
- if (ctx->sig_dont_pass & (1 << ctx->signal)) {
- continue_status = DBG_CONTINUE;
- }
- if (ctx->sig_dont_stop & (1 << ctx->signal)) {
- intercept = 0;
- }
- }
- if (intercept) ctx->pending_intercept = 1;
- }
- }
- else {
- ctx->stopped_by_exception = 1;
- if (!ctx->mem->exiting) ctx->pending_intercept = 1;
- continue_status = DBG_EXCEPTION_NOT_HANDLED;
- }
- send_context_stopped_event(ctx);
- return continue_status;
-}
-
-static void event_win32_context_started(Context * ctx) {
- ContextExtensionWin32 * ext = EXT(ctx);
- trace(LOG_CONTEXT, "context: started: ctx %#lx, id %s", ctx, ctx->id);
- assert(ctx->stopped);
- ext->stop_pending = 0;
- send_context_started_event(ctx);
-}
-
-static void event_win32_context_exited(Context * ctx) {
- ContextExtensionWin32 * ext = EXT(ctx);
- LINK * l = NULL;
- trace(LOG_CONTEXT, "context: exited: ctx %#lx, id %s", ctx, ctx->id);
- assert(!ctx->exited);
- context_lock(ctx);
- ctx->exiting = 1;
- ext->stop_pending = 0;
- if (ctx->stopped) send_context_started_event(ctx);
- l = ctx->children.next;
- while (l != &ctx->children) {
- Context * c = cldl2ctxp(l);
- l = l->next;
- assert(c->parent == ctx);
- if (!c->exited) event_win32_context_exited(c);
- }
- release_error_report(ext->regs_error);
- loc_free(ext->regs);
- ext->regs_error = NULL;
- ext->regs = NULL;
- send_context_exited_event(ctx);
- if (ext->handle != NULL) {
- if (ctx->mem != ctx) {
- log_error("CloseHandle", CloseHandle(ext->handle));
- }
- else if (os_version.dwMajorVersion <= 5) {
- /* Bug in Windows XP: ContinueDebugEvent() does not close exited process handle */
- log_error("CloseHandle", CloseHandle(ext->handle));
- }
- ext->handle = NULL;
- }
- if (ext->debug_state != NULL && ext->debug_state->file_handle != NULL) {
- log_error("CloseHandle", CloseHandle(ext->debug_state->file_handle));
- ext->debug_state->file_handle = NULL;
- }
- ext->debug_state = NULL;
- context_unlock(ctx);
-}
-
-static DWORD WINAPI remote_thread_func(LPVOID args) {
- return 0;
-}
-
-static void break_process_event(void * args) {
- Context * ctx = (Context *)args;
- ContextExtensionWin32 * ext = EXT(ctx);
-
- if (ext->debug_state != NULL) {
- LINK * l;
- int cnt = 0;
- DebugState * debug_state = ext->debug_state;
-
- if (!ctx->exited && debug_state->break_thread == NULL) {
- for (l = ctx->children.next; l != &ctx->children; l = l->next) {
- ContextExtensionWin32 * x = EXT(cldl2ctxp(l));
- if (x->stop_pending && SuspendThread(x->handle) != (DWORD)-1) cnt++;
- }
- if (cnt > 0) {
- const SIZE_T buf_size = 0x100;
- DWORD size = 0;
- int error = 0;
-
- trace(LOG_CONTEXT, "context: creating remote thread in process %#lx, id %s", ctx, ctx->id);
- if (debug_state->break_thread_code == NULL) {
- debug_state->break_thread_code = VirtualAllocEx(ext->handle,
- NULL, buf_size, MEM_COMMIT, PAGE_EXECUTE);
- error = log_error("VirtualAllocEx", debug_state->break_thread_code != NULL);
- }
-
- if (!error) error = log_error("WriteProcessMemory", WriteProcessMemory(ext->handle,
- debug_state->break_thread_code, (LPCVOID)remote_thread_func, buf_size, &size) && size == buf_size);
-
- if (!error) error = log_error("CreateRemoteThread", (debug_state->break_thread = CreateRemoteThread(ext->handle,
- 0, 0, (DWORD (WINAPI*)(LPVOID))debug_state->break_thread_code, NULL, 0, &debug_state->break_thread_id)) != NULL);
-
- if (error) {
- debug_state->break_thread = NULL;
- debug_state->break_thread_id = 0;
- }
- }
- }
- debug_state->break_posted = 0;
- }
- context_unlock(ctx);
-}
-
-static int win32_resume(Context * ctx, int step) {
- Context * prs = ctx->parent;
- ContextExtensionWin32 * ext = EXT(ctx);
- ContextExtensionWin32 * prs_ext = EXT(prs);
- DebugState * debug_state = prs_ext->debug_state;
-
- assert(ctx->stopped);
- assert(!ctx->exited);
-
- if (debug_state->reporting_debug_event) {
- debug_state->reporting_debug_event++;
- }
-
-#if USE_HW_BPS
-
- if (ext->skip_hw_bp_addr == 0 && skip_breakpoint(ctx, step)) return 0;
-
- /* Update debug registers */
- if (ext->skip_hw_bp_addr != 0 || ext->hw_bps_regs_generation != debug_state->hw_bps_generation) {
- int i;
- DWORD Dr7 = 0;
- int step_over_hw_bp = 0;
-
- get_registers(ctx);
- if (ext->regs_error) {
- errno = set_error_report_errno(ext->regs_error);
- return -1;
- }
- Dr7 = ext->regs->Dr7;
- for (i = 0; i < MAX_HW_BPS; i++) {
- ContextBreakpoint * bp = debug_state->hw_bps[i];
- if (bp != NULL &&
- ext->skip_hw_bp_addr == bp->address &&
- (bp->access_types & CTX_BP_ACCESS_INSTRUCTION)) {
- /* Skipping the breakpoint */
- step_over_hw_bp = 1;
- bp = NULL;
- }
- Dr7 &= ~(3u << (i * 2));
- if (bp != NULL) {
- switch (i) {
- case 0:
- if (ext->regs->Dr0 != bp->address) {
- ext->regs->Dr0 = bp->address;
- ext->regs_dirty = 1;
- }
- break;
- case 1:
- if (ext->regs->Dr1 != bp->address) {
- ext->regs->Dr1 = bp->address;
- ext->regs_dirty = 1;
- }
- break;
- case 2:
- if (ext->regs->Dr2 != bp->address) {
- ext->regs->Dr2 = bp->address;
- ext->regs_dirty = 1;
- }
- break;
- case 3:
- if (ext->regs->Dr3 != bp->address) {
- ext->regs->Dr3 = bp->address;
- ext->regs_dirty = 1;
- }
- break;
- }
- Dr7 |= 1u << (i * 2);
- if (bp->access_types == (CTX_BP_ACCESS_INSTRUCTION | CTX_BP_ACCESS_VIRTUAL)) {
- Dr7 &= ~(3u << (i * 4 + 16));
- }
- else if (bp->access_types == (CTX_BP_ACCESS_DATA_WRITE | CTX_BP_ACCESS_VIRTUAL)) {
- Dr7 &= ~(3u << (i * 4 + 16));
- Dr7 |= 1u << (i * 4 + 16);
- }
- else if (bp->access_types == (CTX_BP_ACCESS_DATA_READ | CTX_BP_ACCESS_DATA_WRITE | CTX_BP_ACCESS_VIRTUAL)) {
- Dr7 |= 3u << (i * 4 + 16);
- }
- else {
- errno = set_errno(ERR_UNSUPPORTED, "Invalid hardware breakpoint: unsupported access mode");
- return -1;
- }
- if (bp->length == 1) {
- Dr7 &= ~(3u << (i * 4 + 18));
- }
- else if (bp->length == 2) {
- Dr7 &= ~(3u << (i * 4 + 18));
- Dr7 |= 1u << (i * 4 + 18);
- }
- else if (bp->length == 4) {
- Dr7 |= 3u << (i * 4 + 18);
- }
- else if (bp->length == 8) {
- Dr7 &= ~(3u << (i * 4 + 18));
- Dr7 |= 2u << (i * 4 + 18);
- }
- else {
- errno = set_errno(ERR_UNSUPPORTED, "Invalid hardware breakpoint: unsupported length");
- return -1;
- }
- }
- }
- if (ext->regs->Dr7 != Dr7) {
- ext->regs->Dr7 = Dr7;
- ext->regs_dirty = 1;
- }
- ext->hw_bps_regs_generation = debug_state->hw_bps_generation;
- if (step_over_hw_bp) {
- step = 1;
- ext->hw_bps_regs_generation--;
- }
- else {
- ext->skip_hw_bp_addr = 0;
- }
- }
-
-#else
-
- if (skip_breakpoint(ctx, step)) return 0;
-
-#endif
-
- /* Update CPU trace flag */
- if (!step && ext->trace_flag) {
- get_registers(ctx);
- ext->regs->EFlags &= ~0x100;
- ext->regs_dirty = 1;
- }
- else if (step && !ext->trace_flag) {
- get_registers(ctx);
- ext->regs->EFlags |= 0x100;
- ext->regs_dirty = 1;
- }
-
- /* Flash registers if dirty */
- if (ext->regs_dirty) {
- assert(ext->regs->ContextFlags);
- if (ext->regs_error) {
- trace(LOG_ALWAYS, "Can't resume thread, registers copy is invalid: ctx %#lx, id %s", ctx, ctx->id);
- errno = set_error_report_errno(ext->regs_error);
- return -1;
- }
- if (SetThreadContext(ext->handle, ext->regs) == 0) {
- errno = log_error("SetThreadContext", 0);
- return -1;
- }
- ext->trace_flag = (ext->regs->EFlags & 0x100) != 0;
- ext->regs_dirty = 0;
- }
-
- if (ext->trace_flag) {
- get_registers(ctx);
- if (ext->regs_error) {
- set_error_report_errno(ext->regs_error);
- return -1;
- }
- ext->step_opcodes_addr = ext->regs->Eip;
- if (!ReadProcessMemory(prs_ext->handle, (LPCVOID)ext->regs->Eip, &ext->step_opcodes,
- sizeof(ext->step_opcodes), &ext->step_opcodes_len) || ext->step_opcodes_len == 0) {
- errno = log_error("ReadProcessMemory", 0);
- return -1;
- }
- }
- if (debug_state->reporting_debug_event) {
- ext->start_pending = 1;
- }
- else {
- for (;;) {
- DWORD cnt = ResumeThread(ext->handle);
- if (cnt == (DWORD)-1) {
- errno = log_error("ResumeThread", 0);
- return -1;
- }
- if (cnt <= 1) break;
- }
- }
-
- event_win32_context_started(ctx);
- return 0;
-}
-
-static int win32_terminate(Context * ctx) {
- LINK * l;
- ContextExtensionWin32 * ext = EXT(ctx);
- DebugState * debug_state = ext->debug_state;
-
- if (debug_state->reporting_debug_event) {
- debug_state->reporting_debug_event++;
- }
-
- trace(LOG_CONTEXT, "context: terminating process %#lx, id %s", ctx, ctx->id);
- if (!ctx->exiting) {
- if (!TerminateProcess(ext->handle, 1)) {
- errno = log_error("TerminateProcess", 0);
- return -1;
- }
- ctx->exiting = 1;
- for (l = ctx->children.next; l != &ctx->children; l = l->next) {
- Context * c = cldl2ctxp(l);
- if (!c->stopped) continue;
- event_win32_context_started(c);
- c->exiting = 1;
- }
- }
-
- return 0;
-}
-
-static void debug_event_handler(DebugEvent * debug_event) {
- DebugState * debug_state = debug_event->debug_state;
- DEBUG_EVENT * win32_event = &debug_event->win32_event;
- Context * prs = context_find_from_pid(win32_event->dwProcessId, 0);
- Context * ctx = context_find_from_pid(win32_event->dwThreadId, 1);
- ContextExtensionWin32 * ext = NULL;
-
- assert(ctx == NULL || ctx->parent == prs);
-
- switch (win32_event->dwDebugEventCode) {
- case CREATE_PROCESS_DEBUG_EVENT:
- if (debug_state->state == DEBUG_STATE_INIT) {
- debug_state->state = DEBUG_STATE_PRS_CREATED;
- debug_state->main_thread_id = win32_event->dwThreadId;
- debug_state->main_thread_handle = win32_event->u.CreateProcessInfo.hThread;
- debug_state->file_handle = win32_event->u.CreateProcessInfo.hFile;
- debug_state->base_address = (uintptr_t)win32_event->u.CreateProcessInfo.lpBaseOfImage;
- assert(prs == NULL);
- assert(ctx == NULL);
- ext = EXT(prs = create_context(pid2id(win32_event->dwProcessId, 0)));
- prs->mem = prs;
- prs->mem_access |= MEM_ACCESS_INSTRUCTION;
- prs->mem_access |= MEM_ACCESS_DATA;
- prs->mem_access |= MEM_ACCESS_USER;
- prs->big_endian = big_endian_host();
- ext->pid = win32_event->dwProcessId;
- ext->handle = win32_event->u.CreateProcessInfo.hProcess;
- ext->debug_state = debug_state;
- assert(ext->handle != NULL);
- link_context(prs);
- send_context_created_event(prs);
- }
- else {
- /* This looks like a bug in Windows XP: */
- /* 1. according to the documentation, we should get only one CREATE_PROCESS_DEBUG_EVENT. */
- /* 2. if we don't suspend second process, debugee crashes. */
- assert(debug_state->ini_thread_handle == NULL);
- debug_state->ini_thread_id = win32_event->dwThreadId;
- debug_state->ini_thread_handle = win32_event->u.CreateProcessInfo.hThread;
- SuspendThread(debug_state->ini_thread_handle);
- CloseHandle(win32_event->u.CreateProcessInfo.hFile);
- ResumeThread(debug_state->main_thread_handle);
- }
- break;
- case CREATE_THREAD_DEBUG_EVENT:
- assert(prs != NULL);
- assert(ctx == NULL);
- if (debug_state->state < DEBUG_STATE_PRS_ATTACHED) break;
- if (debug_state->break_thread_id == win32_event->dwThreadId) break;
- ext = EXT(ctx = create_context(pid2id(win32_event->dwThreadId, win32_event->dwProcessId)));
- ext->regs = (REG_SET *)loc_alloc_zero(sizeof(REG_SET));
- ext->pid = win32_event->dwThreadId;
- ext->handle = OpenThread(THREAD_ALL_ACCESS, FALSE, win32_event->dwThreadId);
- ext->debug_state = debug_state;
- ctx->mem = prs;
- ctx->big_endian = prs->big_endian;
- (ctx->parent = prs)->ref_count++;
- list_add_last(&ctx->cldl, &prs->children);
- link_context(ctx);
- send_context_created_event(ctx);
- debug_event->continue_status = event_win32_context_stopped(ctx);
- ext->debug_event = *win32_event;
- break;
- case EXCEPTION_DEBUG_EVENT:
- if (debug_state->state == DEBUG_STATE_PRS_CREATED && win32_event->u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) {
- if (debug_state->ini_thread_handle != NULL) ResumeThread(debug_state->ini_thread_handle);
- debug_state->attach_callback(0, prs, debug_state->attach_data);
- debug_state->attach_callback = NULL;
- debug_state->attach_data = NULL;
- debug_state->state = DEBUG_STATE_PRS_ATTACHED;
- ext = EXT(ctx = create_context(pid2id(debug_state->main_thread_id, win32_event->dwProcessId)));
- ext->regs = (REG_SET *)loc_alloc_zero(sizeof(REG_SET));
- ext->pid = debug_state->main_thread_id;
- ext->handle = OpenThread(THREAD_ALL_ACCESS, FALSE, debug_state->main_thread_id);
- ext->debug_state = debug_state;
- ctx->mem = prs;
- ctx->big_endian = prs->big_endian;
- (ctx->parent = prs)->ref_count++;
- list_add_last(&ctx->cldl, &prs->children);
- link_context(ctx);
- send_context_created_event(ctx);
- ctx->pending_intercept = 1;
- debug_event->continue_status = event_win32_context_stopped(ctx);
- ext->debug_event = *win32_event;
- }
- else if (ctx == NULL || ctx->exiting) {
- /* Does not work as expected: debug_event->continue_status = DBG_EXCEPTION_NOT_HANDLED; */
- }
- else {
- assert(prs != NULL);
- assert(!ctx->exited);
- if (ctx->stopped) {
- DWORD exception_code = win32_event->u.Exception.ExceptionRecord.ExceptionCode;
-#if USE_HW_BPS
- if (exception_code == EXCEPTION_SINGLE_STEP && win32_event->u.Exception.dwFirstChance) {
- /* This event appears to be caused by a hardware breakpoint.
- * It is safe to ignore the event - the breakpoint will be triggered again
- * when the context resumed. */
- debug_event->continue_status = DBG_CONTINUE;
- break;
- }
-#endif
- trace(LOG_ALWAYS, "context: already stopped, id %s, exception 0x%08x", ctx->id, exception_code);
- send_context_started_event(ctx);
- }
- ext = EXT(ctx);
- memcpy(&ext->suspend_reason, &win32_event->u.Exception, sizeof(EXCEPTION_DEBUG_INFO));
- debug_event->continue_status = event_win32_context_stopped(ctx);
- ext->debug_event = *win32_event;
- }
- break;
- case EXIT_THREAD_DEBUG_EVENT:
- assert(prs != NULL);
- if (ctx && !ctx->exited) event_win32_context_exited(ctx);
- if (debug_state->ini_thread_id == win32_event->dwThreadId) {
- debug_state->ini_thread_id = 0;
- debug_state->ini_thread_handle = NULL;
- }
- else if (debug_state->break_thread_id == win32_event->dwThreadId) {
- ext = EXT(prs);
- log_error("CloseHandle", CloseHandle(debug_state->break_thread));
- debug_state->break_thread = NULL;
- debug_state->break_thread_id = 0;
- }
- break;
- case EXIT_PROCESS_DEBUG_EVENT:
- assert(prs != NULL);
- if (ctx && !ctx->exited) event_win32_context_exited(ctx);
- event_win32_context_exited(prs);
- prs = NULL;
- if (debug_state->attach_callback != NULL) {
- int error = set_win32_errno(win32_event->u.ExitProcess.dwExitCode);
- debug_state->attach_callback(error, NULL, debug_state->attach_data);
- debug_state->attach_callback = NULL;
- debug_state->attach_data = NULL;
- }
- break;
- case LOAD_DLL_DEBUG_EVENT:
- assert(prs != NULL);
- debug_state->module_handle = win32_event->u.LoadDll.hFile;
- debug_state->module_address = (uintptr_t)win32_event->u.LoadDll.lpBaseOfDll;
- memory_map_event_module_loaded(prs);
- if (debug_state->module_handle != NULL) {
- log_error("CloseHandle", CloseHandle(debug_state->module_handle));
- }
- debug_state->module_handle = NULL;
- debug_state->module_address = 0;
- break;
- case UNLOAD_DLL_DEBUG_EVENT:
- assert(prs != NULL);
- debug_state->module_address = (uintptr_t)win32_event->u.UnloadDll.lpBaseOfDll;
- memory_map_event_module_unloaded(prs);
- debug_state->module_address = 0;
- break;
- case RIP_EVENT:
- trace(LOG_ALWAYS, "System debugging error: debuggee pid %d, error type %d, error code %d",
- win32_event->dwProcessId, win32_event->u.RipInfo.dwType, win32_event->u.RipInfo.dwError);
- break;
- }
-}
-
-static void continue_debug_event(void * args) {
- DebugEvent * debug_event = (DebugEvent *)args;
- DebugState * debug_state = debug_event->debug_state;
- Context * prs = context_find_from_pid(debug_state->process_id, 0);
-
- assert(debug_state->reporting_debug_event);
- if (debug_state->reporting_debug_event > 1) {
- debug_state->reporting_debug_event = 1;
- post_event(continue_debug_event, debug_event);
- return;
- }
-
- trace(LOG_WAITPID, "continue debug event 1, process id %u", debug_state->process_id);
-
- if (prs != NULL && !prs->exited) {
- LINK * l;
- for (l = prs->children.next; l != &prs->children; l = l->next) {
- Context * ctx = cldl2ctxp(l);
- ContextExtensionWin32 * ext = EXT(ctx);
- if (ctx->stopped || ctx->exited) {
- ext->stop_pending = 0;
- ext->start_pending = 0;
- continue;
- }
- if (ext->stop_pending) {
- memset(&ext->suspend_reason, 0, sizeof(ext->suspend_reason));
- event_win32_context_stopped(ctx);
- ext->debug_event = debug_event->win32_event;
- }
- if (ext->start_pending) {
- for (;;) {
- DWORD cnt = ResumeThread(ext->handle);
- if (cnt <= 1) break;
- }
- ext->start_pending = 0;
- }
- }
- }
-
- trace(LOG_WAITPID, "continue debug event, process id %u", debug_state->process_id);
- log_error("ReleaseSemaphore", SetEvent(debug_state->debug_event_inp));
- log_error("WaitForSingleObject", WaitForSingleObject(debug_state->debug_event_out, INFINITE) != WAIT_FAILED);
- debug_state->reporting_debug_event = 0;
-
- if (prs != NULL && !prs->exited) {
- LINK * l;
- for (l = prs->children.next; l != &prs->children; l = l->next) {
- Context * ctx = cldl2ctxp(l);
- ContextExtensionWin32 * ext = EXT(ctx);
- if (ext->start_pending) {
- for (;;) {
- DWORD cnt = ResumeThread(ext->handle);
- if (cnt <= 1) break;
- }
- ext->start_pending = 0;
- }
- }
- }
-
- log_error("ReleaseSemaphore", SetEvent(debug_state->debug_event_inp));
-}
-
-static void early_debug_event_handler(void * x) {
- DebugEvent * debug_event = (DebugEvent *)x;
- DebugState * debug_state = debug_event->debug_state;
- DEBUG_EVENT * win32_event = &debug_event->win32_event;
-
- if (win32_event->dwDebugEventCode == EXCEPTION_DEBUG_EVENT) {
- trace(LOG_WAITPID, "%s, process %d, thread %d, code %#lx",
- win32_debug_event_name(win32_event->dwDebugEventCode),
- win32_event->dwProcessId, win32_event->dwThreadId,
- win32_event->u.Exception.ExceptionRecord.ExceptionCode);
- }
- else {
- trace(LOG_WAITPID, "%s, process %d, thread %d",
- win32_debug_event_name(win32_event->dwDebugEventCode),
- win32_event->dwProcessId, win32_event->dwThreadId);
- }
-
- debug_state->reporting_debug_event = 1;
- debug_event_handler(debug_event);
- post_event(continue_debug_event, debug_event);
-}
-
-static void debugger_exit_handler(void * x) {
- DebugState * debug_state = (DebugState *)x;
- Context * prs = context_find_from_pid(debug_state->process_id, 0);
-
- trace(LOG_WAITPID, "debugger thread %d exited, debuggee pid %d", debug_state->debug_thread_id, debug_state->process_id);
-
- log_error("WaitForSingleObject", WaitForSingleObject(debug_state->debug_thread, INFINITE) != WAIT_FAILED);
- log_error("CloseHandle", CloseHandle(debug_state->debug_thread));
- log_error("CloseHandle", CloseHandle(debug_state->debug_event_inp));
- log_error("CloseHandle", CloseHandle(debug_state->debug_event_out));
-
- if (prs != NULL && !prs->exited) event_win32_context_exited(prs);
-
- loc_free(debug_state);
-}
-
-static DWORD WINAPI debugger_thread_func(LPVOID x) {
- DebugState * debug_state = (DebugState *)x;
- DebugEvent debug_event;
-
- if (DebugActiveProcess(debug_state->process_id) == 0) {
- debug_state->error = GetLastError();
- trace(LOG_ALWAYS, "Can't attach to a process: error %d", debug_state->error);
- ReleaseSemaphore(debug_state->debug_thread_semaphore, 1, 0);
- return 0;
- }
-
- trace(LOG_WAITPID, "debugger thread %d started", GetCurrentThreadId());
- ReleaseSemaphore(debug_state->debug_thread_semaphore, 1, 0);
-
- memset(&debug_event, 0, sizeof(debug_event));
-
- debug_event.debug_state = debug_state;
-
- for (;;) {
- DEBUG_EVENT * win32_event = &debug_event.win32_event;
-
- memset(win32_event, 0, sizeof(DEBUG_EVENT));
- if (WaitForDebugEvent(win32_event, INFINITE) == 0) {
- trace(LOG_ALWAYS, "WaitForDebugEvent() error %d", GetLastError());
- break;
- }
-
- assert(debug_state->process_id == win32_event->dwProcessId);
- debug_event.continue_status = DBG_CONTINUE;
-
- post_event(early_debug_event_handler, &debug_event);
- WaitForSingleObject(debug_state->debug_event_inp, INFINITE);
- if (ContinueDebugEvent(win32_event->dwProcessId, win32_event->dwThreadId, debug_event.continue_status) == 0) {
- trace(LOG_ALWAYS, "Can't continue debug event: process %d, thread %d: error %d",
- win32_event->dwProcessId, win32_event->dwThreadId, GetLastError());
- }
- SetEvent(debug_state->debug_event_out);
- WaitForSingleObject(debug_state->debug_event_inp, INFINITE);
-
- if (win32_event->dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break;
- if (win32_event->dwDebugEventCode == RIP_EVENT) break;
- }
-
- post_event(debugger_exit_handler, debug_state);
- return 0;
-}
-
-int context_attach(pid_t pid, ContextAttachCallBack * done, void * data, int mode) {
- int error = 0;
- DebugState * debug_state = (DebugState *)loc_alloc_zero(sizeof(DebugState));
-
- assert(done != NULL);
- assert((mode & CONTEXT_ATTACH_SELF) == 0);
- debug_state->process_id = pid;
- debug_state->attach_callback = done;
- debug_state->attach_data = data;
-
- debug_state->debug_event_inp = CreateEvent(NULL, 0, 0, NULL);
- if (debug_state->debug_event_inp == NULL) error = log_error("CreateEvent", 0);
-
- if (!error) {
- debug_state->debug_event_out = CreateEvent(NULL, 0, 0, NULL);
- if (debug_state->debug_event_out == NULL) error = log_error("CreateEvent", 0);
- }
-
- if (!error) {
- debug_state->debug_thread_semaphore = CreateSemaphore(NULL, 0, 1, NULL);
- if (debug_state->debug_thread_semaphore == NULL) error = log_error("CreateSemaphore", 0);
- }
-
- if (!error) {
- debug_state->debug_thread = CreateThread(NULL, 0, debugger_thread_func, debug_state, 0, &debug_state->debug_thread_id);
- if (debug_state->debug_thread == NULL) error = log_error("CreateThread", 0);
- }
-
- if (!error) {
- error = log_error("WaitForSingleObject", WaitForSingleObject(debug_state->debug_thread_semaphore, INFINITE) != WAIT_FAILED);
- }
-
- if (!error) {
- error = log_error("CloseHandle", CloseHandle(debug_state->debug_thread_semaphore));
- debug_state->debug_thread_semaphore = NULL;
- }
-
- if (!error) {
- error = set_win32_errno(debug_state->error);
- }
-
- if (error) {
- if (debug_state->debug_thread) log_error("WaitForSingleObject", WaitForSingleObject(debug_state->debug_thread, INFINITE) != WAIT_FAILED);
- if (debug_state->debug_thread) log_error("CloseHandle", CloseHandle(debug_state->debug_thread));
- if (debug_state->debug_event_inp) log_error("CloseHandle", CloseHandle(debug_state->debug_event_inp));
- if (debug_state->debug_event_out) log_error("CloseHandle", CloseHandle(debug_state->debug_event_out));
- if (debug_state->debug_thread_semaphore) log_error("CloseHandle", CloseHandle(debug_state->debug_thread_semaphore));
- loc_free(debug_state);
- errno = error;
- return -1;
- }
-
- add_waitpid_process(pid);
- return 0;
-}
-
-int context_has_state(Context * ctx) {
- return ctx != NULL && ctx->parent != NULL;
-}
-
-int context_stop(Context * ctx) {
- ContextExtensionWin32 * ext = EXT(ctx);
- DebugState * debug_state = EXT(ctx->parent)->debug_state;
-
- trace(LOG_CONTEXT, "context:%s suspending ctx %#lx id %s",
- ctx->pending_intercept ? "" : " temporary", ctx, ctx->id);
- assert(context_has_state(ctx));
- assert(!ctx->stopped);
- assert(!ctx->exited);
- if (debug_state->reporting_debug_event) {
- debug_state->reporting_debug_event++;
- }
- else if (!debug_state->break_posted) {
- context_lock(ctx->parent);
- post_event_with_delay(break_process_event, ctx->parent, 10000);
- debug_state->break_posted = 1;
- }
- ext->stop_pending = 1;
- return 0;
-}
-
-int context_continue(Context * ctx) {
- assert(is_dispatch_thread());
- assert(context_has_state(ctx));
- assert(ctx->stopped);
- assert(!ctx->exited);
-
- trace(LOG_CONTEXT, "context: resuming ctx %#lx, id %s", ctx, ctx->id);
- return win32_resume(ctx, 0);
-}
-
-int context_single_step(Context * ctx) {
- assert(is_dispatch_thread());
- assert(context_has_state(ctx));
- assert(ctx->stopped);
- assert(!ctx->exited);
-
- trace(LOG_CONTEXT, "context: single step ctx %#lx, id %s", ctx, ctx->id);
- return win32_resume(ctx, 1);
-}
-
-static int context_terminate(Context * ctx) {
- assert(is_dispatch_thread());
- assert(!context_has_state(ctx));
- assert(!ctx->exited);
-
- trace(LOG_CONTEXT, "context: terminate ctx %#lx, id %s", ctx, ctx->id);
- return win32_terminate(ctx);
-}
-
-int context_resume(Context * ctx, int mode, ContextAddress range_start, ContextAddress range_end) {
- switch (mode) {
- case RM_RESUME:
- return context_continue(ctx);
- case RM_STEP_INTO:
- return context_single_step(ctx);
- case RM_TERMINATE:
- return context_terminate(ctx);
- }
- errno = ERR_UNSUPPORTED;
- return -1;
-}
-
-int context_can_resume(Context * ctx, int mode) {
- switch (mode) {
- case RM_RESUME:
- return 1;
- case RM_STEP_INTO:
- return context_has_state(ctx);
- case RM_TERMINATE:
- return ctx != NULL && ctx->parent == NULL;
- }
- return 0;
-}
-
-int context_read_mem(Context * ctx, ContextAddress address, void * buf, size_t size) {
- ContextExtensionWin32 * ext = EXT(ctx = ctx->mem);
- SIZE_T bcnt = 0;
-
- trace(LOG_CONTEXT,
- "context: read memory ctx %#lx, id %s, address %#lx, size %d",
- ctx, ctx->id, address, (int)size);
- assert(is_dispatch_thread());
- mem_err_info.error = 0;
- if (ReadProcessMemory(ext->handle, (LPCVOID)address, buf, size, &bcnt) == 0 || bcnt != size) {
- DWORD error = GetLastError();
- size_t size_next = size;
- size_t size_error = 1;
- /* Check if a smaller block is readable */
- while (bcnt == 0) {
- if (size_next <= 1) break;
- size_next /= 2;
- ReadProcessMemory(ext->handle, (LPCVOID)address, buf, size_next, &bcnt);
- }
- /* Find upper bound of the readable memory */
- while (bcnt < size) {
- if (!ReadProcessMemory(ext->handle, (LPCVOID)(address + bcnt),
- (char *)buf + bcnt, 1, NULL)) {
- error = GetLastError();
- break;
- }
- bcnt++;
- }
- if (check_breakpoints_on_memory_read(ctx, address, buf, bcnt) < 0) return -1;
- /* Find number of unreadable bytes */
- while (size_error < 0x100 && bcnt + size_error < size) {
- if (ReadProcessMemory(ext->handle, (LPCVOID)(address + bcnt + size_error),
- (char *)buf + bcnt + size_error, 1, NULL)) break;
- if (error != GetLastError()) break;
- size_error++;
- }
- mem_err_info.error = set_win32_errno(error);
- mem_err_info.size_valid = bcnt;
- mem_err_info.size_error = size_error;
- return -1;
- }
- return check_breakpoints_on_memory_read(ctx, address, buf, size);
-}
-
-int context_write_mem(Context * ctx, ContextAddress address, void * buf, size_t size) {
- ContextExtensionWin32 * ext = EXT(ctx = ctx->mem);
- SIZE_T bcnt = 0;
-
- trace(LOG_CONTEXT,
- "context: write memory ctx %#lx, id %s, address %#lx, size %d",
- ctx, ctx->id, address, (int)size);
- assert(is_dispatch_thread());
- mem_err_info.error = 0;
- if (check_breakpoints_on_memory_write(ctx, address, buf, size) < 0) return -1;
- if (WriteProcessMemory(ext->handle, (LPVOID)address, buf, size, &bcnt) == 0 || bcnt != size) {
- mem_err_info.error = set_win32_errno(GetLastError());
- mem_err_info.size_valid = bcnt;
- mem_err_info.size_error = 1;
- }
- if (FlushInstructionCache(ext->handle, (LPCVOID)address, bcnt) == 0) {
- mem_err_info.error = 0;
- errno = log_error("FlushInstructionCache", 0);
- return -1;
- }
- if (mem_err_info.error) {
- errno = mem_err_info.error;
- return -1;
- }
- return 0;
-}
-
-#if ENABLE_ExtendedMemoryErrorReports
-int context_get_mem_error_info(MemoryErrorInfo * info) {
- if (mem_err_info.error == 0) {
- set_errno(ERR_OTHER, "Extended memory error info not available");
- return -1;
- }
- *info = mem_err_info;
- return 0;
-}
-#endif
-
-int context_write_reg(Context * ctx, RegisterDefinition * def, unsigned offs, unsigned size, void * buf) {
- ContextExtensionWin32 * ext = EXT(ctx);
-
- assert(is_dispatch_thread());
- assert(offs + size <= def->size);
-
- get_registers(ctx);
- if (ext->regs_error) {
- set_error_report_errno(ext->regs_error);
- return -1;
- }
- memcpy((uint8_t *)ext->regs + def->offset + offs, buf, size);
- ext->regs_dirty = 1;
- return 0;
-}
-
-int context_read_reg(Context * ctx, RegisterDefinition * def, unsigned offs, unsigned size, void * buf) {
- ContextExtensionWin32 * ext = EXT(ctx);
-
- assert(is_dispatch_thread());
- assert(offs + size <= def->size);
-
- get_registers(ctx);
- if (ext->regs_error) {
- set_error_report_errno(ext->regs_error);
- return -1;
- }
- memcpy(buf, (uint8_t *)ext->regs + def->offset + offs, size);
- return 0;
-}
-
-unsigned context_word_size(Context * ctx) {
- return sizeof(void *);
-}
-
-int context_get_canonical_addr(Context * ctx, ContextAddress addr,
- Context ** canonical_ctx, ContextAddress * canonical_addr,
- ContextAddress * block_addr, ContextAddress * block_size) {
- /* Direct mapping, page size is irrelevant */
- ContextAddress page_size = 0x100000;
- assert(is_dispatch_thread());
- *canonical_ctx = ctx->mem;
- if (canonical_addr != NULL) *canonical_addr = addr;
- if (block_addr != NULL) *block_addr = addr & ~(page_size - 1);
- if (block_size != NULL) *block_size = page_size;
- return 0;
-}
-
-Context * context_get_group(Context * ctx, int group) {
- static Context * cpu_group = NULL;
- switch (group) {
- case CONTEXT_GROUP_INTERCEPT:
- return ctx;
- case CONTEXT_GROUP_CPU:
- if (cpu_group == NULL) cpu_group = create_context("CPU");
- return cpu_group;
- }
- return ctx->mem;
-}
-
-int context_get_supported_bp_access_types(Context * ctx) {
-#if USE_HW_BPS
- if (ctx->mem == ctx) return
- CTX_BP_ACCESS_DATA_READ |
- CTX_BP_ACCESS_DATA_WRITE |
- CTX_BP_ACCESS_INSTRUCTION |
- CTX_BP_ACCESS_VIRTUAL;
-#endif
- return 0;
-}
-
-int context_plant_breakpoint(ContextBreakpoint * bp) {
-#if USE_HW_BPS
- int i;
- Context * ctx = bp->ctx;
- assert(bp->access_types);
- if (ctx->mem == ctx && (bp->access_types & CTX_BP_ACCESS_VIRTUAL)) {
- ContextExtensionWin32 * ext = EXT(ctx);
- DebugState * debug_state = ext->debug_state;
- if (debug_state->ok_to_use_hw_bp && bp->length <= 8 && ((1u << bp->length) & 0x116u)) {
- if (bp->access_types == (CTX_BP_ACCESS_INSTRUCTION | CTX_BP_ACCESS_VIRTUAL)) {
- /* Don't use more then 2 HW slots for regular instruction breakpoints */
- int cnt = 0;
- for (i = 0; i < MAX_HW_BPS; i++) {
- assert(debug_state->hw_bps[i] != bp);
- if (debug_state->hw_bps[i] == NULL) continue;
- if ((debug_state->hw_bps[i]->access_types & CTX_BP_ACCESS_INSTRUCTION) == 0) continue;
- cnt++;
- }
- if (cnt >= MAX_HW_BPS / 2) {
- errno = ERR_UNSUPPORTED;
- return -1;
- }
- }
- else if (bp->access_types != (CTX_BP_ACCESS_DATA_WRITE | CTX_BP_ACCESS_VIRTUAL) &&
- bp->access_types != (CTX_BP_ACCESS_DATA_READ | CTX_BP_ACCESS_DATA_WRITE | CTX_BP_ACCESS_VIRTUAL)) {
- errno = ERR_UNSUPPORTED;
- return -1;
- }
- for (i = 0; i < MAX_HW_BPS; i++) {
- if (debug_state->hw_bps[i] == NULL || debug_state->hw_bps[i] == bp) {
- debug_state->hw_bps[i] = bp;
- debug_state->hw_bps_generation++;
- return 0;
- }
- }
- }
- }
-#endif
- errno = ERR_UNSUPPORTED;
- return -1;
-}
-
-int context_unplant_breakpoint(ContextBreakpoint * bp) {
-#if USE_HW_BPS
- int i;
- Context * ctx = bp->ctx;
- if (ctx->mem == ctx && !ctx->exited) {
- ContextExtensionWin32 * ext = EXT(ctx);
- DebugState * debug_state = ext->debug_state;
- for (i = 0; i < MAX_HW_BPS; i++) {
- if (debug_state->hw_bps[i] == bp) {
- debug_state->hw_bps[i] = NULL;
- debug_state->hw_bps_generation++;
- }
- }
- }
-#endif
- return 0;
-}
-
-#if defined(_MSC_VER)
-
-static void add_map_region(MemoryMap * map, DWORD64 addr, ULONG size, char * file) {
- MemoryRegion * r = NULL;
- if (map->region_cnt >= map->region_max) {
- map->region_max += 8;
- map->regions = (MemoryRegion *)loc_realloc(map->regions, sizeof(MemoryRegion) * map->region_max);
- }
- r = map->regions + map->region_cnt++;
- memset(r, 0, sizeof(MemoryRegion));
- r->addr = (ContextAddress)addr;
- r->size = (ContextAddress)size;
- r->file_name = loc_strdup(file);
-}
-
-static BOOL CALLBACK modules_callback(PCWSTR ModuleName, DWORD64 ModuleBase, ULONG ModuleSize, PVOID UserContext) {
- MemoryMap * map = (MemoryMap *)UserContext;
- static char * fnm_buf = NULL;
- static int fnm_max = 0;
- int fnm_len = 0;
- int fnm_err = 0;
-
- if (fnm_buf == NULL) {
- fnm_max = 256;
- fnm_buf = (char *)loc_alloc(fnm_max);
- }
- for (;;) {
- fnm_len = WideCharToMultiByte(CP_UTF8, 0, ModuleName, -1, fnm_buf, fnm_max - 1, NULL, NULL);
- if (fnm_len != 0) break;
- fnm_err = GetLastError();
- if (fnm_err != ERROR_INSUFFICIENT_BUFFER) {
- set_win32_errno(fnm_err);
- trace(LOG_ALWAYS, "Can't get module name: %s", errno_to_str(errno));
- return TRUE;
- }
- fnm_max *= 2;
- fnm_buf = (char *)loc_realloc(fnm_buf, fnm_max);
- }
- fnm_buf[fnm_len] = 0;
-
- add_map_region(map, ModuleBase, ModuleSize, fnm_buf);
-
- return TRUE;
-}
-
-#endif
-
-int context_get_memory_map(Context * ctx, MemoryMap * map) {
- ctx = ctx->mem;
- assert(!ctx->exited);
-#if defined(_MSC_VER)
- {
- ContextExtensionWin32 * ext = EXT(ctx);
- if (!EnumerateLoadedModulesW64(ext->handle, modules_callback, map)) {
- set_win32_errno(GetLastError());
- return -1;
- }
- }
-#endif
- return 0;
-}
-
-HANDLE get_context_handle(Context * ctx) {
- ContextExtensionWin32 * ext = EXT(ctx);
- return ext->handle;
-}
-
-HANDLE get_context_file_handle(Context * ctx) {
- ContextExtensionWin32 * ext = EXT(ctx);
- return ext->debug_state->file_handle;
-}
-
-DWORD64 get_context_base_address(Context * ctx) {
- ContextExtensionWin32 * ext = EXT(ctx);
- return ext->debug_state->base_address;
-}
-
-HANDLE get_context_module_handle(Context * ctx) {
- ContextExtensionWin32 * ext = EXT(ctx);
- return ext->debug_state->module_handle;
-}
-
-DWORD64 get_context_module_address(Context * ctx) {
- ContextExtensionWin32 * ext = EXT(ctx);
- return ext->debug_state->module_address;
-}
-
-void add_context_exception_handler(ContextExceptionHandler * h) {
- assert(exception_handler_cnt < MAX_EXCEPTION_HANDLERS);
- exception_handlers[exception_handler_cnt++] = h;
-}
-
-static void eventpoint_at_main(Context * ctx, void * args) {
- suspend_debug_context(ctx);
-}
-
-static void waitpid_listener(int pid, int exited, int exit_code, int signal, int event_code, int syscall, void * args) {
-}
-
-void init_contexts_sys_dep(void) {
- context_extension_offset = context_extension(sizeof(ContextExtensionWin32));
- ini_context_pid_hash();
- add_waitpid_listener(waitpid_listener, NULL);
- memset(&os_version, 0, sizeof(os_version));
- os_version.dwOSVersionInfoSize = sizeof(os_version);
- GetVersionEx((OSVERSIONINFO *)&os_version);
- create_eventpoint("main", NULL, eventpoint_at_main, NULL);
-}
-
-#endif /* if ENABLE_DebugContext */
-#endif /* WIN32 */
diff --git a/agent/tcf/system/Windows/context-win32.h b/agent/tcf/system/Windows/context-win32.h
deleted file mode 100644
index 8c49751e..00000000
--- a/agent/tcf/system/Windows/context-win32.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-/*
- * This module handles process/thread OS contexts and their state machine.
- */
-
-#ifndef D_context_win32
-#define D_context_win32
-
-#include <tcf/config.h>
-#include <tcf/framework/context.h>
-
-extern HANDLE get_context_handle(Context * ctx);
-extern HANDLE get_context_file_handle(Context * ctx);
-extern HANDLE get_context_module_handle(Context * ctx);
-
-extern DWORD64 get_context_base_address(Context * ctx);
-extern DWORD64 get_context_module_address(Context * ctx);
-
-typedef int ContextExceptionHandler(Context *, EXCEPTION_DEBUG_INFO *);
-extern void add_context_exception_handler(ContextExceptionHandler * h);
-
-#endif /* D_context_win32 */
diff --git a/agent/tcf/system/Windows/pthreads-win32.c b/agent/tcf/system/Windows/pthreads-win32.c
deleted file mode 100644
index e6118798..00000000
--- a/agent/tcf/system/Windows/pthreads-win32.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010, 2011 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-#include <tcf/config.h>
-
-#if defined(WIN32) && !defined(DISABLE_PTHREADS_WIN32)
-
-#include <assert.h>
-#include <tcf/framework/myalloc.h>
-#include <tcf/framework/errors.h>
-#include <tcf/system/Windows/pthreads-win32.h>
-
-/*********************************************************************
- Support of pthreads on Windows is implemented according to
- recommendations from the paper:
-
- Strategies for Implementing POSIX Condition Variables on Win32
- C++ Report, SIGS, Vol. 10, No. 5, June, 1998
-
- Douglas C. Schmidt and Irfan Pyarali
- Department of Computer Science
- Washington University, St. Louis, Missouri
-**********************************************************************/
-
-/* TODO: POSIX pthread functions don't set errno */
-
-typedef struct {
- int waiters_count;
- CRITICAL_SECTION waiters_count_lock;
- HANDLE sema;
- HANDLE waiters_done;
- size_t was_broadcast;
-} PThreadCond;
-
-int pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutexattr_t * attr) {
- assert(attr == NULL);
- *mutex = (pthread_mutex_t)CreateMutex(NULL, FALSE, NULL);
- if (*mutex == NULL) return set_win32_errno(GetLastError());
- return 0;
-}
-
-int pthread_mutex_lock(pthread_mutex_t * mutex) {
- assert(mutex != NULL);
- assert(*mutex != NULL);
- if (WaitForSingleObject(*mutex, INFINITE) == WAIT_FAILED) return set_win32_errno(GetLastError());
- return 0;
-}
-
-int pthread_mutex_unlock(pthread_mutex_t * mutex) {
- assert(mutex != NULL);
- assert(*mutex != NULL);
- if (!ReleaseMutex(*mutex)) return set_win32_errno(GetLastError());
- return 0;
-}
-
-int pthread_mutex_destroy(pthread_mutex_t *mutex) {
- assert(mutex != NULL);
- assert(*mutex != NULL);
- if (!CloseHandle(*mutex)) return set_win32_errno(GetLastError());
- return 0;
-}
-
-int pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t * attr) {
- PThreadCond * p = (PThreadCond *)loc_alloc_zero(sizeof(PThreadCond));
- assert(attr == NULL);
- p->waiters_count = 0;
- p->was_broadcast = 0;
- p->sema = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
- if (p->sema == NULL) return set_win32_errno(GetLastError());
- InitializeCriticalSection(&p->waiters_count_lock);
- p->waiters_done = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (p->waiters_done == NULL) return set_win32_errno(GetLastError());
- *cond = (pthread_cond_t)p;
- return 0;
-}
-
-int pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex) {
- DWORD res = 0;
- int last_waiter = 0;
- PThreadCond * p = (PThreadCond *)*cond;
-
- EnterCriticalSection(&p->waiters_count_lock);
- p->waiters_count++;
- LeaveCriticalSection(&p->waiters_count_lock);
-
- /* This call atomically releases the mutex and waits on the */
- /* semaphore until <pthread_cond_signal> or <pthread_cond_broadcast> */
- /* are called by another thread. */
- res = SignalObjectAndWait(*mutex, p->sema, INFINITE, FALSE);
- if (res == WAIT_FAILED) return set_win32_errno(GetLastError());
-
- /* Re-acquire lock to avoid race conditions. */
- EnterCriticalSection(&p->waiters_count_lock);
-
- /* We're no longer waiting... */
- p->waiters_count--;
-
- /* Check to see if we're the last waiter after <pthread_cond_broadcast>. */
- last_waiter = p->was_broadcast && p->waiters_count == 0;
-
- LeaveCriticalSection(&p->waiters_count_lock);
-
- /* If we're the last waiter thread during this particular broadcast */
- /* then let all the other threads proceed. */
- if (last_waiter) {
- /* This call atomically signals the <waiters_done_> event and waits until */
- /* it can acquire the <mutex>. This is required to ensure fairness. */
- DWORD err = SignalObjectAndWait(p->waiters_done, *mutex, INFINITE, FALSE);
- if (err == WAIT_FAILED) return set_win32_errno(GetLastError());
- }
- else {
- /* Always regain the external mutex since that's the guarantee we */
- /* give to our callers. */
- DWORD err = WaitForSingleObject(*mutex, INFINITE);
- if (err == WAIT_FAILED) return set_win32_errno(GetLastError());
- }
- assert(res == WAIT_OBJECT_0);
- return 0;
-}
-
-int pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex, const struct timespec * abstime) {
- DWORD res = 0;
- int last_waiter = 0;
- PThreadCond * p = (PThreadCond *)*cond;
- DWORD timeout = 0;
- struct timespec timenow;
-
- if (clock_gettime(CLOCK_REALTIME, &timenow)) return errno;
- if (abstime->tv_sec < timenow.tv_sec) return ETIMEDOUT;
- if (abstime->tv_sec == timenow.tv_sec) {
- if (abstime->tv_nsec <= timenow.tv_nsec) return ETIMEDOUT;
- }
- timeout = (DWORD)((abstime->tv_sec - timenow.tv_sec) * 1000 + (abstime->tv_nsec - timenow.tv_nsec) / 1000000 + 5);
-
- EnterCriticalSection(&p->waiters_count_lock);
- p->waiters_count++;
- LeaveCriticalSection(&p->waiters_count_lock);
-
- /* This call atomically releases the mutex and waits on the */
- /* semaphore until <pthread_cond_signal> or <pthread_cond_broadcast> */
- /* are called by another thread. */
- res = SignalObjectAndWait(*mutex, p->sema, timeout, FALSE);
- if (res == WAIT_FAILED) return set_win32_errno(GetLastError());
-
- /* Re-acquire lock to avoid race conditions. */
- EnterCriticalSection(&p->waiters_count_lock);
-
- /* We're no longer waiting... */
- p->waiters_count--;
-
- /* Check to see if we're the last waiter after <pthread_cond_broadcast>. */
- last_waiter = p->was_broadcast && p->waiters_count == 0;
-
- LeaveCriticalSection(&p->waiters_count_lock);
-
- /* If we're the last waiter thread during this particular broadcast */
- /* then let all the other threads proceed. */
- if (last_waiter) {
- /* This call atomically signals the <waiters_done> event and waits until */
- /* it can acquire the <mutex>. This is required to ensure fairness. */
- DWORD err = SignalObjectAndWait(p->waiters_done, *mutex, INFINITE, FALSE);
- if (err == WAIT_FAILED) return set_win32_errno(GetLastError());
- }
- else {
- /* Always regain the external mutex since that's the guarantee we */
- /* give to our callers. */
- DWORD err = WaitForSingleObject(*mutex, INFINITE);
- if (err == WAIT_FAILED) return set_win32_errno(GetLastError());
- }
-
- if (res == WAIT_TIMEOUT) return errno = ETIMEDOUT;
- assert(res == WAIT_OBJECT_0);
- return 0;
-}
-
-int pthread_cond_signal(pthread_cond_t * cond) {
- int have_waiters = 0;
- PThreadCond * p = (PThreadCond *)*cond;
-
- EnterCriticalSection(&p->waiters_count_lock);
- have_waiters = p->waiters_count > 0;
- LeaveCriticalSection(&p->waiters_count_lock);
-
- /* If there aren't any waiters, then this is a no-op. */
- if (have_waiters) {
- if (!ReleaseSemaphore(p->sema, 1, 0)) return set_win32_errno(GetLastError());
- }
- return 0;
-}
-
-int pthread_cond_broadcast(pthread_cond_t * cond) {
- int have_waiters = 0;
- PThreadCond * p = (PThreadCond *)*cond;
-
- /* This is needed to ensure that <waiters_count_> and <was_broadcast_> are */
- /* consistent relative to each other. */
- EnterCriticalSection(&p->waiters_count_lock);
-
- if (p->waiters_count > 0) {
- /* We are broadcasting, even if there is just one waiter... */
- /* Record that we are broadcasting, which helps optimize */
- /* <pthread_cond_wait> for the non-broadcast case. */
- p->was_broadcast = 1;
- have_waiters = 1;
- }
-
- if (have_waiters) {
- /* Wake up all the waiters atomically. */
- if (!ReleaseSemaphore(p->sema, p->waiters_count, 0)) return set_win32_errno(GetLastError());
-
- LeaveCriticalSection(&p->waiters_count_lock);
-
- /* Wait for all the awakened threads to acquire the counting */
- /* semaphore. */
- if (WaitForSingleObject(p->waiters_done, INFINITE) == WAIT_FAILED) return set_win32_errno(GetLastError());
- /* This assignment is okay, even without the <waiters_count_lock_> held */
- /* because no other waiter threads can wake up to access it. */
- p->was_broadcast = 0;
- }
- else {
- LeaveCriticalSection(&p->waiters_count_lock);
- }
- return 0;
-}
-
-int pthread_cond_destroy(pthread_cond_t * cond) {
- PThreadCond * p = (PThreadCond *)*cond;
-
- DeleteCriticalSection(&p->waiters_count_lock);
- if (!CloseHandle(p->sema)) return set_win32_errno(GetLastError());
- if (!CloseHandle(p->waiters_done)) return set_win32_errno(GetLastError());
-
- loc_free(p);
- *cond = NULL;
- return 0;
-}
-
-typedef struct ThreadArgs ThreadArgs;
-
-struct ThreadArgs {
- void * (*start)(void *);
- void * args;
-};
-
-static void start_thread(void * x) {
- ThreadArgs a = *(ThreadArgs *)x;
-
- loc_free(x);
- ExitThread((DWORD)a.start(a.args));
-}
-
-int pthread_create(pthread_t * res, const pthread_attr_t * attr,
- void * (*start)(void *), void * args) {
- HANDLE thread = NULL;
- DWORD thread_id = 0;
- ThreadArgs * a = (ThreadArgs *)loc_alloc(sizeof(ThreadArgs));
-
- a->start = start;
- a->args = args;
- thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)start_thread, a, 0, &thread_id);
- if (thread == NULL) {
- int err = set_win32_errno(GetLastError());
- loc_free(a);
- return errno = err;
- }
- if (!CloseHandle(thread)) return set_win32_errno(GetLastError());
- *res = (pthread_t)thread_id;
- return 0;
-}
-
-int pthread_join(pthread_t thread_id, void ** value_ptr) {
- int error = 0;
- HANDLE thread = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION, FALSE, (DWORD)thread_id);
-
- if (thread == NULL) return set_win32_errno(GetLastError());
- if (WaitForSingleObject(thread, INFINITE) == WAIT_FAILED) error = set_win32_errno(GetLastError());
- if (!error && value_ptr != NULL && !GetExitCodeThread(thread, (LPDWORD)value_ptr)) error = set_win32_errno(GetLastError());
- if (!CloseHandle(thread) && !error) error = set_win32_errno(GetLastError());
- return error;
-}
-
-int pthread_detach(pthread_t thread_id) {
- return 0;
-}
-
-pthread_t pthread_self(void) {
- return (pthread_t)GetCurrentThreadId();
-}
-
-int pthread_equal(pthread_t thread1, pthread_t thread2) {
- return thread1 == thread2;
-}
-
-int pthread_attr_init(pthread_attr_t * attr) {
- *attr = NULL;
- return 0;
-}
-
-#endif
diff --git a/agent/tcf/system/Windows/pthreads-win32.h b/agent/tcf/system/Windows/pthreads-win32.h
deleted file mode 100644
index e98874e0..00000000
--- a/agent/tcf/system/Windows/pthreads-win32.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2011 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-/*
- * PThreads emulation for Windows.
- */
-
-#ifndef D_pthreads_win32
-#define D_pthreads_win32
-
-#if defined(__CYGWIN__)
-# include <cygwin/types.h>
-#else
-typedef struct pthread_struct * pthread_t;
-typedef struct pthread_attr_struct * pthread_attr_t;
-typedef struct pthread_mutex_struct * pthread_mutex_t;
-typedef struct pthread_cond_struct * pthread_cond_t;
-typedef struct pthread_mutexattr_struct * pthread_mutexattr_t;
-typedef struct pthread_condattr_struct * pthread_condattr_t;
-#endif
-
-extern int pthread_attr_init(pthread_attr_t * attr);
-
-extern int pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t * attr);
-extern int pthread_cond_signal(pthread_cond_t * cond);
-extern int pthread_cond_broadcast(pthread_cond_t * cond);
-extern int pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex);
-extern int pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex,
- const struct timespec * abstime);
-extern int pthread_cond_destroy(pthread_cond_t * cond);
-
-extern int pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutexattr_t * attr);
-extern int pthread_mutex_lock(pthread_mutex_t * mutex);
-extern int pthread_mutex_unlock(pthread_mutex_t * mutex);
-extern int pthread_mutex_destroy(pthread_mutex_t *mutex);
-
-extern pthread_t pthread_self(void);
-extern int pthread_create(pthread_t * thread, const pthread_attr_t * attr,
- void * (*start_routine)(void *), void * arg);
-extern int pthread_join(pthread_t thread, void **value_ptr);
-extern int pthread_detach(pthread_t thread);
-extern int pthread_equal(pthread_t thread1, pthread_t thread2);
-
-#endif /* D_pthreads_win32 */
diff --git a/agent/tcf/system/Windows/regset.h b/agent/tcf/system/Windows/regset.h
deleted file mode 100644
index fb4eab83..00000000
--- a/agent/tcf/system/Windows/regset.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-/*
- * This header file provides definition of REG_SET - a structure that can
- * hold values of target CPU registers.
- */
-
-#if defined(WIN32)
- typedef CONTEXT REG_SET;
-#endif
diff --git a/agent/tcf/system/Windows/windbgcache.c b/agent/tcf/system/Windows/windbgcache.c
deleted file mode 100644
index e6f094f2..00000000
--- a/agent/tcf/system/Windows/windbgcache.c
+++ /dev/null
@@ -1,405 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-/*
- * This module provides access to Windows Portable Executable debug information.
- * Current implementation delegates all its job to DBGHELP.DLL.
- */
-
-#include <tcf/config.h>
-
-#if defined(WIN32) && !ENABLE_ELF
-# define ENABLE_PE_Symbols ((SERVICE_LineNumbers && !ENABLE_LineNumbersProxy) || (SERVICE_Symbols && !ENABLE_SymbolsProxy))
-# define ENABLE_EnumerateModules (SERVICE_MemoryMap && !ENABLE_ContextProxy)
-#else
-# define ENABLE_PE_Symbols 0
-# define ENABLE_EnumerateModules 0
-#endif
-
-#if ENABLE_PE_Symbols || ENABLE_EnumerateModules
-
-#include <assert.h>
-#include <stdio.h>
-#include <wchar.h>
-#include <tcf/system/Windows/windbgcache.h>
-#include <tcf/system/Windows/context-win32.h>
-#include <tcf/framework/trace.h>
-#include <tcf/framework/myalloc.h>
-#include <tcf/services/memorymap.h>
-
-static HINSTANCE dbghelp_dll = NULL;
-
-#define SYM_SEARCH_PATH ""
-/* Path could contain "http://msdl.microsoft.com/download/symbols",
- but access to Microsoft debug info server is too slow,
- and dbghelp.dll caching is inadequate
-*/
-
-static wchar_t * pathes[] = {
- L"%\\Debugging Tools for Windows (x86)\\dbghelp.dll",
- L"%\\Debugging Tools for Windows\\dbghelp.dll",
- L".\\dbghelp.dll",
- L"dbghelp.dll",
- NULL
-};
-
-#if ENABLE_PE_Symbols
-
-static void event_context_created(Context * ctx, void * client_data) {
- HANDLE handle = NULL;
- if (ctx->parent != NULL) return;
- handle = get_context_handle(ctx);
- assert(handle != NULL);
- assert(ctx->mem == ctx);
- if (!SymInitialize(handle, SYM_SEARCH_PATH, FALSE)) {
- set_win32_errno(GetLastError());
- trace(LOG_ALWAYS, "SymInitialize() error: %s", errno_to_str(errno));
- }
- if (!SymLoadModule64(handle, get_context_file_handle(ctx),
- NULL, NULL, get_context_base_address(ctx), 0)) {
- set_win32_errno(GetLastError());
- trace(LOG_ALWAYS, "SymLoadModule64() error: %s", errno_to_str(errno));
- }
-}
-
-static void event_context_exited(Context * ctx, void * client_data) {
- HANDLE handle = NULL;
- if (ctx->parent != NULL) return;
- handle = get_context_handle(ctx);
- assert(handle != NULL);
- assert(ctx->mem == ctx);
- if (!SymUnloadModule64(handle, get_context_base_address(ctx))) {
- set_win32_errno(GetLastError());
- trace(LOG_ALWAYS, "SymUnloadModule64(0x%Ix,0x%I64x) (context exit) error: %s",
- handle, get_context_base_address(ctx), errno_to_str(errno));
- }
- if (!SymCleanup(handle)) {
- set_win32_errno(GetLastError());
- trace(LOG_ALWAYS, "SymCleanup() error: %s", errno_to_str(errno));
- }
-}
-
-static void event_module_loaded(Context * ctx, void * client_data) {
- HANDLE handle = get_context_handle(ctx);
- assert(handle != NULL);
- assert(ctx->mem == ctx);
- if (!SymLoadModule64(handle, get_context_module_handle(ctx),
- NULL, NULL, get_context_module_address(ctx), 0)) {
- set_win32_errno(GetLastError());
- trace(LOG_ALWAYS, "SymLoadModule64() error: %s", errno_to_str(errno));
- }
-}
-
-static void event_module_unloaded(Context * ctx, void * client_data) {
- HANDLE handle = get_context_handle(ctx);
- assert(handle != NULL);
- assert(ctx->mem == ctx);
- if (!SymUnloadModule64(handle, get_context_module_address(ctx))) {
- DWORD err = GetLastError();
- /* Workaround:
- * On Windows 7 first few UNLOAD_DLL_DEBUG_EVENT come without matching LOAD_DLL_DEBUG_EVENT,
- * SymUnloadModule64() returns error 0x57 "The parameter is incorrect" for such events.
- * No proper fix is found for this issue. */
- if (err != 0x57) {
- int n = set_win32_errno(err);
- trace(LOG_ALWAYS, "SymUnloadModule64(0x%Ix,0x%I64x) (unload DLL) error: %s",
- handle, get_context_module_address(ctx), errno_to_str(n));
- }
- }
-}
-
-static ContextEventListener ctx_listener = {
- event_context_created,
- event_context_exited,
-};
-
-static MemoryMapEventListener map_listener = {
- event_module_loaded,
- NULL,
- event_module_unloaded
-};
-
-#endif
-
-static void CheckDLLVersion(void) {
- DWORD handle = 0;
- WCHAR fnm[_MAX_PATH];
- BYTE * version_info = NULL;
- DWORD size = GetModuleFileNameW(dbghelp_dll, fnm, _MAX_PATH);
- fnm[size] = 0;
- size = GetFileVersionInfoSizeW(fnm, &handle);
- version_info = (BYTE *)loc_alloc_zero(size);
- if (!GetFileVersionInfoW(fnm, handle, size, version_info)) {
- trace(LOG_ALWAYS, "Cannot get DBGHELP.DLL version info: %s",
- errno_to_str(set_win32_errno(GetLastError())));
- }
- else {
- UINT vsfi_len = 0;
- VS_FIXEDFILEINFO * vsfi = NULL;
- VerQueryValueW(version_info, L"\\", (void**)&vsfi, &vsfi_len);
- if (HIWORD(vsfi->dwFileVersionMS) < 6 || HIWORD(vsfi->dwFileVersionMS) == 6 && LOWORD(vsfi->dwFileVersionMS) < 9) {
- char path[_MAX_PATH * 2];
- trace(LOG_ALWAYS, "DBGHELP.DLL version is less then 6.9 - debug services might not work properly");
- if (WideCharToMultiByte(CP_UTF8, 0, fnm, -1, path, sizeof(path), NULL, NULL)) {
- trace(LOG_ALWAYS, "%s", path);
- }
- trace(LOG_ALWAYS, "DBGHELP.DLL version %d.%d.%d.%d",
- HIWORD(vsfi->dwFileVersionMS), LOWORD(vsfi->dwFileVersionMS),
- HIWORD(vsfi->dwFileVersionLS), LOWORD(vsfi->dwFileVersionLS));
- }
- }
- loc_free(version_info);
-}
-
-static FARPROC GetProc(char * name) {
- if (dbghelp_dll == NULL) {
- wchar_t ** p = pathes;
- while (dbghelp_dll == NULL && *p != NULL) {
- if (**p == '%') {
- HKEY key;
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
- L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion",
- 0, KEY_READ, &key) == ERROR_SUCCESS) {
- wchar_t buf[FILE_PATH_SIZE];
- DWORD size = sizeof(buf);
- memset(buf, 0, sizeof(buf));
- if (RegQueryValueExW(key,
- L"ProgramFilesDir (x86)",
- NULL, NULL, (LPBYTE)buf, &size) == ERROR_SUCCESS) {
- wcsncat(buf, *p + 1, FILE_PATH_SIZE - size / sizeof(wchar_t));
- dbghelp_dll = LoadLibraryW(buf);
- }
- if (dbghelp_dll == NULL) {
- size = sizeof(buf);
- memset(buf, 0, sizeof(buf));
- if (RegQueryValueExW(key,
- L"ProgramFilesDir",
- NULL, NULL, (LPBYTE)buf, &size) == ERROR_SUCCESS) {
- wcsncat(buf, *p + 1, FILE_PATH_SIZE - size / sizeof(wchar_t));
- dbghelp_dll = LoadLibraryW(buf);
- }
- }
- RegCloseKey(key);
- }
- }
- else {
- dbghelp_dll = LoadLibraryW(*p);
- }
- p++;
- }
- if (dbghelp_dll == NULL) {
- assert(GetLastError() != 0);
- return NULL;
- }
- CheckDLLVersion();
-#if ENABLE_PE_Symbols
- add_context_event_listener(&ctx_listener, NULL);
- add_memory_map_event_listener(&map_listener, NULL);
-#endif
- }
- return GetProcAddress(dbghelp_dll, name);
-}
-
-#endif
-
-#if ENABLE_PE_Symbols
-
-BOOL SymInitialize(HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess) {
- typedef BOOL (FAR WINAPI * ProcType)(HANDLE, PCSTR, BOOL);
- static ProcType proc = NULL;
- if (proc == NULL) {
- proc = (ProcType)GetProc("SymInitialize");
- if (proc == NULL) return 0;
- }
- return proc(hProcess, UserSearchPath, fInvadeProcess);
-}
-
-DWORD SymGetOptions(void) {
- typedef DWORD (FAR WINAPI * ProcType)(void);
- static ProcType proc = NULL;
- if (proc == NULL) {
- proc = (ProcType)GetProc("SymGetOptions");
- if (proc == NULL) return 0;
- }
- return proc();
-}
-
-BOOL SymSetOptions(DWORD Options) {
- typedef BOOL (FAR WINAPI * ProcType)(DWORD);
- static ProcType proc = NULL;
- if (proc == NULL) {
- proc = (ProcType)GetProc("SymSetOptions");
- if (proc == NULL) return 0;
- }
- return proc(Options);
-}
-
-BOOL SymGetLineFromName(HANDLE hProcess, PCSTR ModuleName, PCSTR FileName, DWORD dwLineNumber, PLONG plDisplacement, PIMAGEHLP_LINE Line) {
- typedef BOOL (FAR WINAPI * ProcType)(HANDLE, PCSTR, PCSTR, DWORD, PLONG, PIMAGEHLP_LINE);
- static ProcType proc = NULL;
- if (proc == NULL) {
- proc = (ProcType)GetProc("SymGetLineFromName");
- if (proc == NULL) return 0;
- }
- return proc(hProcess, ModuleName, FileName, dwLineNumber, plDisplacement, Line);
-}
-
-BOOL SymGetLineFromAddr(HANDLE hProcess, DWORD dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE Line) {
- typedef BOOL (FAR WINAPI * ProcType)(HANDLE, DWORD, PDWORD, PIMAGEHLP_LINE);
- static ProcType proc = NULL;
- if (proc == NULL) {
- proc = (ProcType)GetProc("SymGetLineFromAddr");
- if (proc == NULL) return 0;
- }
- return proc(hProcess, dwAddr, pdwDisplacement, Line);
-}
-
-BOOL SymGetLineNext(HANDLE hProcess, PIMAGEHLP_LINE Line) {
- typedef BOOL (FAR WINAPI * ProcType)(HANDLE, PIMAGEHLP_LINE);
- static ProcType proc = NULL;
- if (proc == NULL) {
- proc = (ProcType)GetProc("SymGetLineNext");
- if (proc == NULL) return 0;
- }
- assert(Line != NULL);
- assert(Line->Address != 0);
- return proc(hProcess, Line);
-}
-
-BOOL SymGetTypeInfo(HANDLE hProcess, DWORD64 ModBase, ULONG TypeId, IMAGEHLP_SYMBOL_TYPE_INFO GetType, PVOID pInfo) {
- typedef BOOL (FAR WINAPI * ProcType)(HANDLE, DWORD64, ULONG, IMAGEHLP_SYMBOL_TYPE_INFO, PVOID);
- static ProcType proc = NULL;
- if (proc == NULL) {
- proc = (ProcType)GetProc("SymGetTypeInfo");
- if (proc == NULL) return 0;
- }
- return proc(hProcess, ModBase, TypeId, GetType, pInfo);
-}
-
-BOOL SymFromIndex(HANDLE hProcess, ULONG64 BaseOfDll, DWORD Index, PSYMBOL_INFO Symbol) {
- typedef BOOL (FAR WINAPI * ProcType)(HANDLE, ULONG64, DWORD, PSYMBOL_INFO);
- static ProcType proc = NULL;
- if (proc == NULL) {
- proc = (ProcType)GetProc("SymFromIndex");
- if (proc == NULL) return 0;
- }
- return proc(hProcess, BaseOfDll, Index, Symbol);
-}
-
-BOOL SymFromAddr(HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol) {
- typedef BOOL (FAR WINAPI * ProcType)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFO);
- static ProcType proc = NULL;
- if (proc == NULL) {
- proc = (ProcType)GetProc("SymFromAddr");
- if (proc == NULL) return 0;
- }
- return proc(hProcess, Address, Displacement, Symbol);
-}
-
-BOOL SymSetContext(HANDLE hProcess, PIMAGEHLP_STACK_FRAME StackFrame, PIMAGEHLP_CONTEXT Context) {
- typedef BOOL (FAR WINAPI * ProcType)(HANDLE, PIMAGEHLP_STACK_FRAME, PIMAGEHLP_CONTEXT);
- static ProcType proc = NULL;
- if (proc == NULL) {
- proc = (ProcType)GetProc("SymSetContext");
- if (proc == NULL) return 0;
- }
- return proc(hProcess, StackFrame, Context);
-}
-
-BOOL SymFromName(HANDLE hProcess, PCSTR Name, PSYMBOL_INFO Symbol) {
- typedef BOOL (FAR WINAPI * ProcType)(HANDLE, PCSTR, PSYMBOL_INFO);
- static ProcType proc = NULL;
- if (proc == NULL) {
- proc = (ProcType)GetProc("SymFromName");
- if (proc == NULL) return 0;
- }
- return proc(hProcess, Name, Symbol);
-}
-
-BOOL SymEnumSymbols(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR Mask, PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, PVOID UserContext) {
- typedef BOOL (FAR WINAPI * ProcType)(HANDLE, ULONG64, PCSTR, PSYM_ENUMERATESYMBOLS_CALLBACK, PVOID);
- static ProcType proc = NULL;
- if (proc == NULL) {
- proc = (ProcType)GetProc("SymEnumSymbols");
- if (proc == NULL) return 0;
- }
- return proc(hProcess, BaseOfDll, Mask, EnumSymbolsCallback, UserContext);
-}
-
-BOOL SymGetTypeFromName(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR Name, PSYMBOL_INFO Symbol) {
- typedef BOOL (FAR WINAPI * ProcType)(HANDLE, ULONG64, PCSTR, PSYMBOL_INFO);
- static ProcType proc = NULL;
- if (proc == NULL) {
- proc = (ProcType)GetProc("SymGetTypeFromName");
- if (proc == NULL) return 0;
- }
- return proc(hProcess, BaseOfDll, Name, Symbol);
-}
-
-DWORD64 SymGetModuleBase64(HANDLE hProcess, ULONG64 Address) {
- typedef DWORD64 (FAR WINAPI * ProcType)(HANDLE, ULONG64);
- static ProcType proc = NULL;
- if (proc == NULL) {
- proc = (ProcType)GetProc("SymGetModuleBase64");
- if (proc == NULL) return 0;
- }
- return proc(hProcess, Address);
-}
-
-BOOL SymLoadModule64(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll) {
- typedef BOOL (FAR WINAPI * ProcType)(HANDLE, HANDLE, PCSTR, PCSTR, DWORD64, DWORD);
- static ProcType proc = NULL;
- if (proc == NULL) {
- proc = (ProcType)GetProc("SymLoadModule64");
- if (proc == NULL) return 0;
- }
- return proc(hProcess, hFile, ImageName, ModuleName, BaseOfDll, SizeOfDll);
-}
-
-BOOL SymUnloadModule64(HANDLE hProcess, DWORD64 BaseOfDll) {
- typedef BOOL (FAR WINAPI * ProcType)(HANDLE, DWORD64);
- static ProcType proc = NULL;
- if (proc == NULL) {
- proc = (ProcType)GetProc("SymUnloadModule64");
- if (proc == NULL) return 0;
- }
- return proc(hProcess, BaseOfDll);
-}
-
-BOOL SymCleanup(HANDLE hProcess) {
- typedef BOOL (FAR WINAPI * ProcType)(HANDLE);
- static ProcType proc = NULL;
- if (proc == NULL) {
- proc = (ProcType)GetProc("SymCleanup");
- if (proc == NULL) return 0;
- }
- return proc(hProcess);
-}
-
-#endif
-
-#if ENABLE_EnumerateModules
-
-BOOL LocEnumerateLoadedModulesW64(HANDLE hProcess, PENUMLOADED_MODULES_CALLBACKW64 Callback, PVOID UserContext) {
- typedef BOOL (FAR WINAPI * ProcType)(HANDLE, PENUMLOADED_MODULES_CALLBACKW64, PVOID);
- static ProcType proc = NULL;
- if (proc == NULL) {
- proc = (ProcType)GetProc("EnumerateLoadedModulesW64");
- if (proc == NULL) return 0;
- }
- return proc(hProcess, Callback, UserContext);
-}
-
-#endif
diff --git a/agent/tcf/system/Windows/windbgcache.h b/agent/tcf/system/Windows/windbgcache.h
deleted file mode 100644
index 670cad7d..00000000
--- a/agent/tcf/system/Windows/windbgcache.h
+++ /dev/null
@@ -1,251 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008 Wind River Systems, Inc. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- * You may elect to redistribute this code under either of these licenses.
- *
- * Contributors:
- * Wind River Systems - initial API and implementation
- *******************************************************************************/
-
-/*
- * This module provides access to Windows Portable Executable debug information.
- */
-
-#ifndef D_windbgcache
-#define D_windbgcache
-
-#include <tcf/config.h>
-
-#if defined(WIN32)
-
-#if defined(__GNUC__)
-# include <imagehlp.h>
-#else
-# define _NO_CVCONST_H
-# include <dbghelp.h>
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined(__GNUC__)
-typedef enum _IMAGEHLP_SYMBOL_TYPE_INFO {
- TI_GET_SYMTAG,
- TI_GET_SYMNAME,
- TI_GET_LENGTH,
- TI_GET_TYPE,
- TI_GET_TYPEID,
- TI_GET_BASETYPE,
- TI_GET_ARRAYINDEXTYPEID,
- TI_FINDCHILDREN,
- TI_GET_DATAKIND,
- TI_GET_ADDRESSOFFSET,
- TI_GET_OFFSET,
- TI_GET_VALUE,
- TI_GET_COUNT,
- TI_GET_CHILDRENCOUNT,
- TI_GET_BITPOSITION,
- TI_GET_VIRTUALBASECLASS,
- TI_GET_VIRTUALTABLESHAPEID,
- TI_GET_VIRTUALBASEPOINTEROFFSET,
- TI_GET_CLASSPARENTID,
- TI_GET_NESTED,
- TI_GET_SYMINDEX,
- TI_GET_LEXICALPARENT,
- TI_GET_ADDRESS,
- TI_GET_THISADJUST,
- TI_GET_UDTKIND,
- TI_IS_EQUIV_TO,
- TI_GET_CALLING_CONVENTION,
- TI_IS_CLOSE_EQUIV_TO,
- TI_GTIEX_REQS_VALID,
- TI_GET_VIRTUALBASEOFFSET,
- TI_GET_VIRTUALBASEDISPINDEX,
- TI_GET_IS_REFERENCE,
- IMAGEHLP_SYMBOL_TYPE_INFO_MAX,
-} IMAGEHLP_SYMBOL_TYPE_INFO;
-
-typedef struct _TI_FINDCHILDREN_PARAMS {
- ULONG Count;
- ULONG Start;
- ULONG ChildId[1];
-} TI_FINDCHILDREN_PARAMS;
-
-enum SymTagEnum {
- SymTagNull,
- SymTagExe,
- SymTagCompiland,
- SymTagCompilandDetails,
- SymTagCompilandEnv,
- SymTagFunction,
- SymTagBlock,
- SymTagData,
- SymTagAnnotation,
- SymTagLabel,
- SymTagPublicSymbol,
- SymTagUDT,
- SymTagEnum,
- SymTagFunctionType,
- SymTagPointerType,
- SymTagArrayType,
- SymTagBaseType,
- SymTagTypedef,
- SymTagBaseClass,
- SymTagFriend,
- SymTagFunctionArgType,
- SymTagFuncDebugStart,
- SymTagFuncDebugEnd,
- SymTagUsingNamespace,
- SymTagVTableShape,
- SymTagVTable,
- SymTagCustom,
- SymTagThunk,
- SymTagCustomType,
- SymTagManagedType,
- SymTagDimension,
- SymTagMax
-};
-
-#define SYMFLAG_VALUEPRESENT 0x00000001
-#define SYMFLAG_REGISTER 0x00000008
-#define SYMFLAG_REGREL 0x00000010
-#define SYMFLAG_FRAMEREL 0x00000020
-#define SYMFLAG_PARAMETER 0x00000040
-#define SYMFLAG_LOCAL 0x00000080
-#define SYMFLAG_CONSTANT 0x00000100
-#define SYMFLAG_EXPORT 0x00000200
-#define SYMFLAG_FORWARDER 0x00000400
-#define SYMFLAG_FUNCTION 0x00000800
-#define SYMFLAG_VIRTUAL 0x00001000
-#define SYMFLAG_THUNK 0x00002000
-#define SYMFLAG_TLSREL 0x00004000
-#define SYMFLAG_SLOT 0x00008000
-#define SYMFLAG_ILREL 0x00010000
-#define SYMFLAG_METADATA 0x00020000
-#define SYMFLAG_CLR_TOKEN 0x00040000
-
-typedef struct _SYMBOL_INFO {
- ULONG SizeOfStruct;
- ULONG TypeIndex;
- ULONG64 Reserved[2];
- ULONG Index;
- ULONG Size;
- ULONG64 ModBase;
- ULONG Flags;
- ULONG64 Value;
- ULONG64 Address;
- ULONG Register;
- ULONG Scope;
- ULONG Tag;
- ULONG NameLen;
- ULONG MaxNameLen;
- CHAR Name[1];
-} SYMBOL_INFO, *PSYMBOL_INFO;
-
-typedef struct _IMAGEHLP_STACK_FRAME {
- ULONG64 InstructionOffset;
- ULONG64 ReturnOffset;
- ULONG64 FrameOffset;
- ULONG64 StackOffset;
- ULONG64 BackingStoreOffset;
- ULONG64 FuncTableEntry;
- ULONG64 Params[4];
- ULONG64 Reserved[5];
- BOOL Virtual;
- ULONG Reserved2;
-} IMAGEHLP_STACK_FRAME, *PIMAGEHLP_STACK_FRAME;
-
-typedef VOID IMAGEHLP_CONTEXT, *PIMAGEHLP_CONTEXT;
-
-typedef BOOL (CALLBACK *PSYM_ENUMERATESYMBOLS_CALLBACK)(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext);
-typedef BOOL (CALLBACK *PENUMLOADED_MODULES_CALLBACKW64)(PCWSTR ModuleName, DWORD64 ModuleBase, ULONG ModuleSize, PVOID UserContext);
-
-#endif /* defined(__GNUC__) */
-
-enum BasicType {
- btNoType = 0,
- btVoid = 1,
- btChar = 2,
- btWChar = 3,
- btInt = 6,
- btUInt = 7,
- btFloat = 8,
- btBCD = 9,
- btBool = 10,
- btLong = 13,
- btULong = 14,
- btCurrency = 25,
- btDate = 26,
- btVariant = 27,
- btComplex = 28,
- btBit = 29,
- btBSTR = 30,
- btHresult = 31
-};
-
-enum DataKind {
- DataIsUnknown,
- DataIsLocal,
- DataIsStaticLocal,
- DataIsParam,
- DataIsObjectPtr,
- DataIsFileStatic,
- DataIsGlobal,
- DataIsMember,
- DataIsStaticMember,
- DataIsConstant
-};
-
-#define SymInitialize LocSymInitialize
-#define SymGetOptions LocSymGetOptions
-#define SymSetOptions LocSymSetOptions
-#define SymGetLineFromName LocSymGetLineFromName
-#define SymGetLineFromAddr LocSymGetLineFromAddr
-#define SymGetLineNext LocSymGetLineNext
-#define SymGetTypeInfo LocSymGetTypeInfo
-#define SymFromIndex LocSymFromIndex
-#define SymFromAddr LocSymFromAddr
-#define SymSetContext LocSymSetContext
-#define SymFromName LocSymFromName
-#define SymEnumSymbols LocSymEnumSymbols
-#define SymGetTypeFromName LocSymGetTypeFromName
-#define SymGetModuleBase64 LocSymGetModuleBase64
-#define SymLoadModule64 LocSymLoadModule64
-#define SymUnloadModule64 LocSymUnloadModule64
-#define SymCleanup LocSymCleanup
-
-#define EnumerateLoadedModulesW64 LocEnumerateLoadedModulesW64
-
-extern BOOL SymInitialize(HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess);
-extern DWORD SymGetOptions(void);
-extern BOOL SymSetOptions(DWORD Options);
-extern BOOL SymGetLineFromName(HANDLE hProcess, PCSTR ModuleName, PCSTR FileName, DWORD dwLineNumber, PLONG plDisplacement, PIMAGEHLP_LINE Line);
-extern BOOL SymGetLineFromAddr(HANDLE hProcess, DWORD dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE Line);
-extern BOOL SymGetLineNext(HANDLE hProcess, PIMAGEHLP_LINE Line);
-extern BOOL SymGetTypeInfo(HANDLE hProcess, DWORD64 ModBase, ULONG TypeId, IMAGEHLP_SYMBOL_TYPE_INFO GetType, PVOID pInfo);
-extern BOOL SymFromIndex(HANDLE hProcess, ULONG64 BaseOfDll, DWORD Index, PSYMBOL_INFO Symbol);
-extern BOOL SymFromAddr(HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol);
-extern BOOL SymSetContext(HANDLE hProcess, PIMAGEHLP_STACK_FRAME StackFrame, PIMAGEHLP_CONTEXT Context);
-extern BOOL SymFromName(HANDLE hProcess, PCSTR Name, PSYMBOL_INFO Symbol);
-extern BOOL SymEnumSymbols(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR Mask, PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, PVOID UserContext);
-extern BOOL SymGetTypeFromName(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR Name, PSYMBOL_INFO Symbol);
-extern DWORD64 SymGetModuleBase64(HANDLE hProcess, ULONG64 Address);
-extern BOOL SymLoadModule64(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll);
-extern BOOL SymUnloadModule64(HANDLE hProcess, DWORD64 BaseOfDll);
-extern BOOL SymCleanup(HANDLE hProcess);
-
-extern BOOL LocEnumerateLoadedModulesW64(HANDLE hProcess, PENUMLOADED_MODULES_CALLBACKW64 Callback, PVOID UserContext);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* defined(WIN32) */
-#endif /* D_windbgcache */

Back to the top