[DBGHELP_APITEST] Add tests for pdb and rsym parsing. CORE-12773
[reactos.git] / rostests / apitests / dbghelp / data.c
1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Support functions for dbghelp api test
5 * PROGRAMMER: Mark Jansen
6 */
7
8 #include <windows.h>
9 #include <stdio.h>
10 #include <zlib.h>
11
12 #include "wine/test.h"
13
14 extern IMAGE_DOS_HEADER __ImageBase;
15
16 static char szTempPath[MAX_PATH];
17
18 static const char* tmpdir()
19 {
20 if (szTempPath[0] == '\0')
21 {
22 GetTempPathA(MAX_PATH, szTempPath);
23 lstrcatA(szTempPath, "dbghelp_tst");
24 }
25 return szTempPath;
26 }
27
28 static int extract_one(const char* filename, const char* resid)
29 {
30 HMODULE mod = (HMODULE)&__ImageBase;
31 HGLOBAL glob;
32 PVOID data, decompressed;
33 uLongf size, dstsize;
34 DWORD gccSize, dwErr;
35 HANDLE file;
36 int ret;
37 HRSRC rsrc = FindResourceA(mod, resid, MAKEINTRESOURCEA(RT_RCDATA));
38 ok(rsrc != 0, "Failed finding '%s' res\n", resid);
39 if (!rsrc)
40 return 0;
41
42 size = SizeofResource(mod, rsrc);
43 glob = LoadResource(mod, rsrc);
44 ok(glob != NULL, "Failed loading '%s' res\n", resid);
45 if (!glob)
46 return 0;
47
48 data = LockResource(glob);
49
50 dstsize = 1024 * 256;
51 decompressed = malloc(dstsize);
52
53 if (uncompress(decompressed, &dstsize, data, size) != Z_OK)
54 {
55 ok(0, "uncompress failed for %s\n", resid);
56 free(decompressed);
57 return 0;
58 }
59
60
61 file = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
62 gccSize = size;
63 ret = WriteFile(file, decompressed, dstsize, &gccSize, NULL);
64 dwErr = GetLastError();
65 CloseHandle(file);
66 free(decompressed);
67 ok(ret, "WriteFile failed (%d)\n", dwErr);
68 return ret && dstsize == gccSize;
69 }
70
71
72 int extract_msvc_exe(char szFile[MAX_PATH])
73 {
74 const char* dir = tmpdir();
75 BOOL ret = CreateDirectoryA(dir, NULL);
76 ok(ret, "CreateDirectoryA failed(%d)\n", GetLastError());
77
78 sprintf(szFile, "%s\\uffs.pdb", dir);
79 if (!extract_one(szFile, "msvc_uffs.pdb"))
80 return 0;
81
82 sprintf(szFile, "%s\\uffs.dll", dir);
83 if (!extract_one(szFile, "msvc_uffs.dll"))
84 return 0;
85
86 return 1;
87 }
88
89 void cleanup_msvc_exe()
90 {
91 char szFile[MAX_PATH];
92 BOOL ret;
93 const char* dir = tmpdir();
94
95 sprintf(szFile, "%s\\uffs.pdb", dir);
96 ret = DeleteFileA(szFile);
97 ok(ret, "DeleteFileA failed(%d)\n", GetLastError());
98
99 sprintf(szFile, "%s\\uffs.dll", dir);
100 ret = DeleteFileA(szFile);
101 ok(ret, "DeleteFileA failed(%d)\n", GetLastError());
102 ret = RemoveDirectoryA(dir);
103 ok(ret, "RemoveDirectoryA failed(%d)\n", GetLastError());
104 }
105
106 int extract_gcc_exe(char szFile[MAX_PATH])
107 {
108 const char* dir = tmpdir();
109 BOOL ret = CreateDirectoryA(dir, NULL);
110 ok(ret, "CreateDirectoryA failed(%d)\n", GetLastError());
111
112 sprintf(szFile, "%s\\uffs.dll", dir);
113 if (!extract_one(szFile, "gcc_uffs.dll"))
114 return 0;
115
116 return 1;
117 }
118
119 void cleanup_gcc_exe()
120 {
121 char szFile[MAX_PATH];
122 BOOL ret;
123 const char* dir = tmpdir();
124
125 sprintf(szFile, "%s\\uffs.dll", dir);
126 ret = DeleteFileA(szFile);
127 ok(ret, "DeleteFileA failed(%d)\n", GetLastError());
128 ret = RemoveDirectoryA(dir);
129 ok(ret, "RemoveDirectoryA failed(%d)\n", GetLastError());
130 }
131
132
133 #if 0
134 static int compress_one(const char* src, const char* dest)
135 {
136 DWORD size, size2, res;
137 FILE* file = fopen(src, "rb");
138 fseek(file, 0, SEEK_END);
139 size = ftell(file);
140 fseek(file, 0, SEEK_SET);
141
142 Bytef* buffer, *buffer2;
143 DWORD dwErr = GetLastError();
144
145 buffer = malloc(size);
146 res = fread(buffer, 1, size, file);
147
148 fclose(file);
149
150 if (res != size)
151 {
152 printf("Could not read file: 0x%x\n", dwErr);
153 free(buffer);
154 CloseHandle(file);
155 return 0;
156 }
157 size2 = size *2;
158 buffer2 = malloc(size2);
159 res = compress(buffer2, &size2, buffer, size);
160
161 free(buffer);
162
163 if (Z_OK != res)
164 {
165 free(buffer2);
166 return 0;
167 }
168
169 file = fopen(dest, "wb");
170 res = fwrite(buffer2, 1, size2, file);
171 fclose(file);
172
173 free(buffer2);
174
175 return size2 == res;
176 }
177
178 void create_compressed_files()
179 {
180 SetCurrentDirectoryA("R:/src/trunk/reactos/modules/rostests/apitests/dbghelp");
181 if (!compress_one("testdata/msvc_uffs.dll", "testdata/msvc_uffs.dll.compr"))
182 printf("msvc_uffs.dll failed\n");
183 if (!compress_one("testdata/msvc_uffs.pdb", "testdata/msvc_uffs.pdb.compr"))
184 printf("msvc_uffs.pdb failed\n");
185 if (!compress_one("testdata/gcc_uffs.dll", "testdata/gcc_uffs.dll.compr"))
186 printf("gcc_uffs.dll failed\n");
187 }
188 #endif
189
190 #if 0
191 typedef struct _SYMBOLFILE_HEADER {
192 ULONG SymbolsOffset;
193 ULONG SymbolsLength;
194 ULONG StringsOffset;
195 ULONG StringsLength;
196 } SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER;
197
198 typedef struct _ROSSYM_ENTRY {
199 ULONG Address;
200 ULONG FunctionOffset;
201 ULONG FileOffset;
202 ULONG SourceLine;
203 } ROSSYM_ENTRY, *PROSSYM_ENTRY;
204
205
206 static int is_metadata(const char* name)
207 {
208 size_t len = name ? strlen(name) : 0;
209 return len > 3 && name[0] == '_' && name[1] != '_' && name[len-1] == '_' && name[len-2] == '_';
210 };
211
212 static void dump_rsym_internal(void* data)
213 {
214 PSYMBOLFILE_HEADER RosSymHeader = (PSYMBOLFILE_HEADER)data;
215 PROSSYM_ENTRY Entries = (PROSSYM_ENTRY)((char *)data + RosSymHeader->SymbolsOffset);
216 size_t symbols = RosSymHeader->SymbolsLength / sizeof(ROSSYM_ENTRY);
217 size_t i;
218 char *Strings = (char *)data + RosSymHeader->StringsOffset;
219
220 for (i = 0; i < symbols; i++)
221 {
222 PROSSYM_ENTRY Entry = Entries + i;
223 if (!Entry->FileOffset)
224 {
225 if (Entry->SourceLine)
226 printf("ERR: SOURCELINE (%D) ", Entry->SourceLine);
227 if (is_metadata(Strings + Entry->FunctionOffset))
228 printf("metadata: %s: 0x%x\n", Strings + Entry->FunctionOffset, Entry->Address);
229 else
230 printf("0x%x: %s\n", Entry->Address, Strings + Entry->FunctionOffset);
231 }
232 else
233 {
234 printf("0x%x: %s (%s:%u)\n", Entry->Address,
235 Strings + Entry->FunctionOffset,
236 Strings + Entry->FileOffset,
237 Entry->SourceLine);
238 }
239 }
240
241 }
242
243 void dump_rsym(const char* filename)
244 {
245 char* data;
246 long size, res;
247 PIMAGE_FILE_HEADER PEFileHeader;
248 PIMAGE_OPTIONAL_HEADER PEOptHeader;
249 PIMAGE_SECTION_HEADER PESectionHeaders;
250 WORD i;
251
252 FILE* f = fopen(filename, "rb");
253
254 fseek(f, 0, SEEK_END);
255 size = ftell(f);
256 fseek(f, 0, SEEK_SET);
257
258 data = malloc(size);
259 res = fread(data, 1, size, f);
260 fclose(f);
261
262 PEFileHeader = (PIMAGE_FILE_HEADER)((char *)data + ((PIMAGE_DOS_HEADER)data)->e_lfanew + sizeof(ULONG));
263 PEOptHeader = (PIMAGE_OPTIONAL_HEADER)(PEFileHeader + 1);
264 PESectionHeaders = (PIMAGE_SECTION_HEADER)((char *)PEOptHeader + PEFileHeader->SizeOfOptionalHeader);
265
266 for (i = 0; i < PEFileHeader->NumberOfSections; i++)
267 {
268 if (!strcmp((char *)PESectionHeaders[i].Name, ".rossym"))
269 {
270 dump_rsym_internal(data + PESectionHeaders[i].PointerToRawData);
271 break;
272 }
273 }
274 free(data);
275 }
276
277 #endif