158 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			158 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (C)2015-2016 Haxe Foundation
 | 
						|
 *
 | 
						|
 * Permission is hereby granted, free of charge, to any person obtaining a
 | 
						|
 * copy of this software and associated documentation files (the "Software"),
 | 
						|
 * to deal in the Software without restriction, including without limitation
 | 
						|
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | 
						|
 * and/or sell copies of the Software, and to permit persons to whom the
 | 
						|
 * Software is furnished to do so, subject to the following conditions:
 | 
						|
 *
 | 
						|
 * The above copyright notice and this permission notice shall be included in
 | 
						|
 * all copies or substantial portions of the Software.
 | 
						|
 *
 | 
						|
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
						|
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
						|
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
						|
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 | 
						|
 * DEALINGS IN THE SOFTWARE.
 | 
						|
 */
 | 
						|
#include <hl.h>
 | 
						|
#include <hlmodule.h>
 | 
						|
 | 
						|
struct _hl_socket;
 | 
						|
typedef struct _hl_socket hl_socket;
 | 
						|
HL_API void hl_socket_init();
 | 
						|
HL_API hl_socket *hl_socket_new( bool udp );
 | 
						|
HL_API bool hl_socket_bind( hl_socket *s, int host, int port );
 | 
						|
HL_API bool hl_socket_listen( hl_socket *s, int n );
 | 
						|
HL_API void hl_socket_close( hl_socket *s );
 | 
						|
HL_API hl_socket *hl_socket_accept( hl_socket *s );
 | 
						|
HL_API int hl_socket_send( hl_socket *s, vbyte *buf, int pos, int len );
 | 
						|
HL_API int hl_socket_recv( hl_socket *s, vbyte *buf, int pos, int len );
 | 
						|
HL_API void hl_sys_sleep( double t );
 | 
						|
HL_API int hl_sys_getpid();
 | 
						|
 | 
						|
HL_API int hl_closure_stack_capture;
 | 
						|
 | 
						|
static hl_socket *debug_socket = NULL;
 | 
						|
static hl_socket *client_socket = NULL;
 | 
						|
static bool debugger_connected = false;
 | 
						|
static bool debugger_stopped = false;
 | 
						|
 | 
						|
#define send hl_send_data
 | 
						|
static void send( void *ptr, int size ) {
 | 
						|
	hl_socket_send(client_socket, ptr, 0, size);
 | 
						|
}
 | 
						|
 | 
						|
static void hl_debug_loop( hl_module *m ) {
 | 
						|
	void *inf_addr = hl_gc_threads_info();
 | 
						|
	int flags = 0;
 | 
						|
	int hl_ver = HL_VERSION;
 | 
						|
	bool loop = false;
 | 
						|
	int pid = hl_sys_getpid();
 | 
						|
#	ifdef HL_64
 | 
						|
	flags |= 1;
 | 
						|
#	endif
 | 
						|
	if( sizeof(bool) == 4 ) flags |= 2;
 | 
						|
#	ifdef HL_THREADS
 | 
						|
	flags |= 4;
 | 
						|
	loop = true;
 | 
						|
#	endif
 | 
						|
#	ifdef HL_WIN_CALL
 | 
						|
	flags |= 8;
 | 
						|
#	endif
 | 
						|
	hl_get_thread()->flags |= HL_THREAD_INVISIBLE;
 | 
						|
	do {
 | 
						|
		int i;
 | 
						|
		vbyte cmd;
 | 
						|
		hl_socket *s = hl_socket_accept(debug_socket);
 | 
						|
		if( s == NULL ) break;
 | 
						|
		client_socket = s;
 | 
						|
		send("HLD1",4);
 | 
						|
		send(&flags,4);
 | 
						|
		send(&hl_ver, 4);
 | 
						|
		send(&pid,4);
 | 
						|
		send(&inf_addr, sizeof(void*));
 | 
						|
		send(&m->globals_data,sizeof(void*));
 | 
						|
		send(&m->jit_code,sizeof(void*));
 | 
						|
		send(&m->codesize,4);
 | 
						|
		send(&m->code->types,sizeof(void*));
 | 
						|
 | 
						|
		for(i=1;i<=HBYTES;i++) {
 | 
						|
			hl_type t = {(hl_type_kind)i};
 | 
						|
			int k = 1 + hl_pad_struct(1,&t);
 | 
						|
			send(&k,4);
 | 
						|
		}
 | 
						|
 | 
						|
		send(&m->code->nfunctions,4);
 | 
						|
		for(i=0;i<m->code->nfunctions;i++) {
 | 
						|
			hl_function *f = m->code->functions + i;
 | 
						|
			hl_debug_infos *d = m->jit_debug + i;
 | 
						|
			struct {
 | 
						|
				int nops;
 | 
						|
				int start;
 | 
						|
				unsigned char large;
 | 
						|
			} fdata;
 | 
						|
			fdata.nops = f->nops;
 | 
						|
			fdata.start = d->start;
 | 
						|
			fdata.large = (unsigned char)d->large;
 | 
						|
			send(&fdata,9);
 | 
						|
			send(d->offsets,(d->large ? sizeof(int) : sizeof(unsigned short)) * (f->nops + 1));
 | 
						|
		}
 | 
						|
 | 
						|
		hl_closure_stack_capture = 8;
 | 
						|
 | 
						|
		// wait answer
 | 
						|
		// for some reason, this is not working on windows (recv returns 0 ?)
 | 
						|
		hl_socket_recv(s,&cmd,0,1);
 | 
						|
		hl_socket_close(s);
 | 
						|
		debugger_connected = true;
 | 
						|
		client_socket = NULL;
 | 
						|
	} while( loop );
 | 
						|
	debugger_stopped = true;
 | 
						|
}
 | 
						|
 | 
						|
h_bool hl_module_debug( hl_module *m, int port, h_bool wait ) {
 | 
						|
	hl_socket *s;
 | 
						|
	hl_socket_init();
 | 
						|
	s = hl_socket_new(false);
 | 
						|
	if( s == NULL ) return false;
 | 
						|
	if( !hl_socket_bind(s,0x0100007F/*127.0.0.1*/,port) || !hl_socket_listen(s, 10) ) {
 | 
						|
		hl_socket_close(s);
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	debug_socket = s;
 | 
						|
#	ifdef HL_THREADS
 | 
						|
	hl_add_root(&debug_socket);
 | 
						|
	hl_add_root(&client_socket);
 | 
						|
	if( !hl_thread_start(hl_debug_loop, m, true) ) {
 | 
						|
		hl_socket_close(s);
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	if( wait ) {
 | 
						|
		while( !debugger_connected )
 | 
						|
			hl_sys_sleep(0.01);
 | 
						|
	}
 | 
						|
#	else
 | 
						|
	// imply --debug-wait
 | 
						|
	hl_debug_loop(m);
 | 
						|
	hl_socket_close(debug_socket);
 | 
						|
	debug_socket = NULL;
 | 
						|
#	endif
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
void hl_module_debug_stop() {
 | 
						|
	if( !debug_socket ) return;
 | 
						|
#	ifdef HL_THREADS
 | 
						|
	hl_socket_close(debug_socket);
 | 
						|
	while( !debugger_stopped )
 | 
						|
		hl_sys_sleep(0.01);
 | 
						|
	hl_remove_root(&debug_socket);
 | 
						|
	hl_remove_root(&client_socket);
 | 
						|
#	endif
 | 
						|
}
 |