Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencoff.c
Go to the documentation of this file.
00001 /* 00002 * Read VC++ debug information from COFF and eventually 00003 * from PDB files. 00004 * 00005 * Copyright (C) 1996, Eric Youngdale. 00006 * Copyright (C) 1999-2000, Ulrich Weigand. 00007 * Copyright (C) 2004, Eric Pouech. 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 2.1 of the License, or (at your option) any later version. 00013 * 00014 * This library is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Lesser General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public 00020 * License along with this library; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00022 */ 00023 00024 /* 00025 * Note - this handles reading debug information for 32 bit applications 00026 * that run under Windows-NT for example. I doubt that this would work well 00027 * for 16 bit applications, but I don't think it really matters since the 00028 * file format is different, and we should never get in here in such cases. 00029 * 00030 * TODO: 00031 * Get 16 bit CV stuff working. 00032 * Add symbol size to internal symbol table. 00033 */ 00034 00035 #include "config.h" 00036 #include "wine/port.h" 00037 00038 #include <assert.h> 00039 #include <stdlib.h> 00040 00041 #include <string.h> 00042 #ifdef HAVE_UNISTD_H 00043 # include <unistd.h> 00044 #endif 00045 00046 #include <stdarg.h> 00047 #include "windef.h" 00048 #include "winbase.h" 00049 #include "winternl.h" 00050 00051 #include "wine/exception.h" 00052 #include "wine/debug.h" 00053 #include "dbghelp_private.h" 00054 #include "wine/mscvpdb.h" 00055 00056 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_coff); 00057 00058 /*======================================================================== 00059 * Process COFF debug information. 00060 */ 00061 00062 struct CoffFile 00063 { 00064 unsigned int startaddr; 00065 unsigned int endaddr; 00066 struct symt_compiland* compiland; 00067 int linetab_offset; 00068 int linecnt; 00069 struct symt** entries; 00070 int neps; 00071 int neps_alloc; 00072 }; 00073 00074 struct CoffFileSet 00075 { 00076 struct CoffFile* files; 00077 int nfiles; 00078 int nfiles_alloc; 00079 }; 00080 00081 static const char* coff_get_name(const IMAGE_SYMBOL* coff_sym, 00082 const char* coff_strtab) 00083 { 00084 static char namebuff[9]; 00085 const char* nampnt; 00086 00087 if (coff_sym->N.Name.Short) 00088 { 00089 memcpy(namebuff, coff_sym->N.ShortName, 8); 00090 namebuff[8] = '\0'; 00091 nampnt = &namebuff[0]; 00092 } 00093 else 00094 { 00095 nampnt = coff_strtab + coff_sym->N.Name.Long; 00096 } 00097 00098 if (nampnt[0] == '_') nampnt++; 00099 return nampnt; 00100 } 00101 00102 static int coff_add_file(struct CoffFileSet* coff_files, struct module* module, 00103 const char* filename) 00104 { 00105 struct CoffFile* file; 00106 00107 if (coff_files->nfiles + 1 >= coff_files->nfiles_alloc) 00108 { 00109 if (coff_files->files) 00110 { 00111 coff_files->nfiles_alloc *= 2; 00112 coff_files->files = HeapReAlloc(GetProcessHeap(), 0, coff_files->files, 00113 coff_files->nfiles_alloc * sizeof(struct CoffFile)); 00114 } 00115 else 00116 { 00117 coff_files->nfiles_alloc = 16; 00118 coff_files->files = HeapAlloc(GetProcessHeap(), 0, 00119 coff_files->nfiles_alloc * sizeof(struct CoffFile)); 00120 } 00121 } 00122 file = coff_files->files + coff_files->nfiles; 00123 file->startaddr = 0xffffffff; 00124 file->endaddr = 0; 00125 file->compiland = symt_new_compiland(module, 0, 00126 source_new(module, NULL, filename)); 00127 file->linetab_offset = -1; 00128 file->linecnt = 0; 00129 file->entries = NULL; 00130 file->neps = file->neps_alloc = 0; 00131 00132 return coff_files->nfiles++; 00133 } 00134 00135 static void coff_add_symbol(struct CoffFile* coff_file, struct symt* sym) 00136 { 00137 if (coff_file->neps + 1 >= coff_file->neps_alloc) 00138 { 00139 if (coff_file->entries) 00140 { 00141 coff_file->neps_alloc *= 2; 00142 coff_file->entries = HeapReAlloc(GetProcessHeap(), 0, coff_file->entries, 00143 coff_file->neps_alloc * sizeof(struct symt*)); 00144 } 00145 else 00146 { 00147 coff_file->neps_alloc = 32; 00148 coff_file->entries = HeapAlloc(GetProcessHeap(), 0, 00149 coff_file->neps_alloc * sizeof(struct symt*)); 00150 } 00151 } 00152 coff_file->entries[coff_file->neps++] = sym; 00153 } 00154 00155 DECLSPEC_HIDDEN BOOL coff_process_info(const struct msc_debug_info* msc_dbg) 00156 { 00157 const IMAGE_AUX_SYMBOL* aux; 00158 const IMAGE_COFF_SYMBOLS_HEADER* coff; 00159 const IMAGE_LINENUMBER* coff_linetab; 00160 const IMAGE_LINENUMBER* linepnt; 00161 const char* coff_strtab; 00162 const IMAGE_SYMBOL* coff_sym; 00163 const IMAGE_SYMBOL* coff_symbols; 00164 struct CoffFileSet coff_files; 00165 int curr_file_idx = -1; 00166 unsigned int i; 00167 int j; 00168 int k; 00169 int l; 00170 int linetab_indx; 00171 const char* nampnt; 00172 int naux; 00173 BOOL ret = FALSE; 00174 ULONG64 addr; 00175 00176 TRACE("Processing COFF symbols...\n"); 00177 00178 assert(sizeof(IMAGE_SYMBOL) == IMAGE_SIZEOF_SYMBOL); 00179 assert(sizeof(IMAGE_LINENUMBER) == IMAGE_SIZEOF_LINENUMBER); 00180 00181 coff_files.files = NULL; 00182 coff_files.nfiles = coff_files.nfiles_alloc = 0; 00183 00184 coff = (const IMAGE_COFF_SYMBOLS_HEADER*)msc_dbg->root; 00185 00186 coff_symbols = (const IMAGE_SYMBOL*)((const char *)coff + coff->LvaToFirstSymbol); 00187 coff_linetab = (const IMAGE_LINENUMBER*)((const char *)coff + coff->LvaToFirstLinenumber); 00188 coff_strtab = (const char*)(coff_symbols + coff->NumberOfSymbols); 00189 00190 linetab_indx = 0; 00191 00192 for (i = 0; i < coff->NumberOfSymbols; i++) 00193 { 00194 coff_sym = coff_symbols + i; 00195 naux = coff_sym->NumberOfAuxSymbols; 00196 00197 if (coff_sym->StorageClass == IMAGE_SYM_CLASS_FILE) 00198 { 00199 curr_file_idx = coff_add_file(&coff_files, msc_dbg->module, 00200 (const char*)(coff_sym + 1)); 00201 TRACE("New file %s\n", (const char*)(coff_sym + 1)); 00202 i += naux; 00203 continue; 00204 } 00205 00206 if (curr_file_idx < 0) 00207 { 00208 assert(coff_files.nfiles == 0 && coff_files.nfiles_alloc == 0); 00209 curr_file_idx = coff_add_file(&coff_files, msc_dbg->module, "<none>"); 00210 TRACE("New file <none>\n"); 00211 } 00212 00213 /* 00214 * This guy marks the size and location of the text section 00215 * for the current file. We need to keep track of this so 00216 * we can figure out what file the different global functions 00217 * go with. 00218 */ 00219 if (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC && 00220 naux != 0 && coff_sym->Type == 0 && coff_sym->SectionNumber == 1) 00221 { 00222 aux = (const IMAGE_AUX_SYMBOL*) (coff_sym + 1); 00223 00224 if (coff_files.files[curr_file_idx].linetab_offset != -1) 00225 { 00226 /* 00227 * Save this so we can still get the old name. 00228 */ 00229 const char* fn; 00230 00231 fn = source_get(msc_dbg->module, 00232 coff_files.files[curr_file_idx].compiland->source); 00233 00234 TRACE("Duplicating sect from %s: %x %x %x %d %d\n", 00235 fn, aux->Section.Length, 00236 aux->Section.NumberOfRelocations, 00237 aux->Section.NumberOfLinenumbers, 00238 aux->Section.Number, aux->Section.Selection); 00239 TRACE("More sect %d %s %08x %d %d %d\n", 00240 coff_sym->SectionNumber, 00241 coff_get_name(coff_sym, coff_strtab), 00242 coff_sym->Value, coff_sym->Type, 00243 coff_sym->StorageClass, coff_sym->NumberOfAuxSymbols); 00244 00245 /* 00246 * Duplicate the file entry. We have no way to describe 00247 * multiple text sections in our current way of handling things. 00248 */ 00249 coff_add_file(&coff_files, msc_dbg->module, fn); 00250 } 00251 else 00252 { 00253 TRACE("New text sect from %s: %x %x %x %d %d\n", 00254 source_get(msc_dbg->module, coff_files.files[curr_file_idx].compiland->source), 00255 aux->Section.Length, 00256 aux->Section.NumberOfRelocations, 00257 aux->Section.NumberOfLinenumbers, 00258 aux->Section.Number, aux->Section.Selection); 00259 } 00260 00261 if (coff_files.files[curr_file_idx].startaddr > coff_sym->Value) 00262 { 00263 coff_files.files[curr_file_idx].startaddr = coff_sym->Value; 00264 } 00265 00266 if (coff_files.files[curr_file_idx].endaddr < coff_sym->Value + aux->Section.Length) 00267 { 00268 coff_files.files[curr_file_idx].endaddr = coff_sym->Value + aux->Section.Length; 00269 } 00270 00271 coff_files.files[curr_file_idx].linetab_offset = linetab_indx; 00272 coff_files.files[curr_file_idx].linecnt = aux->Section.NumberOfLinenumbers; 00273 linetab_indx += aux->Section.NumberOfLinenumbers; 00274 i += naux; 00275 continue; 00276 } 00277 00278 if (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC && naux == 0 && 00279 coff_sym->SectionNumber == 1) 00280 { 00281 DWORD base = msc_dbg->sectp[coff_sym->SectionNumber - 1].VirtualAddress; 00282 /* 00283 * This is a normal static function when naux == 0. 00284 * Just register it. The current file is the correct 00285 * one in this instance. 00286 */ 00287 nampnt = coff_get_name(coff_sym, coff_strtab); 00288 00289 TRACE("\tAdding static symbol %s\n", nampnt); 00290 00291 /* FIXME: was adding symbol to this_file ??? */ 00292 coff_add_symbol(&coff_files.files[curr_file_idx], 00293 &symt_new_function(msc_dbg->module, 00294 coff_files.files[curr_file_idx].compiland, 00295 nampnt, 00296 msc_dbg->module->module.BaseOfImage + base + coff_sym->Value, 00297 0 /* FIXME */, 00298 NULL /* FIXME */)->symt); 00299 i += naux; 00300 continue; 00301 } 00302 00303 if (coff_sym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL && 00304 ISFCN(coff_sym->Type) && coff_sym->SectionNumber > 0) 00305 { 00306 struct symt_compiland* compiland = NULL; 00307 DWORD base = msc_dbg->sectp[coff_sym->SectionNumber - 1].VirtualAddress; 00308 nampnt = coff_get_name(coff_sym, coff_strtab); 00309 00310 TRACE("%d: %s %s\n", 00311 i, wine_dbgstr_longlong(msc_dbg->module->module.BaseOfImage + base + coff_sym->Value), 00312 nampnt); 00313 TRACE("\tAdding global symbol %s (sect=%s)\n", 00314 nampnt, msc_dbg->sectp[coff_sym->SectionNumber - 1].Name); 00315 00316 /* 00317 * Now we need to figure out which file this guy belongs to. 00318 */ 00319 for (j = 0; j < coff_files.nfiles; j++) 00320 { 00321 if (coff_files.files[j].startaddr <= base + coff_sym->Value 00322 && coff_files.files[j].endaddr > base + coff_sym->Value) 00323 { 00324 compiland = coff_files.files[j].compiland; 00325 break; 00326 } 00327 } 00328 if (j < coff_files.nfiles) 00329 { 00330 coff_add_symbol(&coff_files.files[j], 00331 &symt_new_function(msc_dbg->module, compiland, nampnt, 00332 msc_dbg->module->module.BaseOfImage + base + coff_sym->Value, 00333 0 /* FIXME */, NULL /* FIXME */)->symt); 00334 } 00335 else 00336 { 00337 symt_new_function(msc_dbg->module, NULL, nampnt, 00338 msc_dbg->module->module.BaseOfImage + base + coff_sym->Value, 00339 0 /* FIXME */, NULL /* FIXME */); 00340 } 00341 i += naux; 00342 continue; 00343 } 00344 00345 if (coff_sym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL && 00346 coff_sym->SectionNumber > 0) 00347 { 00348 DWORD base = msc_dbg->sectp[coff_sym->SectionNumber - 1].VirtualAddress; 00349 struct location loc; 00350 00351 /* 00352 * Similar to above, but for the case of data symbols. 00353 * These aren't treated as entrypoints. 00354 */ 00355 nampnt = coff_get_name(coff_sym, coff_strtab); 00356 00357 TRACE("%d: %s %s\n", 00358 i, wine_dbgstr_longlong(msc_dbg->module->module.BaseOfImage + base + coff_sym->Value), 00359 nampnt); 00360 TRACE("\tAdding global data symbol %s\n", nampnt); 00361 00362 /* 00363 * Now we need to figure out which file this guy belongs to. 00364 */ 00365 loc.kind = loc_absolute; 00366 loc.reg = 0; 00367 loc.offset = msc_dbg->module->module.BaseOfImage + base + coff_sym->Value; 00368 symt_new_global_variable(msc_dbg->module, NULL, nampnt, TRUE /* FIXME */, 00369 loc, 0 /* FIXME */, NULL /* FIXME */); 00370 i += naux; 00371 continue; 00372 } 00373 00374 if (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC && naux == 0) 00375 { 00376 /* 00377 * Ignore these. They don't have anything to do with 00378 * reality. 00379 */ 00380 i += naux; 00381 continue; 00382 } 00383 00384 TRACE("Skipping unknown entry '%s' %d %d %d\n", 00385 coff_get_name(coff_sym, coff_strtab), 00386 coff_sym->StorageClass, coff_sym->SectionNumber, naux); 00387 00388 /* 00389 * For now, skip past the aux entries. 00390 */ 00391 i += naux; 00392 } 00393 00394 if (coff_files.files != NULL) 00395 { 00396 /* 00397 * OK, we now should have a list of files, and we should have a list 00398 * of entrypoints. We need to sort the entrypoints so that we are 00399 * able to tie the line numbers with the given functions within the 00400 * file. 00401 */ 00402 for (j = 0; j < coff_files.nfiles; j++) 00403 { 00404 if (coff_files.files[j].entries != NULL) 00405 { 00406 qsort(coff_files.files[j].entries, coff_files.files[j].neps, 00407 sizeof(struct symt*), symt_cmp_addr); 00408 } 00409 } 00410 00411 /* 00412 * Now pick apart the line number tables, and attach the entries 00413 * to the given functions. 00414 */ 00415 for (j = 0; j < coff_files.nfiles; j++) 00416 { 00417 l = 0; 00418 if (coff_files.files[j].neps != 0) 00419 { 00420 for (k = 0; k < coff_files.files[j].linecnt; k++) 00421 { 00422 linepnt = coff_linetab + coff_files.files[j].linetab_offset + k; 00423 /* 00424 * If we have spilled onto the next entrypoint, then 00425 * bump the counter.. 00426 */ 00427 for (;;) 00428 { 00429 if (l+1 >= coff_files.files[j].neps) break; 00430 symt_get_address(coff_files.files[j].entries[l+1], &addr); 00431 if (((msc_dbg->module->module.BaseOfImage + linepnt->Type.VirtualAddress) < addr)) 00432 break; 00433 l++; 00434 } 00435 00436 if (coff_files.files[j].entries[l+1]->tag == SymTagFunction) 00437 { 00438 /* 00439 * Add the line number. This is always relative to the 00440 * start of the function, so we need to subtract that offset 00441 * first. 00442 */ 00443 symt_get_address(coff_files.files[j].entries[l+1], &addr); 00444 symt_add_func_line(msc_dbg->module, (struct symt_function*)coff_files.files[j].entries[l+1], 00445 coff_files.files[j].compiland->source, linepnt->Linenumber, 00446 msc_dbg->module->module.BaseOfImage + linepnt->Type.VirtualAddress - addr); 00447 } 00448 } 00449 } 00450 } 00451 00452 for (j = 0; j < coff_files.nfiles; j++) 00453 { 00454 HeapFree(GetProcessHeap(), 0, coff_files.files[j].entries); 00455 } 00456 HeapFree(GetProcessHeap(), 0, coff_files.files); 00457 msc_dbg->module->module.SymType = SymCoff; 00458 /* FIXME: we could have a finer grain here */ 00459 msc_dbg->module->module.LineNumbers = TRUE; 00460 msc_dbg->module->module.GlobalSymbols = TRUE; 00461 msc_dbg->module->module.TypeInfo = FALSE; 00462 msc_dbg->module->module.SourceIndexed = TRUE; 00463 msc_dbg->module->module.Publics = TRUE; 00464 ret = TRUE; 00465 } 00466 00467 return ret; 00468 } Generated on Sun May 27 2012 04:23:19 for ReactOS by
1.7.6.1
|