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 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_rsym
);
14 typedef struct rsym_file_entry_s
20 typedef struct rsym_func_entry_s
23 struct symt_function
* func
;
24 struct rsym_func_entry_s
* next
;
29 /******************************************************************
30 * rsym_finalize_function (copied from stabs_finalize_function)
32 * Ends function creation: mainly:
33 * - cleans up line number information
34 * - tries to set up a debug-start tag (FIXME: heuristic to be enhanced)
36 static void rsym_finalize_function(struct module
* module
, struct symt_function
* func
)
42 symt_normalize_function(module
, func
);
43 /* To define the debug-start of the function, we use the second line number.
44 * Not 100% bullet proof, but better than nothing
46 if (symt_fill_func_line_info(module
, func
, func
->address
, &il
) &&
47 symt_get_func_line_next(module
, &il
))
49 loc
.kind
= loc_absolute
;
50 loc
.offset
= il
.Address
- func
->address
;
51 symt_add_function_point(module
, func
, SymTagFuncDebugStart
,
57 static int is_metadata_sym(const char* name
)
59 ULONG len
= name
? strlen(name
) : 0;
60 return len
> 3 && name
[0] == '_' && name
[1] != '_' && name
[len
-1] == '_' && name
[len
-2] == '_';
63 static int use_raw_address(const char* name
)
68 if (!strcmp(name
, "__ImageBase"))
71 if (!strcmp(name
, "__RUNTIME_PSEUDO_RELOC_LIST__"))
78 BOOL
rsym_parse(struct module
* module
, unsigned long load_offset
,
79 const void* rsym_ptr
, int rsymlen
)
81 const ROSSYM_HEADER
* RosSymHeader
;
82 const ROSSYM_ENTRY
* First
, *Last
, *Entry
;
86 struct sparse_array file_table
, func_table
;
87 rsym_func_entry_t
* first_func
= NULL
;
90 RosSymHeader
= rsym_ptr
;
92 if (RosSymHeader
->SymbolsOffset
< sizeof(ROSSYM_HEADER
)
93 || RosSymHeader
->StringsOffset
< RosSymHeader
->SymbolsOffset
+ RosSymHeader
->SymbolsLength
94 || rsymlen
< RosSymHeader
->StringsOffset
+ RosSymHeader
->StringsLength
95 || 0 != (RosSymHeader
->SymbolsLength
% sizeof(ROSSYM_ENTRY
)))
97 WARN("Invalid ROSSYM_HEADER\n");
101 First
= (const ROSSYM_ENTRY
*)((const char*)rsym_ptr
+ RosSymHeader
->SymbolsOffset
);
102 Last
= First
+ RosSymHeader
->SymbolsLength
/ sizeof(ROSSYM_ENTRY
);
103 Strings
= (const CHAR
*)rsym_ptr
+ RosSymHeader
->StringsOffset
;
105 pool_init(&pool
, 65536);
106 sparse_array_init(&file_table
, sizeof(rsym_file_entry_t
), 64);
107 sparse_array_init(&func_table
, sizeof(rsym_func_entry_t
), 128);
109 for (Entry
= First
; Entry
!= Last
; Entry
++)
111 ULONG Address
= load_offset
+ Entry
->Address
;
112 if (!Entry
->FileOffset
)
114 rsym_func_entry_t
* func
= sparse_array_find(&func_table
, Entry
->FunctionOffset
);
116 /* We do not want to define a data point where there is already a function! */
117 if (!func
|| func
->Address
!= Address
)
119 const char* SymbolName
= Strings
+ Entry
->FunctionOffset
;
120 if (!is_metadata_sym(SymbolName
))
122 /* TODO: How should we determine the size? */
123 ULONG Size
= sizeof(ULONG
);
124 if (use_raw_address(SymbolName
))
125 Address
= Entry
->Address
;
127 symt_new_public(module
, NULL
, SymbolName
, Address
, Size
);
131 /* Maybe use it to fill some metadata? */
137 rsym_file_entry_t
* file
= sparse_array_find(&file_table
, Entry
->FileOffset
);
138 rsym_func_entry_t
* func
= sparse_array_find(&func_table
, Entry
->FunctionOffset
);
142 file
= sparse_array_add(&file_table
, Entry
->FileOffset
, &pool
);
143 file
->File
= Strings
+ Entry
->FileOffset
;
144 file
->Source
= source_new(module
, NULL
, Strings
+ Entry
->FileOffset
);
149 func
= sparse_array_add(&func_table
, Entry
->FunctionOffset
, &pool
);
150 func
->func
= symt_new_function(module
, NULL
, Strings
+ Entry
->FunctionOffset
,
152 func
->Address
= Address
;
153 func
->next
= first_func
;
157 /* TODO: What if we have multiple chunks scattered around? */
158 symt_add_func_line(module
, func
->func
, file
->Source
, Entry
->SourceLine
, Address
- func
->Address
);
164 /* TODO: Size of function? */
165 rsym_finalize_function(module
, first_func
->func
);
166 first_func
= first_func
->next
;
169 module
->module
.SymType
= SymDia
;
170 module
->module
.CVSig
= 'R' | ('S' << 8) | ('Y' << 16) | ('M' << 24);
171 module
->module
.LineNumbers
= TRUE
;
172 module
->module
.GlobalSymbols
= TRUE
;
173 module
->module
.TypeInfo
= FALSE
;
174 module
->module
.SourceIndexed
= TRUE
;
175 module
->module
.Publics
= TRUE
;