ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

coff.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.