diff options
-rw-r--r-- | agent.dsp | 10 | ||||
-rw-r--r-- | breakpoints.c | 340 | ||||
-rw-r--r-- | context.c | 24 | ||||
-rw-r--r-- | context.h | 1 | ||||
-rw-r--r-- | dbghelp.dll | bin | 0 -> 1061944 bytes | |||
-rw-r--r-- | dwarfio.c | 38 | ||||
-rw-r--r-- | dwarfio.h | 5 | ||||
-rw-r--r-- | errors.c | 2 | ||||
-rw-r--r-- | linenumbers.h | 5 | ||||
-rw-r--r-- | linenumbers_elf.c | 110 | ||||
-rw-r--r-- | linenumbers_win32.c | 78 | ||||
-rw-r--r-- | peer.c | 8 | ||||
-rw-r--r-- | protocol.c | 40 | ||||
-rw-r--r-- | symbols_win32.c | 46 |
14 files changed, 512 insertions, 195 deletions
@@ -50,6 +50,10 @@ BSC32=bscmake.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib WS2_32.lib Iphlpapi.lib dbghelp.lib /nologo /subsystem:console /machine:I386
+# Begin Special Build Tool
+SOURCE=$(InputPath)
+PostBuild_Cmds=copy dbghelp.dll Release
+# End Special Build Tool
!ELSEIF "$(CFG)" == "agent - Win32 Debug"
@@ -73,7 +77,11 @@ BSC32=bscmake.exe # ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib WS2_32.lib Iphlpapi.lib dbghelp.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib WS2_32.lib Iphlpapi.lib dbghelp.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# Begin Special Build Tool
+SOURCE=$(InputPath)
+PostBuild_Cmds=copy dbghelp.dll Debug
+# End Special Build Tool
!ENDIF
diff --git a/breakpoints.c b/breakpoints.c index 69d79a9e..f4f90cf1 100644 --- a/breakpoints.c +++ b/breakpoints.c @@ -40,6 +40,7 @@ #include "symbols.h" #include "json.h" #include "link.h" +#include "linenumbers.h" #if defined(_WRS_KERNEL) # include <private/vxdbgLibP.h> @@ -75,6 +76,13 @@ struct BreakpointInfo { char * err_msg; char * address; char * condition; +#if SERVICE_LineNumbers + char * file; + int line; + int column; +#endif + int skip_count; + int hit_count; BreakpointAttribute * unsupported; }; @@ -100,8 +108,10 @@ struct BreakInstruction { static const char * BREAKPOINTS = "Breakpoints"; +#define is_running(ctx) (!(ctx)->stopped && context_has_state(ctx)) + #define ADDR2INSTR_HASH_SIZE 1023 -#define addr2instr_hash(addr) (((addr) + ((addr) >> 8)) % ADDR2INSTR_HASH_SIZE) +#define addr2instr_hash(addr) ((unsigned)((addr) + ((addr) >> 8)) % ADDR2INSTR_HASH_SIZE) #define link_all2bi(A) ((BreakInstruction *)((char *)(A) - (int)&((BreakInstruction *)0)->link_all)) #define link_adr2bi(A) ((BreakInstruction *)((char *)(A) - (int)&((BreakInstruction *)0)->link_adr)) @@ -132,7 +142,7 @@ static int condition_expression_identifier(char * name, Value * v); static ExpressionContext bp_address_ctx = { address_expression_identifier, NULL }; static ExpressionContext bp_condition_ctx = { condition_expression_identifier, NULL }; -static int id2bp_hash(char * id) { +static unsigned id2bp_hash(char * id) { unsigned hash = 0; while (*id) hash = (hash >> 16) + hash + (unsigned char)*id++; return hash % ID2BP_HASH_SIZE; @@ -189,7 +199,7 @@ static void remove_instruction(BreakInstruction * bi) { } } #else - if (!bi->ctx->exited && bi->ctx->stopped) { + if (!bi->ctx->exited && !is_running(bi->ctx)) { if (context_write_mem(bi->ctx, bi->address, bi->saved_code, BREAK_SIZE) < 0) { bi->error = errno; } @@ -229,12 +239,12 @@ static void delete_unused_instructions(void) { list_remove(&bi->link_all); list_remove(&bi->link_adr); if (bi->planted) { - if (bi->ctx->exited || !bi->ctx->stopped) { + if (bi->ctx->exited || is_running(bi->ctx)) { LINK * qp = context_root.next; while (qp != &context_root) { Context * ctx = ctxl2ctxp(qp); qp = qp->next; - if (ctx->mem == bi->ctx->mem && !ctx->exited && ctx->stopped) { + if (ctx->mem == bi->ctx->mem && !ctx->exited && !is_running(ctx)) { assert(bi->ctx != ctx); context_unlock(bi->ctx); context_lock(ctx); @@ -267,7 +277,7 @@ static BreakInstruction * find_instruction(Context * ctx, unsigned long address) BreakInstruction * bi = link_adr2bi(l); l = l->next; if (bi->ctx->mem == ctx->mem && bi->address == address) { - if (bi->ctx->exited || !bi->ctx->stopped) { + if (bi->ctx->exited || is_running(bi->ctx)) { assert(bi->ctx != ctx); context_unlock(bi->ctx); context_lock(ctx); @@ -368,6 +378,42 @@ static void address_expression_error(BreakpointInfo * bp, char * msg) { snprintf(bp->err_msg, size, "Invalid breakpoint address '%s': %s", bp->address, msg); } +static void plant_breakpoint_in_context(BreakpointInfo * bp, Context * ctx, unsigned long address) { + BreakInstruction * bi = NULL; + bi = find_instruction(ctx, address); + if (bi == NULL) { + bi = add_instruction(ctx, address); + } + else if (bp->planted) { + int i = 0; + while (i < bi->ref_cnt && bi->refs[i] != bp) i++; + if (i < bi->ref_cnt) return; + } + if (bi->ref_cnt >= bi->ref_size) { + bi->ref_size = bi->ref_size == 0 ? 8 : bi->ref_size * 2; + bi->refs = (BreakpointInfo **)loc_realloc(bi->refs, sizeof(BreakpointInfo *) * bi->ref_size); + } + bi->refs[bi->ref_cnt++] = bp; + if (bi->ctx != ctx) bi->ctx_cnt++; + if (bi->error) { + if (!bp->error) bp->error = bi->error; + } + else { + bp->planted = 1; + bp->hit_count = 0; + } +} + +typedef struct PlantBreakpointArgs { + BreakpointInfo * bp; + Context * ctx; +} PlantBreakpointArgs; + +static void plant_breakpoint_address_iterator(void * x, unsigned long address) { + PlantBreakpointArgs * args = (PlantBreakpointArgs *)x; + plant_breakpoint_in_context(args->bp, args->ctx, address); +} + static void plant_breakpoint(BreakpointInfo * bp) { LINK * qp; char * p = NULL; @@ -382,45 +428,40 @@ static void plant_breakpoint(BreakpointInfo * bp) { bp->err_msg = NULL; } - if (bp->address == NULL) { - bp->error = ERR_INV_EXPRESSION; - trace(LOG_ALWAYS, "No breakpoint address"); - return; - } - expression_context = NULL; - if (evaluate_expression(&bp_address_ctx, bp->address, &v) < 0) { - if (errno != ERR_INV_CONTEXT) { - address_expression_error(bp, NULL); + if (bp->address != NULL) { + expression_context = NULL; + if (evaluate_expression(&bp_address_ctx, bp->address, &v) < 0) { + if (errno != ERR_INV_CONTEXT) { + address_expression_error(bp, NULL); + trace(LOG_ALWAYS, "Error: %s", bp->err_msg); + return; + } + context_sensitive = 1; + } + if (!context_sensitive && v.type != VALUE_INT && v.type != VALUE_UNS) { + errno = ERR_INV_EXPRESSION; + address_expression_error(bp, "Must be integer number"); trace(LOG_ALWAYS, "Error: %s", bp->err_msg); return; } + } +#if SERVICE_LineNumbers + else if (bp->file != NULL) { context_sensitive = 1; } - if (!context_sensitive && v.type != VALUE_INT && v.type != VALUE_UNS) { - errno = ERR_INV_EXPRESSION; - address_expression_error(bp, "Must be integer number"); - trace(LOG_ALWAYS, "Error: %s", bp->err_msg); +#endif + else { + bp->error = ERR_INV_EXPRESSION; + trace(LOG_ALWAYS, "No breakpoint address"); return; } for (qp = context_root.next; qp != &context_root; qp = qp->next) { - BreakInstruction * bi = NULL; Context * ctx = ctxl2ctxp(qp); - if (ctx->exited || ctx->exiting || !ctx->stopped) continue; - if (context_sensitive) { - expression_context = ctx; - if (evaluate_expression(&bp_address_ctx, bp->address, &v) < 0) { - address_expression_error(bp, NULL); - trace(LOG_ALWAYS, "Error: %s", bp->err_msg); - continue; - } - if (v.type != VALUE_INT && v.type != VALUE_UNS) { - errno = ERR_INV_EXPRESSION; - address_expression_error(bp, "Must be integer number"); - continue; - } - } + if (ctx->exited || ctx->exiting) continue; + if (is_running(ctx)) continue; + if (bp->condition != NULL) { /* Optimize away the breakpoint if condition is always false for given context */ Value c; @@ -437,31 +478,71 @@ static void plant_breakpoint(BreakpointInfo * bp) { } } } - bi = find_instruction(ctx, v.value); - if (bi == NULL) { - bi = add_instruction(ctx, v.value); - } - else if (bp->planted) { - int i = 0; - while (i < bi->ref_cnt && bi->refs[i] != bp) i++; - if (i < bi->ref_cnt) continue; - } - if (bi->ref_cnt >= bi->ref_size) { - bi->ref_size = bi->ref_size == 0 ? 8 : bi->ref_size * 2; - bi->refs = (BreakpointInfo **)loc_realloc(bi->refs, sizeof(BreakpointInfo *) * bi->ref_size); - } - bi->refs[bi->ref_cnt++] = bp; - if (bi->ctx != ctx) bi->ctx_cnt++; - if (bi->error) { - if (!bp->error) bp->error = bi->error; + if (context_sensitive) { + if (bp->address != NULL) { + expression_context = ctx; + if (evaluate_expression(&bp_address_ctx, bp->address, &v) < 0) { + address_expression_error(bp, NULL); + trace(LOG_ALWAYS, "BP Error: %s", bp->err_msg); + continue; + } + if (v.type != VALUE_INT && v.type != VALUE_UNS) { + errno = ERR_INV_EXPRESSION; + address_expression_error(bp, "Must be integer number"); + continue; + } + plant_breakpoint_in_context(bp, ctx, v.value); + } +#if SERVICE_LineNumbers + else if (bp->file != NULL) { + PlantBreakpointArgs args; + if (ctx->parent != NULL && ctx->mem == ctx->parent->mem) continue; + args.ctx = ctx; + args.bp = bp; + if (line_to_address(ctx, bp->file, bp->line, bp->column, + plant_breakpoint_address_iterator, &args) < 0) { + assert(errno != 0); + if (bp->error == 0) { + bp->error = errno; + assert(bp->err_msg == NULL); + bp->err_msg = loc_strdup(errno_to_str(bp->error)); + trace(LOG_ALWAYS, "BP Error: %s", bp->err_msg); + } + } + } +#endif + else { + assert(0); + } } else { - bp->planted = 1; + if (ctx->parent != NULL && ctx->mem == ctx->parent->mem) continue; + plant_breakpoint_in_context(bp, ctx, v.value); } } if (bp->planted) bp->error = 0; } +static void free_bp(BreakpointInfo * bp) { + list_remove(&bp->link_all); + list_remove(&bp->link_id); + loc_free(bp->err_msg); + loc_free(bp->address); +#if SERVICE_LineNumbers + loc_free(bp->file); +#endif + loc_free(bp->condition); + while (bp->unsupported != NULL) { + BreakpointAttribute * u = bp->unsupported; + bp->unsupported = u->next; + loc_free(u->name); + loc_free(u->value); + loc_free(u); + } + assert(list_is_empty(&bp->refs)); + loc_free(bp); +} + static void event_replant_breakpoints(void *arg) { LINK * l = breakpoints.next; replanting = 0; @@ -470,12 +551,7 @@ static void event_replant_breakpoints(void *arg) { BreakpointInfo * bp = link_all2bp(l); l = l->next; if (bp->deleted) { - list_remove(&bp->link_all); - list_remove(&bp->link_id); - loc_free(bp->err_msg); - loc_free(bp->address); - loc_free(bp->condition); - loc_free(bp); + free_bp(bp); continue; } bp->planted = 0; @@ -528,10 +604,38 @@ static int copy_breakpoint_info(BreakpointInfo * dst, BreakpointInfo * src) { } src->condition = NULL; +#if SERVICE_LineNumbers + if (!str_equ(dst->file, src->file)) { + loc_free(dst->file); + dst->file = src->file; + res = 1; + } + else { + loc_free(src->file); + } + src->file = NULL; + + if (dst->line != src->line) { + dst->line = src->line; + res = 1; + } + + if (dst->column != src->column) { + dst->column = src->column; + res = 1; + } +#endif + + if (dst->skip_count != src->skip_count) { + dst->skip_count = src->skip_count; + res = 1; + } + if (dst->enabled != src->enabled) { dst->enabled = src->enabled; res = 1; } + if (dst->unsupported != src->unsupported) { while (dst->unsupported != NULL) { BreakpointAttribute * u = dst->unsupported; @@ -593,6 +697,20 @@ static void read_breakpoint_properties(InputStream * inp, BreakpointInfo * bp) { else if (strcmp(name, "Condition") == 0) { bp->condition = json_read_alloc_string(inp); } +#if SERVICE_LineNumbers + else if (strcmp(name, "File") == 0) { + bp->file = json_read_alloc_string(inp); + } + else if (strcmp(name, "Line") == 0) { + bp->line = json_read_long(inp); + } + else if (strcmp(name, "Column") == 0) { + bp->column = json_read_long(inp); + } +#endif + else if (strcmp(name, "SkipCount") == 0) { + bp->skip_count = json_read_long(inp); + } else if (strcmp(name, "Enabled") == 0) { bp->enabled = json_read_boolean(inp); } @@ -634,6 +752,36 @@ static void write_breakpoint_properties(OutputStream * out, BreakpointInfo * bp) json_write_string(out, bp->condition); } +#if SERVICE_LineNumbers + if (bp->file != NULL) { + out->write(out, ','); + json_write_string(out, "File"); + out->write(out, ':'); + json_write_string(out, bp->file); + } + + if (bp->line > 0) { + out->write(out, ','); + json_write_string(out, "Line"); + out->write(out, ':'); + json_write_long(out, bp->line); + } + + if (bp->column > 0) { + out->write(out, ','); + json_write_string(out, "Column"); + out->write(out, ':'); + json_write_long(out, bp->column); + } +#endif + + if (bp->skip_count > 0) { + out->write(out, ','); + json_write_string(out, "SkipCount"); + out->write(out, ':'); + json_write_long(out, bp->skip_count); + } + if (bp->enabled) { out->write(out, ','); json_write_string(out, "Enabled"); @@ -645,7 +793,7 @@ static void write_breakpoint_properties(OutputStream * out, BreakpointInfo * bp) out->write(out, ','); json_write_string(out, u->name); out->write(out, ':'); - json_write_string(out, u->value); + write_string(out, u->value); u = u->next; } @@ -709,7 +857,7 @@ static void add_breakpoint(InputStream * inp, OutputStream * out, BreakpointInfo } r = find_breakpoint_ref(p, inp); if (r == NULL) { - int inp_hash = (int)inp / 16 % INP2BR_HASH_SIZE; + unsigned inp_hash = (unsigned)inp / 16 % INP2BR_HASH_SIZE; r = (BreakpointRef *)loc_alloc_zero(sizeof(BreakpointRef)); list_add_last(&r->link_inp, inp2br + inp_hash); list_add_last(&r->link_bp, &p->refs); @@ -735,11 +883,7 @@ static void remove_breakpoint(OutputStream * out, BreakpointInfo * bp) { replant_breakpoints(); } else { - list_remove(&bp->link_all); - list_remove(&bp->link_id); - loc_free(bp->address); - loc_free(bp->condition); - loc_free(bp); + free_bp(bp); } } @@ -752,7 +896,7 @@ static void remove_ref(OutputStream * out, BreakpointRef * br) { } static void delete_breakpoint_refs(InputStream * inp, OutputStream * out) { - int hash = (int)inp / 16 % INP2BR_HASH_SIZE; + unsigned hash = (unsigned)inp / 16 % INP2BR_HASH_SIZE; LINK * l = inp2br[hash].next; while (l != &inp2br[hash]) { BreakpointRef * br = link_inp2br(l); @@ -788,7 +932,7 @@ static void command_ini_bps(char * token, Channel * c) { } static void command_get_bp_ids(char * token, Channel * c) { - int hash = (int)&c->inp / 16 % INP2BR_HASH_SIZE; + unsigned hash = (unsigned)&c->inp / 16 % INP2BR_HASH_SIZE; LINK * l = inp2br[hash].next; int cnt = 0; @@ -846,10 +990,11 @@ static void command_get_status(char * token, Channel * c) { static void command_bp_add(char * token, Channel * c) { BreakpointInfo bp; read_breakpoint_properties(&c->inp, &bp); - add_breakpoint(&c->inp, &c->bcg->out, &bp); if (c->inp.read(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (c->inp.read(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); + add_breakpoint(&c->inp, &c->bcg->out, &bp); + write_stringz(&c->out, "R"); write_stringz(&c->out, token); write_errno(&c->out, 0); @@ -858,16 +1003,12 @@ static void command_bp_add(char * token, Channel * c) { static void command_bp_change(char * token, Channel * c) { BreakpointInfo bp; - BreakpointInfo * p; read_breakpoint_properties(&c->inp, &bp); - p = find_breakpoint(bp.id); - if (p != NULL && copy_breakpoint_info(p, &bp)) { - if (p->planted || p->enabled && p->unsupported == NULL) replant_breakpoints(); - send_event_context_changed(&c->bcg->out, p); - } if (c->inp.read(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (c->inp.read(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); + add_breakpoint(&c->inp, &c->bcg->out, &bp); + write_stringz(&c->out, "R"); write_stringz(&c->out, token); write_errno(&c->out, 0); @@ -986,6 +1127,24 @@ static void command_get_capabilities(char * token, Channel * c) { json_write_string(&c->out, "Address"); c->out.write(&c->out, ':'); json_write_boolean(&c->out, 1); +#if SERVICE_LineNumbers + c->out.write(&c->out, ','); + json_write_string(&c->out, "File"); + c->out.write(&c->out, ':'); + json_write_boolean(&c->out, 1); + c->out.write(&c->out, ','); + json_write_string(&c->out, "Line"); + c->out.write(&c->out, ':'); + json_write_boolean(&c->out, 1); + c->out.write(&c->out, ','); + json_write_string(&c->out, "Column"); + c->out.write(&c->out, ':'); + json_write_boolean(&c->out, 1); +#endif + c->out.write(&c->out, ','); + json_write_string(&c->out, "SkipCount"); + c->out.write(&c->out, ':'); + json_write_boolean(&c->out, 1); c->out.write(&c->out, ','); json_write_string(&c->out, "Condition"); c->out.write(&c->out, ':'); @@ -1011,27 +1170,34 @@ int evaluate_breakpoint_condition(Context * ctx) { if (bi == NULL) return 0; expression_context = ctx; for (i = 0; i < bi->ref_cnt; i++) { - Value v; BreakpointInfo * bp = bi->refs[i]; assert(bp->planted); assert(bp->error == 0); if (bp->deleted) continue; if (bp->unsupported != NULL) continue; if (!bp->enabled) continue; - if (bp->condition == NULL) return 1; - if (evaluate_expression(&bp_condition_ctx, bp->condition, &v) < 0) { - trace(LOG_ALWAYS, "%s: %s", get_expression_error_msg(), bp->condition); - return 1; + if (bp->condition != NULL) { + Value v; + if (evaluate_expression(&bp_condition_ctx, bp->condition, &v) < 0) { + trace(LOG_ALWAYS, "%s: %s", get_expression_error_msg(), bp->condition); + return 1; + } + switch (v.type) { + case VALUE_INT: + case VALUE_UNS: + if (v.value == 0) continue; + break; + case VALUE_STR: + if (v.str == NULL) continue; + break; + } } - switch (v.type) { - case VALUE_INT: - case VALUE_UNS: - if (v.value) return 1; - break; - case VALUE_STR: - if (v.str != NULL) return 1; - break; + if (bp->skip_count > 0) { + bp->hit_count++; + if (bp->hit_count < bp->skip_count) continue; + bp->hit_count = 0; } + return 1; } return 0; } @@ -26,7 +26,7 @@ #include "breakpoints.h" #define CONTEXT_PID_ROOT_SIZE 1024 -#define CONTEXT_PID_HASH(PID) ((PID) % CONTEXT_PID_ROOT_SIZE) +#define CONTEXT_PID_HASH(PID) ((unsigned)(PID) % CONTEXT_PID_ROOT_SIZE) static LINK context_pid_root[CONTEXT_PID_ROOT_SIZE]; static ContextEventListener * event_listeners = NULL; @@ -468,12 +468,14 @@ static void debug_event_handler(void * x) { case EXCEPTION_DEBUG_EVENT: if (ctx == NULL) break; assert(ctx->pending_event.ExceptionRecord.ExceptionCode == 0); - args->continue_status = DBG_EXCEPTION_NOT_HANDLED; switch (args->event.u.Exception.ExceptionRecord.ExceptionCode) { case EXCEPTION_SINGLE_STEP: case EXCEPTION_BREAKPOINT: args->continue_status = DBG_CONTINUE; break; + default: + args->continue_status = DBG_EXCEPTION_NOT_HANDLED; + break; } memcpy(&ctx->pending_event, &args->event.u.Exception, sizeof(EXCEPTION_DEBUG_INFO)); if (!ctx->stopped) event_win32_context_stopped(ctx); @@ -522,7 +524,6 @@ static DWORD WINAPI debugger_thread_func(LPVOID x) { DebugEvent create_process; DebugEvent fantom_process; int state = 0; - int abort = 0; if (event_semaphore == NULL) { args->error = GetLastError(); @@ -543,7 +544,7 @@ static DWORD WINAPI debugger_thread_func(LPVOID x) { memset(&create_process, 0, sizeof(create_process)); memset(&fantom_process, 0, sizeof(fantom_process)); - while (!abort) { + while (1) { DebugEvent * buf = NULL; DEBUG_EVENT * debug_event = &event_buffer.event; @@ -585,6 +586,8 @@ static DWORD WINAPI debugger_thread_func(LPVOID x) { case LOAD_DLL_DEBUG_EVENT: CloseHandle(debug_event->u.LoadDll.hFile); break; + case UNLOAD_DLL_DEBUG_EVENT: + break; default: if (fantom_process.event.dwThreadId == debug_event->dwThreadId) { if (debug_event->dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT) { @@ -602,6 +605,11 @@ static DWORD WINAPI debugger_thread_func(LPVOID x) { /* ResumeThread(fantom_process.event.u.CreateProcessInfo.hThread); */ fantom_process.event.u.CreateProcessInfo.hThread = NULL; } + if (state == 0) { + if (debug_event->dwDebugEventCode == EXCEPTION_DEBUG_EVENT) { + event_buffer.continue_status = DBG_EXCEPTION_NOT_HANDLED; + } + } if (state == 1) { create_process.event_semaphore = event_semaphore; post_event(debug_event_handler, &create_process); @@ -623,12 +631,8 @@ static DWORD WINAPI debugger_thread_func(LPVOID x) { break; } - switch (debug_event->dwDebugEventCode) { - case EXIT_PROCESS_DEBUG_EVENT: - case RIP_EVENT: - abort = 1; - break; - } + if (debug_event->dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break; + if (debug_event->dwDebugEventCode == RIP_EVENT) break; } if (state < 2) ReleaseSemaphore(args->debug_thread_semaphore, 1, 0); @@ -65,6 +65,7 @@ struct Context { LPVOID base_address; EXCEPTION_DEBUG_INFO pending_event; EXCEPTION_DEBUG_INFO suspend_reason; + int sym_handler_loaded; #endif }; diff --git a/dbghelp.dll b/dbghelp.dll Binary files differnew file mode 100644 index 00000000..4abd2b09 --- /dev/null +++ b/dbghelp.dll @@ -211,7 +211,7 @@ U8_T dio_ReadU8(void) { return sBigEndian ? (x0 << 32) | x1 : x0 | (x1 << 32); } -U4_T dio_ReadLEB128(void) { +U4_T dio_ReadULEB128(void) { U4_T res = 0; int i = 0; for (;; i += 7) { @@ -222,6 +222,20 @@ U4_T dio_ReadLEB128(void) { return res; } +I4_T dio_ReadSLEB128(void) { + U4_T res = 0; + int i = 0; + for (;; i += 7) { + U1_T n = dio_ReadU1(); + res |= (n & 0x7Fu) << i; + if ((n & 0x80) == 0) { + res |= -(n & 0x40) << i; + break; + } + } + return (I4_T)res; +} + U8_T dio_ReadU8LEB128(void) { U8_T res = 0; int i = 0; @@ -233,7 +247,7 @@ U8_T dio_ReadU8LEB128(void) { return res; } -I8_T dio_ReadI8LEB128(void) { +I8_T dio_ReadS8LEB128(void) { U8_T res = 0; int i = 0; for (;; i += 7) { @@ -421,12 +435,12 @@ static void dio_ReadAttribute(U2_T Attr, U2_T Form) { case FORM_BLOCK1 : dio_ReadFormBlock(Attr, dio_ReadU1()); break; case FORM_BLOCK2 : dio_ReadFormBlock(Attr, dio_ReadU2()); break; case FORM_BLOCK4 : dio_ReadFormBlock(Attr, dio_ReadU4()); break; - case FORM_BLOCK : dio_ReadFormBlock(Attr, dio_ReadLEB128()); break; + case FORM_BLOCK : dio_ReadFormBlock(Attr, dio_ReadULEB128()); break; case FORM_DATA1 : dio_ReadFormData(Attr, 1, dio_ReadU1()); break; case FORM_DATA2 : dio_ReadFormData(Attr, 2, dio_ReadU2()); break; case FORM_DATA4 : dio_ReadFormData(Attr, 4, dio_ReadU4()); break; case FORM_DATA8 : dio_ReadFormData(Attr, 8, dio_ReadU8()); break; - case FORM_SDATA : dio_ReadFormData(Attr, 8, dio_ReadI8LEB128()); break; + case FORM_SDATA : dio_ReadFormData(Attr, 8, dio_ReadS8LEB128()); break; case FORM_UDATA : dio_ReadFormData(Attr, 8, dio_ReadU8LEB128()); break; case FORM_FLAG : dio_ReadFormFlag(); break; case FORM_STRING : dio_ReadFormString(); break; @@ -436,7 +450,7 @@ static void dio_ReadAttribute(U2_T Attr, U2_T Form) { case FORM_REF2 : dio_ReadFormRelRef(dio_ReadU2()); break; case FORM_REF4 : dio_ReadFormRelRef(dio_ReadU4()); break; case FORM_REF8 : dio_ReadFormRelRef(dio_ReadU8()); break; - case FORM_REF_UDATA : dio_ReadFormRelRef(dio_ReadLEB128()); break; + case FORM_REF_UDATA : dio_ReadFormRelRef(dio_ReadULEB128()); break; default: str_exception(ERR_DWARF, "invalid FORM"); } } @@ -449,7 +463,7 @@ static void dio_ReadEntry(DIO_EntryCallBack CallBack) { int Init = 1; dio_gEntryPos = dio_GetPos(); if (dio_gVersion >= 2) { - U4_T AbbrCode = dio_ReadLEB128(); + U4_T AbbrCode = dio_ReadULEB128(); if (AbbrCode == 0) return; if (AbbrCode >= sAbbrevTableSize || sAbbrevTable[AbbrCode] == NULL) { str_exception(ERR_DWARF, "invalid abbreviation table"); @@ -479,7 +493,7 @@ static void dio_ReadEntry(DIO_EntryCallBack CallBack) { if (AttrPos < Abbr->mAttrLen) { Attr = Abbr->mAttrs[AttrPos++]; Form = Abbr->mAttrs[AttrPos++]; - if (Form == FORM_INDIRECT) Form = (U2_T)dio_ReadLEB128(); + if (Form == FORM_INDIRECT) Form = (U2_T)dio_ReadULEB128(); } } else { @@ -537,7 +551,7 @@ void dio_ReadUnit(DIO_EntryCallBack CallBack) { } } -#define dio_AbbrevTableHash(File, Offset) (((int)(File) + (int)(Offset)) / 4 % ABBREV_TABLE_SIZE) +#define dio_AbbrevTableHash(File, Offset) (((unsigned)(File) + (unsigned)(Offset)) / 16 % ABBREV_TABLE_SIZE) static int dio_IsAbbrevSectionLoaded(ELF_File * File) { DIO_Cache * Cache = dio_GetCache(File); @@ -580,7 +594,7 @@ void dio_LoadAbbrevTable(ELF_File * File) { U4_T AttrPos = 0; U2_T Tag = 0; U1_T Children = 0; - U4_T ID = dio_ReadLEB128(); + U4_T ID = dio_ReadULEB128(); if (ID == 0) { /* End of compilation unit */ U4_T Hash = dio_AbbrevTableHash(File, TableOffset); @@ -607,11 +621,11 @@ void dio_LoadAbbrevTable(ELF_File * File) { AbbrevTable = (DIO_Abbreviation **)loc_realloc(AbbrevTable, sizeof(DIO_Abbreviation *) * AbbrevTableSize); memset(AbbrevTable + Size, 0, sizeof(DIO_Abbreviation *) * (AbbrevTableSize - Size)); } - Tag = (U2_T)dio_ReadLEB128(); + Tag = (U2_T)dio_ReadULEB128(); Children = (U2_T)dio_ReadU1() != 0; for (;;) { - U4_T Attr = dio_ReadLEB128(); - U4_T Form = dio_ReadLEB128(); + U4_T Attr = dio_ReadULEB128(); + U4_T Form = dio_ReadULEB128(); if (Attr >= 0x10000 || Form >= 0x10000) str_exception(ERR_DWARF, "invalid abbreviation table"); if (Attr == 0 && Form == 0) { DIO_Abbreviation * Abbr = AbbrevTable[ID]; @@ -44,9 +44,10 @@ extern U2_T dio_ReadU2(void); extern U4_T dio_ReadU4(void); extern U8_T dio_ReadU8(void); -extern U4_T dio_ReadLEB128(void); +extern U4_T dio_ReadULEB128(void); +extern I4_T dio_ReadSLEB128(void); extern U8_T dio_ReadU8LEB128(void); -extern I8_T dio_ReadI8LEB128(void); +extern I8_T dio_ReadS8LEB128(void); extern U8_T dio_ReadUX(int Size); extern U8_T dio_ReadAddress(void); @@ -46,7 +46,7 @@ static char * system_strerror(void) { } else { int l; - strncpy(msg, (char *)msg_buf, sizeof(msg)); + snprintf(msg, sizeof(msg), "0x%08x: %s", errno_win32, msg_buf, sizeof(msg)); LocalFree(msg_buf); l = strlen(msg); while (l > 0 && (msg[l - 1] == '\n' || msg[l - 1] == '\r')) l--; diff --git a/linenumbers.h b/linenumbers.h index 04dc32c6..0d6c0172 100644 --- a/linenumbers.h +++ b/linenumbers.h @@ -19,6 +19,11 @@ #define D_linenumbers #include "protocol.h" +#include "context.h" + +typedef void (*line_to_address_callback)(void *, unsigned long); + +extern int line_to_address(Context * ctx, char * file, int line, int column, line_to_address_callback, void * args); /* * Initialize Line Numbers service. diff --git a/linenumbers_elf.c b/linenumbers_elf.c index 8ca8dc65..64fe1ce6 100644 --- a/linenumbers_elf.c +++ b/linenumbers_elf.c @@ -316,10 +316,10 @@ static void load_line_numbers(LineNumbersCache * cache, CompUnit * unit) { memset(&file, 0, sizeof(file)); file.name = dio_ReadString(); if (file.name == NULL) break; - dir = dio_ReadLEB128(); + dir = dio_ReadULEB128(); if (dir > 0 && dir <= unit->dirs_cnt) file.dir = unit->dirs[dir - 1]; - file.mtime = dio_ReadLEB128(); - file.size = dio_ReadLEB128(); + file.mtime = dio_ReadULEB128(); + file.size = dio_ReadULEB128(); add_file(unit, &file); } @@ -341,7 +341,7 @@ static void load_line_numbers(LineNumbersCache * cache, CompUnit * unit) { state.epilogue_begin = 0; } else if (opcode == 0) { - U4_T op_size = dio_ReadLEB128(); + U4_T op_size = dio_ReadULEB128(); U8_T op_pos = dio_GetPos(); switch (dio_ReadU1()) { case DW_LNE_define_file: { @@ -349,10 +349,10 @@ static void load_line_numbers(LineNumbersCache * cache, CompUnit * unit) { FileInfo file; memset(&file, 0, sizeof(file)); file.name = dio_ReadString(); - dir = dio_ReadLEB128(); + dir = dio_ReadULEB128(); if (dir > 0 && dir <= unit->dirs_cnt) file.dir = unit->dirs[dir - 1]; - file.mtime = dio_ReadLEB128(); - file.size = dio_ReadLEB128(); + file.mtime = dio_ReadULEB128(); + file.size = dio_ReadULEB128(); add_file(unit, &file); break; } @@ -385,13 +385,13 @@ static void load_line_numbers(LineNumbersCache * cache, CompUnit * unit) { state.address += (ADDR_T)(dio_ReadU8LEB128() * min_instruction_length); break; case DW_LNS_advance_line: - state.line += dio_ReadLEB128(); + state.line += dio_ReadSLEB128(); break; case DW_LNS_set_file: - state.file = dio_ReadLEB128(); + state.file = dio_ReadULEB128(); break; case DW_LNS_set_column: - state.column = dio_ReadLEB128(); + state.column = dio_ReadULEB128(); break; case DW_LNS_negate_stmt: state.is_stmt = !state.is_stmt; @@ -412,7 +412,7 @@ static void load_line_numbers(LineNumbersCache * cache, CompUnit * unit) { state.epilogue_begin = 1; break; case DW_LNS_set_isa: - state.isa = (U1_T)dio_ReadLEB128(); + state.isa = (U1_T)dio_ReadULEB128(); break; default: str_exception(ERR_DWARF, "Invalid line info op code"); @@ -488,6 +488,86 @@ static void load_line_numbers_in_range(LineNumbersCache * cache, ADDR_T addr0, A } } +static int cmp_file(char * file, char * dir, char * name) { + int i; + if (file == NULL) return 0; + if (name == NULL) return 0; + if (strcmp(file, name) == 0) return 1; + i = strlen(name); + while (i > 0 && name[i - 1] != '/' && name[i - 1] != '\\') i--; + if (strcmp(file, name + i) == 0) return 1; + if (dir == NULL) return 0; + i = strlen(dir); + if (strncmp(dir, file, i) == 0 && (file[i] == '/' || file[i] == '\\') && + strcmp(file + i + 1, name) == 0) return 1; + return 0; +} + +int line_to_address(Context * ctx, char * file, int line, int column, line_to_address_callback callback, void * user_args) { + int err = 0; + Trap trap; + LineNumbersCache * cache = NULL; + + if (ctx == NULL) err = ERR_INV_CONTEXT; + else if (ctx->exited) err = ERR_ALREADY_EXITED; + + if (err == 0) { + if (set_trap(&trap)) { + int i; + cache = get_line_numbers_cache(ctx); + for (i = 0; i < cache->units_cnt; i++) { + CompUnit * unit = cache->units + i; + int equ = 0; + if (unit->dir != NULL && unit->name != NULL) { + equ = cmp_file(file, unit->dir, unit->name); + } + if (!equ) { + int j; + for (j = 0; j < unit->files_cnt; j++) { + FileInfo * f = unit->files + j; + if (f->dir != NULL && f->name != NULL) { + equ = cmp_file(file, f->dir, f->name); + if (equ) break; + } + } + } + if (equ) { + int j; + load_line_numbers(cache, unit); + for (j = 0; j < unit->states_cnt - 1; j++) { + LineNumbersState * state = unit->states + j; + LineNumbersState * next = unit->states + j + 1; + char * state_dir = unit->dir; + char * state_name = unit->name; + if (state->end_sequence) continue; + if (line < state->line) continue; + if (line >= next->line) continue; + if (state->file >= 1 && state->file <= unit->files_cnt) { + FileInfo * f = unit->files + (state->file - 1); + state_dir = f->dir; + state_name = f->name; + } + if (!cmp_file(file, state_dir, state_name)) continue; + callback(user_args, state->address); + } + } + } + clear_trap(&trap); + } + else { + err = trap.error; + } + } + + if (cache != NULL) elf_close(cache->file); + + if (err != 0) { + errno = err; + return -1; + } + return 0; +} + static void command_map_to_source(char * token, Channel * c) { int err = 0; char * err_msg = NULL; @@ -548,22 +628,22 @@ static void command_map_to_source(char * token, Channel * c) { c->out.write(&c->out, '{'); json_write_string(&c->out, "SLine"); c->out.write(&c->out, ':'); - json_write_ulong(&c->out, state->line - 1); + json_write_ulong(&c->out, state->line); if (state->column > 0) { c->out.write(&c->out, ','); json_write_string(&c->out, "SCol"); c->out.write(&c->out, ':'); - json_write_ulong(&c->out, state->column - 1); + json_write_ulong(&c->out, state->column); } c->out.write(&c->out, ','); json_write_string(&c->out, "ELine"); c->out.write(&c->out, ':'); - json_write_ulong(&c->out, next->line - 1); + json_write_ulong(&c->out, next->line); if (next->column > 0) { c->out.write(&c->out, ','); json_write_string(&c->out, "ECol"); c->out.write(&c->out, ':'); - json_write_ulong(&c->out, next->column - 1); + json_write_ulong(&c->out, next->column); } state_file = NULL; if (state->file >= 1 && state->file <= unit->files_cnt) { diff --git a/linenumbers_win32.c b/linenumbers_win32.c index 82454b77..ebbbec45 100644 --- a/linenumbers_win32.c +++ b/linenumbers_win32.c @@ -34,9 +34,69 @@ static const char * LINENUMBERS = "LineNumbers"; +typedef struct LineToAddressArgs { + Context * ctx; + char * file; + int line; + line_to_address_callback callback; + void * user_args; + int error; +} LineToAddressArgs; + +static BOOL CALLBACK line_to_address_iterator(PSTR module_name, DWORD base_address, PVOID x) { + DWORD offset = 0; + IMAGEHLP_LINE line; + LineToAddressArgs * args = (LineToAddressArgs *)x; + + memset(&line, 0, sizeof(line)); + line.SizeOfStruct = sizeof(IMAGEHLP_LINE); + + if (args->error == 0 && !SymGetLineFromName(args->ctx->handle, module_name, args->file, args->line, &offset, &line)) { + set_win32_errno(GetLastError()); + args->error = errno; + } + if (args->error == 0) { + args->callback(args->user_args, line.Address); + } + return args->error == 0; +} + +int line_to_address(Context * ctx, char * file, int line, int column, line_to_address_callback callback, void * user_args) { + int err = 0; + + if (ctx == NULL) err = ERR_INV_CONTEXT; + else if (ctx->exited) err = ERR_ALREADY_EXITED; + + if (err == 0 && ctx->parent != NULL) ctx = ctx->parent; + if (err == 0 && set_symbol_context(ctx) != 0) err = errno; + + if (err == 0) { + LineToAddressArgs args; + args.ctx = ctx; + args.file = file; + args.line = line; + args.callback = callback; + args.user_args = user_args; + args.error = 0; + if (!SymEnumerateModules(ctx->handle, line_to_address_iterator, &args)) { + set_win32_errno(GetLastError()); + err = errno; + } + else { + err = args.error; + } + } + + if (err != 0) { + errno = err; + return -1; + } + return 0; +} + static void command_map_to_source(char * token, Channel * c) { int err = 0; - char * err_msg = NULL; + int not_found = 0; char id[256]; unsigned long addr0; unsigned long addr1; @@ -64,19 +124,25 @@ static void command_map_to_source(char * token, Channel * c) { line.SizeOfStruct = sizeof(IMAGEHLP_LINE); if (err == 0 && !SymGetLineFromAddr(ctx->handle, addr0, &offset, &line)) { - set_win32_errno(GetLastError()); - err = errno; + DWORD w = GetLastError(); + if (w == ERROR_MOD_NOT_FOUND) { + not_found = 1; + } + else { + set_win32_errno(w); + err = errno; + } } memcpy(&next, &line, sizeof(next)); - if (err == 0 && !SymGetLineNext(ctx->handle, &next)) { + if (err == 0 && !not_found && !SymGetLineNext(ctx->handle, &next)) { set_win32_errno(GetLastError()); err = errno; } write_stringz(&c->out, "R"); write_stringz(&c->out, token); - write_err_msg(&c->out, err, err_msg); - if (err != 0) { + write_errno(&c->out, err); + if (err != 0 || not_found) { write_stringz(&c->out, "null"); } else { @@ -197,15 +197,13 @@ PeerServer * peer_server_add(PeerServer * n, unsigned int stale_delta) { } /* Find peer server based on ID */ -PeerServer * peer_server_find(const char *id) { - PeerServerList *pi = &peer_server_list; +PeerServer * peer_server_find(const char * id) { + PeerServerList * pi = &peer_server_list; PeerServer * s; assert(is_dispatch_thread()); for (s = pi->root; s != NULL; s = s->next) { - if (strcmp(s->id, id) == 0) { - return s; - } + if (strcmp(s->id, id) == 0) return s; } return NULL; } @@ -124,16 +124,16 @@ static void free_services(void * owner) { } } -static int message_hash(Protocol *p, const char * service, const char * name) { +static unsigned message_hash(Protocol * p, const char * service, const char * name) { int i; - int h = (unsigned long)p; + unsigned h = (unsigned)p; for (i = 0; service[i]; i++) h += service[i]; for (i = 0; name[i]; i++) h += name[i]; h = h + h / MESSAGE_HASH_SIZE; return h % MESSAGE_HASH_SIZE; } -static MessageHandlerInfo * find_message_handler(Protocol *p, char * service, char * name) { +static MessageHandlerInfo * find_message_handler(Protocol * p, char * service, char * name) { MessageHandlerInfo * mh = message_handlers[message_hash(p, service, name)]; while (mh != NULL) { if (mh->p == p && !strcmp(mh->service->name, service) && !strcmp(mh->name, name)) return mh; @@ -142,16 +142,16 @@ static MessageHandlerInfo * find_message_handler(Protocol *p, char * service, ch return NULL; } -static int event_hash(Channel *c, const char * service, const char * name) { +static unsigned event_hash(Channel * c, const char * service, const char * name) { int i; - int h = (unsigned long)c; + unsigned h = (unsigned)c; for (i = 0; service[i]; i++) h += service[i]; for (i = 0; name[i]; i++) h += name[i]; h = h + h / EVENT_HASH_SIZE; return h % EVENT_HASH_SIZE; } -static EventHandlerInfo * find_event_handler(Channel *c, char * service, char * name) { +static EventHandlerInfo * find_event_handler(Channel * c, char * service, char * name) { EventHandlerInfo * mh = event_handlers[event_hash(c, service, name)]; while (mh != NULL) { if (mh->c == c && !strcmp(mh->service->name, service) && !strcmp(mh->name, name)) return mh; @@ -160,11 +160,11 @@ static EventHandlerInfo * find_event_handler(Channel *c, char * service, char * return NULL; } -#define reply_hash(c, tokenid) ((((unsigned long)c)+(tokenid)) % REPLY_HASH_SIZE) +#define reply_hash(c, tokenid) (((unsigned)(c)+(unsigned)(tokenid)) % REPLY_HASH_SIZE) -static ReplyHandlerInfo * find_reply_handler(Channel *c, unsigned long tokenid, int take) { - ReplyHandlerInfo **rhp = &reply_handlers[reply_hash(c, tokenid)]; - ReplyHandlerInfo *rh; +static ReplyHandlerInfo * find_reply_handler(Channel * c, unsigned long tokenid, int take) { + ReplyHandlerInfo ** rhp = &reply_handlers[reply_hash(c, tokenid)]; + ReplyHandlerInfo * rh; while ((rh = *rhp) != NULL) { if (rh->c == c && rh->tokenid == tokenid) { if (take) { @@ -314,8 +314,8 @@ void set_default_message_handler(Protocol *p, ProtocolMessageHandler handler) { p->default_handler = handler; } -void add_command_handler(Protocol *p, const char * service, const char * name, ProtocolCommandHandler handler) { - int h = message_hash(p, service, name); +void add_command_handler(Protocol * p, const char * service, const char * name, ProtocolCommandHandler handler) { + unsigned h = message_hash(p, service, name); MessageHandlerInfo * mh = (MessageHandlerInfo *)loc_alloc(sizeof(MessageHandlerInfo)); mh->p = p; mh->service = protocol_get_service(p, service); @@ -325,8 +325,8 @@ void add_command_handler(Protocol *p, const char * service, const char * name, P message_handlers[h] = mh; } -void add_event_handler(Channel *c, const char * service, const char * name, ProtocolEventHandler handler) { - int h = event_hash(c, service, name); +void add_event_handler(Channel * c, const char * service, const char * name, ProtocolEventHandler handler) { + unsigned h = event_hash(c, service, name); EventHandlerInfo * eh = (EventHandlerInfo *)loc_alloc(sizeof(EventHandlerInfo)); eh->c = c; eh->service = protocol_get_service(c, service); @@ -336,7 +336,7 @@ void add_event_handler(Channel *c, const char * service, const char * name, Prot event_handlers[h] = eh; } -ReplyHandlerInfo *protocol_send_command(Protocol *p, Channel *c, const char *service, const char *name, ReplyHandlerCB handler, void *client_data) { +ReplyHandlerInfo * protocol_send_command(Protocol * p, Channel * c, const char *service, const char *name, ReplyHandlerCB handler, void *client_data) { ReplyHandlerInfo *rh; int h; unsigned long tokenid; @@ -360,7 +360,7 @@ ReplyHandlerInfo *protocol_send_command(Protocol *p, Channel *c, const char *ser return rh; } -void send_hello_message(Protocol *p, Channel *c) { +void send_hello_message(Protocol * p, Channel * c) { ServiceInfo * s = services; int cnt = 0; @@ -381,7 +381,7 @@ void send_hello_message(Protocol *p, Channel *c) { c->out.write(&c->out, MARKER_EOM); } -static void command_sync(char * token, Channel *c) { +static void command_sync(char * token, Channel * c) { if (c->inp.read(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); write_stringz(&c->out, "R"); write_stringz(&c->out, token); @@ -389,7 +389,7 @@ static void command_sync(char * token, Channel *c) { c->out.write(&c->out, MARKER_EOM); } -static void command_redirect(char * token, Channel *c) { +static void command_redirect(char * token, Channel * c) { char id[256]; json_read_string(&c->inp, id, sizeof(id)); @@ -435,7 +435,7 @@ static PeerServer * read_peer_properties(InputStream * inp) { return ps; } -static void command_publish_peer(char * token, Channel *c) { +static void command_publish_peer(char * token, Channel * c) { PeerServer * ps = read_peer_properties(&c->inp); if (c->inp.read(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (c->inp.read(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); @@ -621,7 +621,7 @@ void protocol_release(Protocol * p) { free_services(p); } -void ini_locator_service(Protocol *p) { +void ini_locator_service(Protocol * p) { add_command_handler(p, LOCATOR, "sync", command_sync); add_command_handler(p, LOCATOR, "redirect", command_redirect); add_command_handler(p, LOCATOR, "publishPeer", command_publish_peer); diff --git a/symbols_win32.c b/symbols_win32.c index 7d776b96..64ac4222 100644 --- a/symbols_win32.c +++ b/symbols_win32.c @@ -32,40 +32,10 @@ # define MAX_SYM_NAME 2000 #endif -static HANDLE current_process = NULL; -static ULONG current_base = 0; - -/* -static BOOL CALLBACK EnumSymProc1( - LPSTR SymbolName, - ULONG SymbolAddress, - ULONG SymbolSize, - PVOID UserContext) -{ - printf("%08X %4u %s\n", (long)SymbolAddress, SymbolSize, SymbolName); - return TRUE; -} - -static void print_symbols(void) { - printf("process 0x%08x, base address 0x%08x\n", current_process, current_base); - if (!SymEnumerateSymbols(current_process, current_base, EnumSymProc1, NULL)) { - printf("SymEnumerateSymbols failed: %d\n", GetLastError()); - } -} -*/ - int set_symbol_context(Context * ctx) { if (ctx->parent != NULL) ctx = ctx->parent; assert(ctx->pid == ctx->mem); - if (ctx->handle != current_process) { - if (current_process != NULL) { - if (!SymCleanup(current_process)) { - set_win32_errno(GetLastError()); - trace(LOG_ALWAYS, "SymCleanup() error: %d: %s", - errno, errno_to_str(errno)); - } - current_process = NULL; - } + if (!ctx->sym_handler_loaded) { if (!SymInitialize(ctx->handle, NULL, FALSE)) { set_win32_errno(GetLastError()); return -1; @@ -74,8 +44,7 @@ int set_symbol_context(Context * ctx) { set_win32_errno(GetLastError()); return -1; } - current_process = ctx->handle; - current_base = (ULONG)ctx->base_address; + ctx->sym_handler_loaded = 1; } return 0; } @@ -147,13 +116,18 @@ int find_symbol(Context * ctx, char * name, Symbol * sym) { static void event_context_exited(Context * ctx, void * client_data) { assert(ctx->handle != NULL); - if (ctx->handle == current_process) { - if (!SymCleanup(current_process)) { + if (ctx->sym_handler_loaded) { + if (!SymUnloadModule(ctx->handle, (DWORD)ctx->base_address)) { + set_win32_errno(GetLastError()); + trace(LOG_ALWAYS, "SymUnloadModule() error: %d: %s", + errno, errno_to_str(errno)); + } + if (!SymCleanup(ctx->handle)) { set_win32_errno(GetLastError()); trace(LOG_ALWAYS, "SymCleanup() error: %d: %s", errno, errno_to_str(errno)); } - current_process = NULL; + ctx->sym_handler_loaded = 0; } } |