summaryrefslogtreecommitdiff
path: root/phpdbg_win.c
blob: 29f80449fa3224d598aa6c394032f1ed347f0c7b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
   +----------------------------------------------------------------------+
   | PHP Version 5                                                        |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997-2014 The PHP Group                                |
   +----------------------------------------------------------------------+
   | This source file is subject to version 3.01 of the PHP license,	  |
   | that is bundled with this package in the file LICENSE, and is        |
   | available through the world-wide-web at the following url:           |
   | http://www.php.net/license/3_01.txt                                  |
   | If you did not receive a copy of the PHP license and are unable to   |
   | obtain it through the world-wide-web, please send a note to          |
   | license@php.net so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
   | Authors: Felipe Pena <felipe@php.net>                                |
   | Authors: Joe Watkins <joe.watkins@live.co.uk>                        |
   | Authors: Bob Weinand <bwoebi@php.net>                                |
   +----------------------------------------------------------------------+
*/

#include "zend.h"
#include "phpdbg.h"

phpdbg_btree phpdbg_memory_tree;

int mprotect(void *addr, size_t size, int protection) {
	int var;
	//printf("Set protection of %p to %s\n", addr, protection == (PROT_READ | PROT_WRITE) ? "rw": "r-");
	return (int)VirtualProtect(addr, size, protection == (PROT_READ | PROT_WRITE) ? PAGE_READWRITE : PAGE_READONLY, &var);
}

size_t virtual_size(void *ptr) {
	return (size_t)phpdbg_btree_find(&phpdbg_memory_tree, (zend_ulong)ptr)->ptr;
}

void *virtual_malloc(size_t size) {
	size_t real_size = phpdbg_get_total_page_size(NULL, size);
	void *addr = VirtualAlloc(NULL, real_size, MEM_COMMIT, PAGE_READWRITE);
	phpdbg_btree_insert(&phpdbg_memory_tree, (zend_ulong)addr, (void *)real_size);
	return addr;
}

void virtual_free(void *ptr) {
	phpdbg_watch_efree(ptr);
	VirtualFree(ptr, virtual_size(ptr), MEM_RELEASE);
	phpdbg_btree_delete(&phpdbg_memory_tree, (zend_ulong)ptr);
}

void *virtual_realloc(void *ptr, size_t size) {
	void *ret;
	size_t original_size = virtual_size(ptr);

	if (original_size >= size) {
		return ptr;
	}
	
	ret = virtual_malloc(size);
	memcpy(ret, ptr, original_size);
	virtual_free(ptr);
	return ret;
}

void phpdbg_win_set_mm_heap(zend_mm_heap *heap) {
	phpdbg_btree_init(&phpdbg_memory_tree, sizeof(void *) * 8);
	heap->_free = virtual_free;
	heap->_realloc = virtual_realloc;
	heap->_malloc = virtual_malloc;
}

int phpdbg_exception_handler_win32(EXCEPTION_POINTERS *xp) {
	EXCEPTION_RECORD *xr = xp->ExceptionRecord;
	CONTEXT *xc = xp->ContextRecord;
	if(xr->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
		TSRMLS_FETCH();
		//printf("Watchpoint hit at: %p\n", xr->ExceptionInformation[1]);
		if (phpdbg_watchpoint_segfault_handler((void *)xr->ExceptionInformation[1] TSRMLS_CC) == SUCCESS) {
			return EXCEPTION_CONTINUE_EXECUTION;
		}
	}
	return EXCEPTION_CONTINUE_SEARCH;
}