1 /* 2 * PROJECT: ReactOS dbghelp extension 3 * LICENSE: GPLv2+ - See COPYING in the top level directory 4 * PURPOSE: Parse rsym information for use with dbghelp 5 * PROGRAMMER: Mark Jansen 6 */ 7 8 #include "dbghelp_private.h" 9 #include <reactos/rossym.h> 10 11 #include <wine/debug.h> 12 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_rsym); 13 14 15 typedef struct rsym_file_entry_s 16 { 17 const char* File; 18 unsigned Source; 19 } rsym_file_entry_t; 20 21 typedef struct rsym_func_entry_s 22 { 23 ULONG_PTR Address; 24 struct symt_function* func; 25 struct rsym_func_entry_s* next; 26 } rsym_func_entry_t; 27 28 29 30 /****************************************************************** 31 * rsym_finalize_function (copied from stabs_finalize_function) 32 * 33 * Ends function creation: mainly: 34 * - cleans up line number information 35 * - tries to set up a debug-start tag (FIXME: heuristic to be enhanced) 36 */ 37 static void rsym_finalize_function(struct module* module, struct symt_function* func) 38 { 39 IMAGEHLP_LINE64 il; 40 struct location loc; 41 42 if (!func) return; 43 symt_normalize_function(module, func); 44 /* To define the debug-start of the function, we use the second line number. 45 * Not 100% bullet proof, but better than nothing 46 */ 47 if (symt_fill_func_line_info(module, func, func->address, &il) && 48 symt_get_func_line_next(module, &il)) 49 { 50 loc.kind = loc_absolute; 51 loc.offset = il.Address - func->address; 52 symt_add_function_point(module, func, SymTagFuncDebugStart, 53 &loc, NULL); 54 } 55 } 56 57 58 static int is_metadata_sym(const char* name) 59 { 60 ULONG len = name ? strlen(name) : 0; 61 return len > 3 && name[0] == '_' && name[1] != '_' && name[len-1] == '_' && name[len-2] == '_'; 62 }; 63 64 static int use_raw_address(const char* name) 65 { 66 if (!name) 67 return 0; 68 69 if (!strcmp(name, "__ImageBase")) 70 return 1; 71 72 if (!strcmp(name, "__RUNTIME_PSEUDO_RELOC_LIST__")) 73 return 1; 74 75 return 0; 76 } 77 78 79 BOOL rsym_parse(struct module* module, unsigned long load_offset, 80 const void* rsym_ptr, int rsymlen) 81 { 82 const ROSSYM_HEADER* RosSymHeader; 83 const ROSSYM_ENTRY* First, *Last, *Entry; 84 const CHAR* Strings; 85 86 struct pool pool; 87 struct sparse_array file_table, func_table; 88 rsym_func_entry_t* first_func = NULL; 89 90 91 RosSymHeader = rsym_ptr; 92 93 if (RosSymHeader->SymbolsOffset < sizeof(ROSSYM_HEADER) 94 || RosSymHeader->StringsOffset < RosSymHeader->SymbolsOffset + RosSymHeader->SymbolsLength 95 || rsymlen < RosSymHeader->StringsOffset + RosSymHeader->StringsLength 96 || 0 != (RosSymHeader->SymbolsLength % sizeof(ROSSYM_ENTRY))) 97 { 98 WARN("Invalid ROSSYM_HEADER\n"); 99 return FALSE; 100 } 101 102 First = (const ROSSYM_ENTRY *)((const char*)rsym_ptr + RosSymHeader->SymbolsOffset); 103 Last = First + RosSymHeader->SymbolsLength / sizeof(ROSSYM_ENTRY); 104 Strings = (const CHAR*)rsym_ptr + RosSymHeader->StringsOffset; 105 106 pool_init(&pool, 65536); 107 sparse_array_init(&file_table, sizeof(rsym_file_entry_t), 64); 108 sparse_array_init(&func_table, sizeof(rsym_func_entry_t), 128); 109 110 for (Entry = First; Entry != Last; Entry++) 111 { 112 ULONG Address = load_offset + Entry->Address; 113 if (!Entry->FileOffset) 114 { 115 rsym_func_entry_t* func = sparse_array_find(&func_table, Entry->FunctionOffset); 116 117 /* We do not want to define a data point where there is already a function! */ 118 if (!func || func->Address != Address) 119 { 120 const char* SymbolName = Strings + Entry->FunctionOffset; 121 if (!is_metadata_sym(SymbolName)) 122 { 123 /* TODO: How should we determine the size? */ 124 ULONG Size = sizeof(ULONG); 125 if (use_raw_address(SymbolName)) 126 Address = Entry->Address; 127 128 symt_new_public(module, NULL, SymbolName, FALSE, Address, Size); 129 } 130 else 131 { 132 /* Maybe use it to fill some metadata? */ 133 } 134 } 135 } 136 else 137 { 138 rsym_file_entry_t* file = sparse_array_find(&file_table, Entry->FileOffset); 139 rsym_func_entry_t* func = sparse_array_find(&func_table, Entry->FunctionOffset); 140 141 if (!file) 142 { 143 file = sparse_array_add(&file_table, Entry->FileOffset, &pool); 144 file->File = Strings + Entry->FileOffset; 145 file->Source = source_new(module, NULL, Strings + Entry->FileOffset); 146 } 147 148 if (!func) 149 { 150 func = sparse_array_add(&func_table, Entry->FunctionOffset, &pool); 151 func->func = symt_new_function(module, NULL, Strings + Entry->FunctionOffset, 152 Address, 0, NULL); 153 func->Address = Address; 154 func->next = first_func; 155 first_func = func; 156 } 157 158 /* TODO: What if we have multiple chunks scattered around? */ 159 symt_add_func_line(module, func->func, file->Source, Entry->SourceLine, Address - func->Address); 160 } 161 } 162 163 while (first_func) 164 { 165 /* TODO: Size of function? */ 166 rsym_finalize_function(module, first_func->func); 167 first_func = first_func->next; 168 } 169 170 module->module.SymType = SymDia; 171 module->module.CVSig = 'R' | ('S' << 8) | ('Y' << 16) | ('M' << 24); 172 module->module.LineNumbers = TRUE; 173 module->module.GlobalSymbols = TRUE; 174 module->module.TypeInfo = FALSE; 175 module->module.SourceIndexed = TRUE; 176 module->module.Publics = TRUE; 177 178 pool_destroy(&pool); 179 180 return TRUE; 181 } 182 183