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
8 #include "dbghelp_private.h"
9 #include <reactos/rossym.h>
11 #include <wine/debug.h>
12 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_rsym
);
15 typedef struct rsym_file_entry_s
21 typedef struct rsym_func_entry_s
24 struct symt_function
* func
;
25 struct rsym_func_entry_s
* next
;
30 /******************************************************************
31 * rsym_finalize_function (copied from stabs_finalize_function)
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)
37 static void rsym_finalize_function(struct module
* module
, struct symt_function
* func
)
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
47 if (symt_fill_func_line_info(module
, func
, func
->address
, &il
) &&
48 symt_get_func_line_next(module
, &il
))
50 loc
.kind
= loc_absolute
;
51 loc
.offset
= il
.Address
- func
->address
;
52 symt_add_function_point(module
, func
, SymTagFuncDebugStart
,
58 static int is_metadata_sym(const char* name
)
60 ULONG len
= name
? strlen(name
) : 0;
61 return len
> 3 && name
[0] == '_' && name
[1] != '_' && name
[len
-1] == '_' && name
[len
-2] == '_';
64 static int use_raw_address(const char* name
)
69 if (!strcmp(name
, "__ImageBase"))
72 if (!strcmp(name
, "__RUNTIME_PSEUDO_RELOC_LIST__"))
79 BOOL
rsym_parse(struct module
* module
, unsigned long load_offset
,
80 const void* rsym_ptr
, int rsymlen
)
82 const ROSSYM_HEADER
* RosSymHeader
;
83 const ROSSYM_ENTRY
* First
, *Last
, *Entry
;
87 struct sparse_array file_table
, func_table
;
88 rsym_func_entry_t
* first_func
= NULL
;
91 RosSymHeader
= rsym_ptr
;
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
)))
98 WARN("Invalid ROSSYM_HEADER\n");
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
;
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);
110 for (Entry
= First
; Entry
!= Last
; Entry
++)
112 ULONG Address
= load_offset
+ Entry
->Address
;
113 if (!Entry
->FileOffset
)
115 rsym_func_entry_t
* func
= sparse_array_find(&func_table
, Entry
->FunctionOffset
);
117 /* We do not want to define a data point where there is already a function! */
118 if (!func
|| func
->Address
!= Address
)
120 const char* SymbolName
= Strings
+ Entry
->FunctionOffset
;
121 if (!is_metadata_sym(SymbolName
))
123 /* TODO: How should we determine the size? */
124 ULONG Size
= sizeof(ULONG
);
125 if (use_raw_address(SymbolName
))
126 Address
= Entry
->Address
;
128 symt_new_public(module
, NULL
, SymbolName
, Address
, Size
);
132 /* Maybe use it to fill some metadata? */
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
);
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
);
150 func
= sparse_array_add(&func_table
, Entry
->FunctionOffset
, &pool
);
151 func
->func
= symt_new_function(module
, NULL
, Strings
+ Entry
->FunctionOffset
,
153 func
->Address
= Address
;
154 func
->next
= first_func
;
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
);
165 /* TODO: Size of function? */
166 rsym_finalize_function(module
, first_func
->func
);
167 first_func
= first_func
->next
;
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
;