Author: mjansen Date: Fri Feb 17 16:18:15 2017 New Revision: 73817 URL: http://svn.reactos.org/svn/reactos?rev=73817&view=rev Log: [DBGHELP] Add experimental rsym support. CORE-12773
Added: trunk/reactos/dll/win32/dbghelp/rsym.c (with props) Modified: trunk/reactos/dll/win32/dbghelp/CMakeLists.txt trunk/reactos/dll/win32/dbghelp/dbghelp_private.h trunk/reactos/dll/win32/dbghelp/pe_module.c Modified: trunk/reactos/dll/win32/dbghelp/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/dbghelp/CMakeLists.txt?rev=73817&r1=73816&r2=73817&view=diff ============================================================================== --- trunk/reactos/dll/win32/dbghelp/CMakeLists.txt [iso-8859-1] (original) +++ trunk/reactos/dll/win32/dbghelp/CMakeLists.txt [iso-8859-1] Fri Feb 17 16:18:15 2017 @@ -63,6 +63,7 @@ path.c pe_module.c rosstubs.c + rsym.c source.c stabs.c stack.c Modified: trunk/reactos/dll/win32/dbghelp/dbghelp_private.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/dbghelp/dbghelp_private.h?rev=73817&r1=73816&r2=73817&view=diff ============================================================================== --- trunk/reactos/dll/win32/dbghelp/dbghelp_private.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/dbghelp/dbghelp_private.h [iso-8859-1] Fri Feb 17 16:18:15 2017 @@ -713,6 +713,12 @@ struct image_file_map* fmap) DECLSPEC_HIDDEN; extern BOOL dwarf2_virtual_unwind(struct cpu_stack_walk* csw, DWORD_PTR ip, CONTEXT* context, ULONG_PTR* cfa) DECLSPEC_HIDDEN; + +/* rsym.c */ +extern BOOL rsym_parse(struct module* module, unsigned long load_offset, + const void* rsym, int rsymlen) DECLSPEC_HIDDEN; + + /* stack.c */ #ifndef DBGHELP_STATIC_LIB Modified: trunk/reactos/dll/win32/dbghelp/pe_module.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/dbghelp/pe_module.c?rev=73817&r1=73816&r2=73817&view=diff ============================================================================== --- trunk/reactos/dll/win32/dbghelp/pe_module.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/dbghelp/pe_module.c [iso-8859-1] Fri Feb 17 16:18:15 2017 @@ -507,6 +507,32 @@ #ifndef DBGHELP_STATIC_LIB /****************************************************************** + * pe_load_rsym + * + * look for ReactOS's own rsym format + */ +static BOOL pe_load_rsym(struct module* module) +{ + struct image_file_map* fmap = &module->format_info[DFI_PE]->u.pe_info->fmap; + struct image_section_map sect_rsym; + BOOL ret = FALSE; + + if (pe_find_section(fmap, ".rossym", §_rsym)) + { + const char* rsym = image_map_section(§_rsym); + if (rsym != IMAGE_NO_MAP) + { + ret = rsym_parse(module, module->module.BaseOfImage, + rsym, image_get_map_size(§_rsym)); + } + image_unmap_section(§_rsym); + } + TRACE("%s the RSYM debug info\n", ret ? "successfully loaded" : "failed to load"); + + return ret; +} + +/****************************************************************** * pe_load_dbg_file * * loads a .dbg file @@ -704,7 +730,9 @@ ret = pe_load_dwarf(module) || ret; #ifndef DBGHELP_STATIC_LIB ret = pe_load_msc_debug_info(pcs, module) || ret; + ret = pe_load_rsym(module) || ret; #endif + ret = ret || pe_load_coff_symbol_table(module); /* FIXME */ /* if we still have no debug info (we could only get SymExport at this * point), then do the SymExport except if we have an ELF container, Added: trunk/reactos/dll/win32/dbghelp/rsym.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/dbghelp/rsym.c?rev=73817 ============================================================================== --- trunk/reactos/dll/win32/dbghelp/rsym.c (added) +++ trunk/reactos/dll/win32/dbghelp/rsym.c [iso-8859-1] Fri Feb 17 16:18:15 2017 @@ -0,0 +1,181 @@ +/* + * PROJECT: ReactOS dbghelp extension + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Parse rsym information for use with dbghelp + * PROGRAMMER: Mark Jansen + */ + +#include "dbghelp_private.h" +#include <reactos/rossym.h> + +WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_rsym); + + +typedef struct rsym_file_entry_s +{ + const char* File; + unsigned Source; +} rsym_file_entry_t; + +typedef struct rsym_func_entry_s +{ + ULONG_PTR Address; + struct symt_function* func; + struct rsym_func_entry_s* next; +} rsym_func_entry_t; + + + +/****************************************************************** + * rsym_finalize_function (copied from stabs_finalize_function) + * + * Ends function creation: mainly: + * - cleans up line number information + * - tries to set up a debug-start tag (FIXME: heuristic to be enhanced) + */ +static void rsym_finalize_function(struct module* module, struct symt_function* func) +{ + IMAGEHLP_LINE64 il; + struct location loc; + + if (!func) return; + symt_normalize_function(module, func); + /* To define the debug-start of the function, we use the second line number. + * Not 100% bullet proof, but better than nothing + */ + if (symt_fill_func_line_info(module, func, func->address, &il) && + symt_get_func_line_next(module, &il)) + { + loc.kind = loc_absolute; + loc.offset = il.Address - func->address; + symt_add_function_point(module, func, SymTagFuncDebugStart, + &loc, NULL); + } +} + + +static int is_metadata_sym(const char* name) +{ + ULONG len = name ? strlen(name) : 0; + return len > 3 && name[0] == '_' && name[1] != '_' && name[len-1] == '_' && name[len-2] == '_'; +}; + +static int use_raw_address(const char* name) +{ + if (!name) + return 0; + + if (!strcmp(name, "__ImageBase")) + return 1; + + if (!strcmp(name, "__RUNTIME_PSEUDO_RELOC_LIST__")) + return 1; + + return 0; +} + + +BOOL rsym_parse(struct module* module, unsigned long load_offset, + const void* rsym_ptr, int rsymlen) +{ + const ROSSYM_HEADER* RosSymHeader; + const ROSSYM_ENTRY* First, *Last, *Entry; + const CHAR* Strings; + + struct pool pool; + struct sparse_array file_table, func_table; + rsym_func_entry_t* first_func = NULL; + + + RosSymHeader = rsym_ptr; + + if (RosSymHeader->SymbolsOffset < sizeof(ROSSYM_HEADER) + || RosSymHeader->StringsOffset < RosSymHeader->SymbolsOffset + RosSymHeader->SymbolsLength + || rsymlen < RosSymHeader->StringsOffset + RosSymHeader->StringsLength + || 0 != (RosSymHeader->SymbolsLength % sizeof(ROSSYM_ENTRY))) + { + WARN("Invalid ROSSYM_HEADER\n"); + return FALSE; + } + + First = (const ROSSYM_ENTRY *)((const char*)rsym_ptr + RosSymHeader->SymbolsOffset); + Last = First + RosSymHeader->SymbolsLength / sizeof(ROSSYM_ENTRY); + Strings = (const CHAR*)rsym_ptr + RosSymHeader->StringsOffset; + + pool_init(&pool, 65536); + sparse_array_init(&file_table, sizeof(rsym_file_entry_t), 64); + sparse_array_init(&func_table, sizeof(rsym_func_entry_t), 128); + + for (Entry = First; Entry != Last; Entry++) + { + ULONG Address = load_offset + Entry->Address; + if (!Entry->FileOffset) + { + rsym_func_entry_t* func = sparse_array_find(&func_table, Entry->FunctionOffset); + + /* We do not want to define a data point where there is already a function! */ + if (!func || func->Address != Address) + { + const char* SymbolName = Strings + Entry->FunctionOffset; + if (!is_metadata_sym(SymbolName)) + { + /* TODO: How should we determine the size? */ + ULONG Size = sizeof(ULONG); + if (use_raw_address(SymbolName)) + Address = Entry->Address; + + symt_new_public(module, NULL, SymbolName, Address, Size); + } + else + { + /* Maybe use it to fill some metadata? */ + } + } + } + else + { + rsym_file_entry_t* file = sparse_array_find(&file_table, Entry->FileOffset); + rsym_func_entry_t* func = sparse_array_find(&func_table, Entry->FunctionOffset); + + if (!file) + { + file = sparse_array_add(&file_table, Entry->FileOffset, &pool); + file->File = Strings + Entry->FileOffset; + file->Source = source_new(module, NULL, Strings + Entry->FileOffset); + } + + if (!func) + { + func = sparse_array_add(&func_table, Entry->FunctionOffset, &pool); + func->func = symt_new_function(module, NULL, Strings + Entry->FunctionOffset, + Address, 0, NULL); + func->Address = Address; + func->next = first_func; + first_func = func; + } + + /* TODO: What if we have multiple chunks scattered around? */ + symt_add_func_line(module, func->func, file->Source, Entry->SourceLine, Address - func->Address); + } + } + + while (first_func) + { + /* TODO: Size of function? */ + rsym_finalize_function(module, first_func->func); + first_func = first_func->next; + } + + module->module.SymType = SymDia; + module->module.CVSig = 'R' | ('S' << 8) | ('Y' << 16) | ('M' << 24); + module->module.LineNumbers = TRUE; + module->module.GlobalSymbols = TRUE; + module->module.TypeInfo = FALSE; + module->module.SourceIndexed = TRUE; + module->module.Publics = TRUE; + + pool_destroy(&pool); + + return TRUE; +} + Propchange: trunk/reactos/dll/win32/dbghelp/rsym.c ------------------------------------------------------------------------------ svn:eol-style = native