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