xref: /reactos/dll/win32/dbghelp/rsym.c (revision 57519609)
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