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

stabs.c
Go to the documentation of this file.
00001 /*
00002  * File stabs.c - read stabs information from the modules
00003  *
00004  * Copyright (C) 1996,      Eric Youngdale.
00005  *       1999-2005, Eric Pouech
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  *
00021  *
00022  * Maintenance Information
00023  * -----------------------
00024  *
00025  * For documentation on the stabs format see for example
00026  *   The "stabs" debug format
00027  *     by Julia Menapace, Jim Kingdon, David Mackenzie
00028  *     of Cygnus Support
00029  *     available (hopefully) from http://sources.redhat.com/gdb/onlinedocs
00030  */
00031 
00032 #include "config.h"
00033 #include "wine/port.h"
00034 
00035 #include <sys/types.h>
00036 #include <fcntl.h>
00037 #ifdef HAVE_SYS_STAT_H
00038 # include <sys/stat.h>
00039 #endif
00040 #ifdef HAVE_SYS_MMAN_H
00041 #include <sys/mman.h>
00042 #endif
00043 #include <limits.h>
00044 #include <stdlib.h>
00045 #include <string.h>
00046 #ifdef HAVE_UNISTD_H
00047 # include <unistd.h>
00048 #endif
00049 #include <stdio.h>
00050 #include <assert.h>
00051 #include <stdarg.h>
00052 
00053 #ifdef HAVE_MACH_O_NLIST_H
00054 # include <mach-o/nlist.h>
00055 #endif
00056 
00057 #include "windef.h"
00058 #include "winbase.h"
00059 #include "winnls.h"
00060 
00061 #include "dbghelp_private.h"
00062 
00063 #include "wine/debug.h"
00064 
00065 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_stabs);
00066 
00067 #define strtoull _strtoui64
00068 
00069 /* Masks for n_type field */
00070 #ifndef N_STAB
00071 #define N_STAB      0xe0
00072 #endif
00073 #ifndef N_TYPE
00074 #define N_TYPE      0x1e
00075 #endif
00076 #ifndef N_EXT
00077 #define N_EXT       0x01
00078 #endif
00079 
00080 /* Values for (n_type & N_TYPE) */
00081 #ifndef N_UNDF
00082 #define N_UNDF      0x00
00083 #endif
00084 #ifndef N_ABS
00085 #define N_ABS       0x02
00086 #endif
00087 
00088 #define N_GSYM      0x20
00089 #define N_FUN       0x24
00090 #define N_STSYM     0x26
00091 #define N_LCSYM     0x28
00092 #define N_MAIN      0x2a
00093 #define N_ROSYM     0x2c
00094 #define N_BNSYM     0x2e
00095 #define N_OPT       0x3c
00096 #define N_RSYM      0x40
00097 #define N_SLINE     0x44
00098 #define N_ENSYM     0x4e
00099 #define N_SO        0x64
00100 #define N_OSO       0x66
00101 #define N_LSYM      0x80
00102 #define N_BINCL     0x82
00103 #define N_SOL       0x84
00104 #define N_PSYM      0xa0
00105 #define N_EINCL     0xa2
00106 #define N_LBRAC     0xc0
00107 #define N_EXCL      0xc2
00108 #define N_RBRAC     0xe0
00109 
00110 struct stab_nlist
00111 {
00112     unsigned            n_strx;
00113     unsigned char       n_type;
00114     char                n_other;
00115     short               n_desc;
00116     unsigned            n_value;
00117 };
00118 
00119 static void stab_strcpy(char* dest, int sz, const char* source)
00120 {
00121     char*       ptr = dest;
00122     /*
00123      * A strcpy routine that stops when we hit the ':' character.
00124      * Faster than copying the whole thing, and then nuking the
00125      * ':'.
00126      * Takes also care of (valid) a::b constructs
00127      */
00128     while (*source != '\0')
00129     {
00130         if (source[0] != ':' && sz-- > 0) *ptr++ = *source++;
00131         else if (source[1] == ':' && (sz -= 2) > 0)
00132         {
00133             *ptr++ = *source++;
00134             *ptr++ = *source++;
00135         }
00136         else break;
00137     }
00138     *ptr-- = '\0';
00139     /* GCC emits, in some cases, a .<digit>+ suffix.
00140      * This is used for static variable inside functions, so
00141      * that we can have several such variables with same name in
00142      * the same compilation unit
00143      * We simply ignore that suffix when present (we also get rid
00144      * of it in ELF symtab parsing)
00145      */
00146     if (ptr >= dest && isdigit(*ptr))
00147     {
00148         while (ptr > dest && isdigit(*ptr)) ptr--;
00149         if (*ptr == '.') *ptr = '\0';
00150     }
00151     assert(sz > 0);
00152 }
00153 
00154 typedef struct
00155 {
00156    char*        name;
00157    unsigned long    value;
00158    struct symt**        vector;
00159    int          nrofentries;
00160 } include_def;
00161 
00162 #define MAX_INCLUDES    5120
00163 
00164 static include_def*             include_defs = NULL;
00165 static int                  num_include_def = 0;
00166 static int              num_alloc_include_def = 0;
00167 static int                      cu_include_stack[MAX_INCLUDES];
00168 static int              cu_include_stk_idx = 0;
00169 static struct symt**            cu_vector = NULL;
00170 static int              cu_nrofentries = 0;
00171 static struct symt_basic*       stabs_basic[36];
00172 
00173 static int stabs_new_include(const char* file, unsigned long val)
00174 {
00175     if (num_include_def == num_alloc_include_def)
00176     {
00177         if (!include_defs)
00178         {
00179             num_alloc_include_def = 256;
00180             include_defs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
00181                                      sizeof(include_defs[0]) * num_alloc_include_def);
00182         }
00183         else
00184         {
00185             num_alloc_include_def *= 2;
00186             include_defs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, include_defs,
00187                                        sizeof(include_defs[0]) * num_alloc_include_def);
00188         }
00189     }
00190     include_defs[num_include_def].name = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(file) + 1), file);
00191     include_defs[num_include_def].value = val;
00192     include_defs[num_include_def].vector = NULL;
00193     include_defs[num_include_def].nrofentries = 0;
00194 
00195     return num_include_def++;
00196 }
00197 
00198 static int stabs_find_include(const char* file, unsigned long val)
00199 {
00200     int     i;
00201 
00202     for (i = 0; i < num_include_def; i++)
00203     {
00204         if (val == include_defs[i].value &&
00205             strcmp(file, include_defs[i].name) == 0)
00206             return i;
00207     }
00208     return -1;
00209 }
00210 
00211 static int stabs_add_include(int idx)
00212 {
00213     if (idx < 0) return -1;
00214     cu_include_stk_idx++;
00215 
00216     /* if this happens, just bump MAX_INCLUDES */
00217     /* we could also handle this as another dynarray */
00218     assert(cu_include_stk_idx < MAX_INCLUDES);
00219     cu_include_stack[cu_include_stk_idx] = idx;
00220     return cu_include_stk_idx;
00221 }
00222 
00223 static void stabs_reset_includes(void)
00224 {
00225     /*
00226      * The struct symt:s that we would need to use are reset when
00227      * we start a new file. (at least the ones in filenr == 0)
00228      */
00229     cu_include_stk_idx = 0;/* keep 0 as index for the .c file itself */
00230     memset(cu_vector, 0, sizeof(cu_vector[0]) * cu_nrofentries);
00231 }
00232 
00233 static void stabs_free_includes(void)
00234 {
00235     int i;
00236 
00237     stabs_reset_includes();
00238     for (i = 0; i < num_include_def; i++)
00239     {
00240         HeapFree(GetProcessHeap(), 0, include_defs[i].name);
00241         HeapFree(GetProcessHeap(), 0, include_defs[i].vector);
00242     }
00243     HeapFree(GetProcessHeap(), 0, include_defs);
00244     include_defs = NULL;
00245     num_include_def = 0;
00246     num_alloc_include_def = 0;
00247     HeapFree(GetProcessHeap(), 0, cu_vector);
00248     cu_vector = NULL;
00249     cu_nrofentries = 0;
00250 }
00251 
00252 static struct symt** stabs_find_ref(long filenr, long subnr)
00253 {
00254     struct symt**       ret;
00255 
00256     /* FIXME: I could perhaps create a dummy include_def for each compilation
00257      * unit which would allow not to handle those two cases separately
00258      */
00259     if (filenr == 0)
00260     {
00261         if (cu_nrofentries <= subnr)
00262     {
00263             cu_nrofentries = max( cu_nrofentries * 2, subnr + 1 );
00264             if (!cu_vector)
00265                 cu_vector = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
00266                                       sizeof(cu_vector[0]) * cu_nrofentries);
00267             else
00268                 cu_vector = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
00269                                         cu_vector, sizeof(cu_vector[0]) * cu_nrofentries);
00270     }
00271         ret = &cu_vector[subnr];
00272     }
00273     else
00274     {
00275         include_def*    idef;
00276 
00277         assert(filenr <= cu_include_stk_idx);
00278         idef = &include_defs[cu_include_stack[filenr]];
00279 
00280         if (idef->nrofentries <= subnr)
00281     {
00282             idef->nrofentries = max( idef->nrofentries * 2, subnr + 1 );
00283             if (!idef->vector)
00284                 idef->vector = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
00285                                          sizeof(idef->vector[0]) * idef->nrofentries);
00286             else
00287                 idef->vector = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
00288                                            idef->vector, sizeof(idef->vector[0]) * idef->nrofentries);
00289     }
00290         ret = &idef->vector[subnr];
00291     }
00292     TRACE("(%ld,%ld) => %p (%p)\n", filenr, subnr, ret, *ret);
00293     return ret;
00294 }
00295 
00296 static struct symt** stabs_read_type_enum(const char** x)
00297 {
00298     long        filenr, subnr;
00299     const char* iter;
00300     char*       end;
00301 
00302     iter = *x;
00303     if (*iter == '(')
00304     {
00305         ++iter;                             /* '('   */
00306         filenr = strtol(iter, &end, 10);    /* <int> */
00307         iter = ++end;                       /* ','   */
00308         subnr = strtol(iter, &end, 10);     /* <int> */
00309         iter = ++end;                       /* ')'   */
00310     }
00311     else
00312     {
00313         filenr = 0;
00314         subnr = strtol(iter, &end, 10);     /* <int> */
00315         iter = end;
00316     }
00317     *x = iter;
00318     return stabs_find_ref(filenr, subnr);
00319 }
00320 
00321 #define PTS_DEBUG
00322 struct ParseTypedefData
00323 {
00324     const char*     ptr;
00325     char        buf[1024];
00326     int         idx;
00327     struct module*      module;
00328 #ifdef PTS_DEBUG
00329     struct PTS_Error 
00330     {
00331         const char*         ptr;
00332         unsigned            line;
00333     } errors[16];
00334     int                 err_idx;
00335 #endif
00336 };
00337 
00338 #ifdef PTS_DEBUG
00339 static void stabs_pts_push(struct ParseTypedefData* ptd, unsigned line)
00340 {
00341     assert(ptd->err_idx < sizeof(ptd->errors) / sizeof(ptd->errors[0]));
00342     ptd->errors[ptd->err_idx].line = line;
00343     ptd->errors[ptd->err_idx].ptr = ptd->ptr;
00344     ptd->err_idx++;
00345 }
00346 #define PTS_ABORTIF(ptd, t) do { if (t) { stabs_pts_push((ptd), __LINE__); return -1;} } while (0)
00347 #else
00348 #define PTS_ABORTIF(ptd, t) do { if (t) return -1; } while (0)
00349 #endif
00350 
00351 static int stabs_get_basic(struct ParseTypedefData* ptd, unsigned basic, struct symt** symt)
00352 {
00353     PTS_ABORTIF(ptd, basic >= sizeof(stabs_basic) / sizeof(stabs_basic[0]));
00354 
00355     if (!stabs_basic[basic])
00356     {
00357         switch (basic)
00358         {
00359         case  1: stabs_basic[basic] = symt_new_basic(ptd->module, btInt,     "int", 4); break;
00360         case  2: stabs_basic[basic] = symt_new_basic(ptd->module, btChar,    "char", 1); break;
00361         case  3: stabs_basic[basic] = symt_new_basic(ptd->module, btInt,     "short int", 2); break;
00362         case  4: stabs_basic[basic] = symt_new_basic(ptd->module, btInt,     "long int", 4); break;
00363         case  5: stabs_basic[basic] = symt_new_basic(ptd->module, btUInt,    "unsigned char", 1); break;
00364         case  6: stabs_basic[basic] = symt_new_basic(ptd->module, btInt,     "signed char", 1); break;
00365         case  7: stabs_basic[basic] = symt_new_basic(ptd->module, btUInt,    "unsigned short int", 2); break;
00366         case  8: stabs_basic[basic] = symt_new_basic(ptd->module, btUInt,    "unsigned int", 4); break;
00367         case  9: stabs_basic[basic] = symt_new_basic(ptd->module, btUInt,    "unsigned", 2); break;
00368         case 10: stabs_basic[basic] = symt_new_basic(ptd->module, btUInt,    "unsigned long int", 2); break;
00369         case 11: stabs_basic[basic] = symt_new_basic(ptd->module, btVoid,    "void", 0); break;
00370         case 12: stabs_basic[basic] = symt_new_basic(ptd->module, btFloat,   "float", 4); break;
00371         case 13: stabs_basic[basic] = symt_new_basic(ptd->module, btFloat,   "double", 8); break;
00372         case 14: stabs_basic[basic] = symt_new_basic(ptd->module, btFloat,   "long double", 12); break;
00373         case 15: stabs_basic[basic] = symt_new_basic(ptd->module, btInt,     "integer", 4); break;
00374         case 16: stabs_basic[basic] = symt_new_basic(ptd->module, btBool,    "bool", 1); break;
00375         /*    case 17: short real */
00376         /*    case 18: real */
00377         case 25: stabs_basic[basic] = symt_new_basic(ptd->module, btComplex, "float complex", 8); break;
00378         case 26: stabs_basic[basic] = symt_new_basic(ptd->module, btComplex, "double complex", 16); break;
00379         case 30: stabs_basic[basic] = symt_new_basic(ptd->module, btWChar,   "wchar_t", 2); break;
00380         case 31: stabs_basic[basic] = symt_new_basic(ptd->module, btInt,     "long long int", 8); break;
00381         case 32: stabs_basic[basic] = symt_new_basic(ptd->module, btUInt,    "long long unsigned", 8); break;
00382             /* starting at 35 are wine extensions (especially for R implementation) */
00383         case 35: stabs_basic[basic] = symt_new_basic(ptd->module, btComplex, "long double complex", 24); break;
00384         default: PTS_ABORTIF(ptd, 1);
00385         }
00386     }   
00387     *symt = &stabs_basic[basic]->symt;
00388     return 0;
00389 }
00390 
00391 static int stabs_pts_read_type_def(struct ParseTypedefData* ptd, 
00392                                    const char* typename, struct symt** dt);
00393 
00394 static int stabs_pts_read_id(struct ParseTypedefData* ptd)
00395 {
00396     const char*         first = ptd->ptr;
00397     unsigned int    template = 0;
00398     char                ch;
00399 
00400     while ((ch = *ptd->ptr++) != '\0')
00401     {
00402         switch (ch)
00403         {
00404         case ':':
00405             if (template == 0)
00406             {
00407                 unsigned int len = ptd->ptr - first - 1;
00408                 PTS_ABORTIF(ptd, len >= sizeof(ptd->buf) - ptd->idx);
00409                 memcpy(ptd->buf + ptd->idx, first, len);
00410                 ptd->buf[ptd->idx + len] = '\0';
00411                 ptd->idx += len + 1;
00412                 return 0;
00413             }
00414             break;
00415         case '<': template++; break;
00416         case '>': PTS_ABORTIF(ptd, template == 0); template--; break;
00417         }
00418     }
00419     return -1;
00420 }
00421 
00422 static int stabs_pts_read_number(struct ParseTypedefData* ptd, long* v)
00423 {
00424     char*   last;
00425 
00426     *v = strtol(ptd->ptr, &last, 10);
00427     PTS_ABORTIF(ptd, last == ptd->ptr);
00428     ptd->ptr = last;
00429     return 0;
00430 }
00431 
00432 static int stabs_pts_read_type_reference(struct ParseTypedefData* ptd,
00433                                          long* filenr, long* subnr)
00434 {
00435     if (*ptd->ptr == '(')
00436     {
00437     /* '(' <int> ',' <int> ')' */
00438     ptd->ptr++;
00439     PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, filenr) == -1);
00440     PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
00441     PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, subnr) == -1);
00442     PTS_ABORTIF(ptd, *ptd->ptr++ != ')');
00443     }
00444     else
00445     {
00446         *filenr = 0;
00447     PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, subnr) == -1);
00448     }
00449     return 0;
00450 }
00451 
00452 struct pts_range_value
00453 {
00454     ULONGLONG           val;
00455     int                 sign;
00456 };
00457 
00458 static int stabs_pts_read_range_value(struct ParseTypedefData* ptd, struct pts_range_value* prv)
00459 {
00460     char*   last;
00461 
00462     switch (*ptd->ptr)
00463     {
00464     case '0':
00465         while (*ptd->ptr == '0') ptd->ptr++;
00466         if (*ptd->ptr >= '1' && *ptd->ptr <= '7')
00467         {
00468             switch (ptd->ptr[1])
00469             {
00470             case '0': 
00471                 PTS_ABORTIF(ptd, ptd->ptr[0] != '1');
00472                 prv->sign = -1;
00473                 prv->val = 0;
00474                 while (isdigit(*ptd->ptr)) prv->val = (prv->val << 3) + *ptd->ptr++ - '0';
00475                 break;
00476             case '7':
00477                 prv->sign = 1;
00478                 prv->val = 0;
00479                 while (isdigit(*ptd->ptr)) prv->val = (prv->val << 3) + *ptd->ptr++ - '0';
00480                 break;
00481             default: PTS_ABORTIF(ptd, 1); break;
00482             }
00483         } else prv->sign = 0;
00484         break;
00485     case '-':
00486         prv->sign = -1;
00487         prv->val = strtoull(++ptd->ptr, &last, 10);
00488         ptd->ptr = last;
00489         break;
00490     case '+':
00491     default:    
00492         prv->sign = 1;
00493         prv->val = strtoull(ptd->ptr, &last, 10);
00494         ptd->ptr = last;
00495         break;
00496     }
00497     return 0;
00498 }
00499 
00500 static int stabs_pts_read_range(struct ParseTypedefData* ptd, const char* typename,
00501                                 struct symt** dt)
00502 {
00503     struct symt*                ref;
00504     struct pts_range_value      lo;
00505     struct pts_range_value      hi;
00506     unsigned                    size;
00507     enum BasicType              bt;
00508     int                         i;
00509     ULONGLONG                   v;
00510 
00511     /* type ';' <int> ';' <int> ';' */
00512     PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &ref) == -1);
00513     PTS_ABORTIF(ptd, *ptd->ptr++ != ';');   /* ';' */
00514     PTS_ABORTIF(ptd, stabs_pts_read_range_value(ptd, &lo) == -1);
00515     PTS_ABORTIF(ptd, *ptd->ptr++ != ';');   /* ';' */
00516     PTS_ABORTIF(ptd, stabs_pts_read_range_value(ptd, &hi) == -1);
00517     PTS_ABORTIF(ptd, *ptd->ptr++ != ';');   /* ';' */
00518 
00519     /* basically, we don't use ref... in some cases, for example, float is declared
00520      * as a derived type of int... which won't help us... so we guess the types
00521      * from the various formats
00522      */
00523     if (lo.sign == 0 && hi.sign < 0)
00524     {
00525         bt = btUInt;
00526         size = hi.val;
00527     }
00528     else if (lo.sign < 0 && hi.sign == 0)
00529     {
00530         bt = btUInt;
00531         size = lo.val;
00532     }
00533     else if (lo.sign > 0 && hi.sign == 0)
00534     {
00535         bt = btFloat;
00536         size = lo.val;
00537     }
00538     else if (lo.sign < 0 && hi.sign > 0)
00539     {
00540         v = 1 << 7;
00541         for (i = 7; i < 64; i += 8)
00542         {
00543             if (lo.val == v && hi.val == v - 1)
00544             {
00545                 bt = btInt;
00546                 size = (i + 1) / 8;
00547                 break;
00548             }
00549             v <<= 8;
00550         }
00551         PTS_ABORTIF(ptd, i >= 64);
00552     }
00553     else if (lo.sign == 0 && hi.sign > 0)
00554     {
00555         if (hi.val == 127) /* specific case for char... */
00556         {
00557             bt = btChar;
00558             size = 1;
00559         }
00560         else
00561         {
00562             v = 1;
00563             for (i = 8; i <= 64; i += 8)
00564             {
00565                 v <<= 8;
00566                 if (hi.val + 1 == v)
00567                 {
00568                     bt = btUInt;
00569                     size = (i + 1) / 8;
00570                     break;
00571                 }
00572             }
00573             PTS_ABORTIF(ptd, i > 64);
00574         }
00575     }
00576     else PTS_ABORTIF(ptd, 1);
00577 
00578     *dt = &symt_new_basic(ptd->module, bt, typename, size)->symt;
00579     return 0;
00580 }
00581 
00582 static inline int stabs_pts_read_method_info(struct ParseTypedefData* ptd)
00583 {
00584     struct symt*        dt;
00585     const char*         tmp;
00586     char                mthd;
00587 
00588     do
00589     {
00590         /* get type of return value */
00591         PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &dt) == -1);
00592         if (*ptd->ptr == ';') ptd->ptr++;
00593 
00594         /* get types of parameters */
00595         if (*ptd->ptr == ':')
00596         {
00597             PTS_ABORTIF(ptd, !(tmp = strchr(ptd->ptr + 1, ';')));
00598             ptd->ptr = tmp + 1;
00599         }
00600         PTS_ABORTIF(ptd, !(*ptd->ptr >= '0' && *ptd->ptr <= '9'));
00601         ptd->ptr++;
00602         PTS_ABORTIF(ptd, !(ptd->ptr[0] >= 'A' && *ptd->ptr <= 'D'));
00603         mthd = *++ptd->ptr;
00604         PTS_ABORTIF(ptd, mthd != '.' && mthd != '?' && mthd != '*');
00605         ptd->ptr++;
00606         if (mthd == '*')
00607         {
00608             long int            ofs;
00609             struct symt*        dt;
00610 
00611             PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &ofs) == -1);
00612             PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
00613             PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &dt) == -1);
00614             PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
00615         }
00616     } while (*ptd->ptr != ';');
00617     ptd->ptr++;
00618 
00619     return 0;
00620 }
00621 
00622 static inline int stabs_pts_read_aggregate(struct ParseTypedefData* ptd, 
00623                                            struct symt_udt* sdt)
00624 {
00625     long            sz, ofs;
00626     struct symt*        adt;
00627     struct symt*        dt = NULL;
00628     int         idx;
00629     int         doadd;
00630 
00631     PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &sz) == -1);
00632 
00633     doadd = symt_set_udt_size(ptd->module, sdt, sz);
00634     if (*ptd->ptr == '!') /* C++ inheritence */
00635     {
00636         long     num_classes;
00637 
00638         ptd->ptr++;
00639         PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &num_classes) == -1);
00640         PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
00641         while (--num_classes >= 0)
00642         {
00643             ptd->ptr += 2; /* skip visibility and inheritence */
00644             PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &ofs) == -1);
00645             PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
00646 
00647             PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &adt) == -1);
00648 
00649             if (doadd && adt)
00650             {
00651                 char    tmp[256];
00652                 DWORD64 size;
00653 
00654                 strcpy(tmp, "__inherited_class_");
00655                 strcat(tmp, symt_get_name(adt));
00656 
00657                 /* FIXME: TI_GET_LENGTH will not always work, especially when adt
00658                  * has just been seen as a forward definition and not the real stuff
00659                  * yet.
00660                  * As we don't use much the size of members in structs, this may not
00661                  * be much of a problem
00662                  */
00663                 symt_get_info(ptd->module, adt, TI_GET_LENGTH, &size);
00664                 symt_add_udt_element(ptd->module, sdt, tmp, adt, ofs, (DWORD)size * 8);
00665             }
00666             PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
00667         }
00668         
00669     }
00670     /* if the structure has already been filled, just redo the parsing
00671      * but don't store results into the struct
00672      * FIXME: there's a quite ugly memory leak in there...
00673      */
00674 
00675     /* Now parse the individual elements of the structure/union. */
00676     while (*ptd->ptr != ';') 
00677     {
00678     /* agg_name : type ',' <int:offset> ',' <int:size> */
00679     idx = ptd->idx;
00680 
00681         if (ptd->ptr[0] == '$' && ptd->ptr[1] == 'v')
00682         {
00683             long        x;
00684 
00685             if (ptd->ptr[2] == 'f')
00686             {
00687                 /* C++ virtual method table */
00688                 ptd->ptr += 3;
00689                 stabs_read_type_enum(&ptd->ptr);
00690                 PTS_ABORTIF(ptd, *ptd->ptr++ != ':');
00691                 PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &dt) == -1);
00692                 PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
00693                 PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &x) == -1);
00694                 PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
00695                 ptd->idx = idx;
00696                 continue;
00697             }
00698             else if (ptd->ptr[2] == 'b')
00699             {
00700                 ptd->ptr += 3;
00701                 PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &dt) == -1);
00702                 PTS_ABORTIF(ptd, *ptd->ptr++ != ':');
00703                 PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &dt) == -1);
00704                 PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
00705                 PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &x) == -1);
00706                 PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
00707                 ptd->idx = idx;
00708                 continue;
00709             }
00710         }
00711 
00712     PTS_ABORTIF(ptd, stabs_pts_read_id(ptd) == -1);
00713         /* Ref. TSDF R2.130 Section 7.4.  When the field name is a method name
00714          * it is followed by two colons rather than one.
00715          */
00716         if (*ptd->ptr == ':')
00717         {
00718             ptd->ptr++; 
00719             stabs_pts_read_method_info(ptd);
00720             ptd->idx = idx;
00721             continue;
00722         }
00723         else
00724         {
00725             /* skip C++ member protection /0 /1 or /2 */
00726             if (*ptd->ptr == '/') ptd->ptr += 2;
00727         }
00728     PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &adt) == -1);
00729 
00730         switch (*ptd->ptr++)
00731         {
00732         case ',':
00733             PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &ofs) == -1);
00734             PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
00735             PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &sz) == -1);
00736             PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
00737 
00738             if (doadd) symt_add_udt_element(ptd->module, sdt, ptd->buf + idx, adt, ofs, sz);
00739             break;
00740         case ':':
00741             {
00742                 const char* tmp;
00743                 /* method parameters... terminated by ';' */
00744                 PTS_ABORTIF(ptd, !(tmp = strchr(ptd->ptr, ';')));
00745                 ptd->ptr = tmp + 1;
00746             }
00747             break;
00748         default:
00749             PTS_ABORTIF(ptd, TRUE);
00750         }
00751     ptd->idx = idx;
00752     }
00753     PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
00754     if (*ptd->ptr == '~')
00755     {
00756         ptd->ptr++;
00757         PTS_ABORTIF(ptd, *ptd->ptr++ != '%');
00758         PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &dt) == -1);
00759         PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
00760     }
00761     return 0;
00762 }
00763 
00764 static inline int stabs_pts_read_enum(struct ParseTypedefData* ptd, 
00765                                       struct symt_enum* edt)
00766 {
00767     long        value;
00768     int     idx;
00769 
00770     while (*ptd->ptr != ';')
00771     {
00772     idx = ptd->idx;
00773     PTS_ABORTIF(ptd, stabs_pts_read_id(ptd) == -1);
00774     PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &value) == -1);
00775     PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
00776     symt_add_enum_element(ptd->module, edt, ptd->buf + idx, value);
00777     ptd->idx = idx;
00778     }
00779     ptd->ptr++;
00780     return 0;
00781 }
00782 
00783 static inline int stabs_pts_read_array(struct ParseTypedefData* ptd,
00784                                        struct symt** adt)
00785 {
00786     long                lo, hi;
00787     struct symt*        range_dt;
00788     struct symt*        base_dt;
00789 
00790     /* ar<typeinfo_nodef>;<int>;<int>;<typeinfo> */
00791 
00792     PTS_ABORTIF(ptd, *ptd->ptr++ != 'r');
00793 
00794     PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &range_dt) == -1);
00795     PTS_ABORTIF(ptd, *ptd->ptr++ != ';');   /* ';' */
00796     PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &lo) == -1);
00797     PTS_ABORTIF(ptd, *ptd->ptr++ != ';');   /* ';' */
00798     PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &hi) == -1);
00799     PTS_ABORTIF(ptd, *ptd->ptr++ != ';');   /* ';' */
00800 
00801     PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &base_dt) == -1);
00802 
00803     *adt = &symt_new_array(ptd->module, lo, hi, base_dt, range_dt)->symt;
00804     return 0;
00805 }
00806 
00807 static int stabs_pts_read_type_def(struct ParseTypedefData* ptd, const char* typename,
00808                                    struct symt** ret_dt)
00809 {
00810     int         idx;
00811     long        sz = -1;
00812     struct symt*    new_dt = NULL;     /* newly created data type */
00813     struct symt*    ref_dt;        /* referenced data type (pointer...) */
00814     long        filenr1, subnr1, tmp;
00815 
00816     /* things are a bit complicated because of the way the typedefs are stored inside
00817      * the file, because addresses can change when realloc is done, so we must call
00818      * over and over stabs_find_ref() to keep the correct values around
00819      */
00820     PTS_ABORTIF(ptd, stabs_pts_read_type_reference(ptd, &filenr1, &subnr1) == -1);
00821 
00822     while (*ptd->ptr == '=')
00823     {
00824     ptd->ptr++;
00825     PTS_ABORTIF(ptd, new_dt != NULL);
00826 
00827     /* first handle attribute if any */
00828     switch (*ptd->ptr)      
00829         {
00830     case '@':
00831         if (*++ptd->ptr == 's')
00832             {
00833         ptd->ptr++;
00834         if (stabs_pts_read_number(ptd, &sz) == -1)
00835                 {
00836             ERR("Not an attribute... NIY\n");
00837             ptd->ptr -= 2;
00838             return -1;
00839         }
00840         PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
00841         }
00842         break;
00843     }
00844     /* then the real definitions */
00845     switch (*ptd->ptr++)
00846         {
00847     case '*':
00848         case '&':
00849         PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &ref_dt) == -1);
00850         new_dt = &symt_new_pointer(ptd->module, ref_dt, sizeof(void*))->symt;
00851            break;
00852         case 'k': /* 'const' modifier */
00853         case 'B': /* 'volatile' modifier */
00854             /* just kinda ignore the modifier, I guess -gmt */
00855             PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, typename, &new_dt) == -1);
00856         break;
00857     case '(':
00858         ptd->ptr--;
00859             PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, typename, &new_dt) == -1);
00860         break;
00861     case 'a':
00862         PTS_ABORTIF(ptd, stabs_pts_read_array(ptd, &new_dt) == -1);
00863         break;
00864     case 'r':
00865         PTS_ABORTIF(ptd, stabs_pts_read_range(ptd, typename, &new_dt) == -1);
00866         assert(!*stabs_find_ref(filenr1, subnr1));
00867         *stabs_find_ref(filenr1, subnr1) = new_dt;
00868         break;
00869     case 'f':
00870         PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &ref_dt) == -1);
00871         new_dt = &symt_new_function_signature(ptd->module, ref_dt, -1)->symt;
00872         break;
00873     case 'e':
00874             stabs_get_basic(ptd, 1 /* int */, &ref_dt);
00875             new_dt = &symt_new_enum(ptd->module, typename, ref_dt)->symt;
00876         PTS_ABORTIF(ptd, stabs_pts_read_enum(ptd, (struct symt_enum*)new_dt) == -1);
00877         break;
00878     case 's':
00879     case 'u':
00880             {
00881                 struct symt_udt*    udt;
00882                 enum UdtKind kind = (ptd->ptr[-1] == 's') ? UdtStruct : UdtUnion;
00883                 /* udt can have been already defined in a forward definition */
00884                 udt = (struct symt_udt*)*stabs_find_ref(filenr1, subnr1);
00885                 if (!udt)
00886                 {
00887                     udt = symt_new_udt(ptd->module, typename, 0, kind);
00888                     /* we need to set it here, because a struct can hold a pointer
00889                      * to itself
00890                      */
00891                     new_dt = *stabs_find_ref(filenr1, subnr1) = &udt->symt;
00892                 }
00893                 else
00894                 {
00895                     unsigned l1, l2;
00896                     if (udt->symt.tag != SymTagUDT)
00897                     {
00898                         ERR("Forward declaration (%p/%s) is not an aggregate (%u)\n",
00899                             udt, symt_get_name(&udt->symt), udt->symt.tag);
00900                         return -1;
00901                     }
00902                     /* FIXME: we currently don't correctly construct nested C++
00903                      * classes names. Therefore, we could be here with either:
00904                      * - typename and udt->hash_elt.name being the same string
00905                      *   (non embedded case)
00906                      * - typename being foo::bar while udt->hash_elt.name being 
00907                      *   just bar
00908                      * So, we twist the comparison to test both occurrences. When
00909                      * we have proper C++ types in this file, this twist has to be
00910                      * removed
00911                      */
00912                     l1 = strlen(udt->hash_elt.name);
00913                     l2 = strlen(typename);
00914                     if (l1 > l2 || strcmp(udt->hash_elt.name, typename + l2 - l1))
00915                         ERR("Forward declaration name mismatch %s <> %s\n",
00916                             udt->hash_elt.name, typename);
00917                     new_dt = &udt->symt;
00918                 }
00919                 PTS_ABORTIF(ptd, stabs_pts_read_aggregate(ptd, udt) == -1);
00920         }
00921         break;
00922     case 'x':
00923         idx = ptd->idx;
00924             tmp = *ptd->ptr++;
00925         PTS_ABORTIF(ptd, stabs_pts_read_id(ptd) == -1);
00926         switch (tmp)
00927             {
00928         case 'e':
00929                 stabs_get_basic(ptd, 1 /* int */, &ref_dt);
00930                 new_dt = &symt_new_enum(ptd->module, ptd->buf + idx, ref_dt)->symt;
00931                 break;
00932         case 's':
00933                 new_dt = &symt_new_udt(ptd->module, ptd->buf + idx, 0, UdtStruct)->symt;
00934             break;
00935             case 'u':
00936                 new_dt = &symt_new_udt(ptd->module, ptd->buf + idx, 0, UdtUnion)->symt;
00937             break;
00938         default:
00939                 return -1;
00940         }
00941         ptd->idx = idx;
00942         break;
00943     case '-':
00944             {
00945                 PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &tmp) == -1);
00946                 PTS_ABORTIF(ptd, stabs_get_basic(ptd, tmp, &new_dt) == -1);
00947                 PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
00948             }
00949         break;
00950         case '#':
00951             if (*ptd->ptr == '#')
00952             {
00953                 ptd->ptr++;
00954                 PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &ref_dt) == -1);
00955                 new_dt = &symt_new_function_signature(ptd->module, ref_dt, -1)->symt;
00956             }
00957             else
00958             {
00959                 struct symt*    cls_dt;
00960                 struct symt*    pmt_dt;
00961 
00962                 PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &cls_dt) == -1);
00963                 PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
00964                 PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &ref_dt) == -1);
00965                 new_dt = &symt_new_function_signature(ptd->module, ref_dt, -1)->symt;
00966                 while (*ptd->ptr == ',')
00967                 {
00968                     ptd->ptr++;
00969                     PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &pmt_dt) == -1);
00970                 }
00971             }
00972             break;
00973         case 'R':
00974             {
00975                 long    type, len, unk;
00976                 int     basic;
00977                 
00978                 PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &type) == -1);
00979                 PTS_ABORTIF(ptd, *ptd->ptr++ != ';');   /* ';' */
00980                 PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &len) == -1);
00981                 PTS_ABORTIF(ptd, *ptd->ptr++ != ';');   /* ';' */
00982                 PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &unk) == -1);
00983                 PTS_ABORTIF(ptd, *ptd->ptr++ != ';');   /* ';' */
00984 
00985                 switch (type) /* see stabs_get_basic for the details */
00986                 {
00987                 case 1: basic = 12; break;
00988                 case 2: basic = 13; break;
00989                 case 3: basic = 25; break;
00990                 case 4: basic = 26; break;
00991                 case 5: basic = 35; break;
00992                 case 6: basic = 14; break;
00993                 default: PTS_ABORTIF(ptd, 1);
00994                 }
00995                 PTS_ABORTIF(ptd, stabs_get_basic(ptd, basic, &new_dt) == -1);
00996             }
00997             break;
00998     default:
00999         ERR("Unknown type '%c'\n", ptd->ptr[-1]);
01000         return -1;
01001     }
01002     }
01003 
01004     if (!new_dt)
01005     {
01006         /* is it a forward declaration that has been filled ? */
01007     new_dt = *stabs_find_ref(filenr1, subnr1);
01008         /* if not, this should be void (which is defined as a ref to itself, but we
01009          * don't correctly catch it)
01010          */
01011         if (!new_dt && typename)
01012         {
01013             new_dt = &symt_new_basic(ptd->module, btVoid, typename, 0)->symt;
01014             PTS_ABORTIF(ptd, strcmp(typename, "void"));
01015         }
01016     }            
01017 
01018     *stabs_find_ref(filenr1, subnr1) = *ret_dt = new_dt;
01019 
01020     TRACE("Adding (%ld,%ld) %s\n", filenr1, subnr1, debugstr_a(typename));
01021 
01022     return 0;
01023 }
01024 
01025 static int stabs_parse_typedef(struct module* module, const char* ptr, 
01026                                const char* typename)
01027 {
01028     struct ParseTypedefData ptd;
01029     struct symt*                dt;
01030     int             ret = -1;
01031 
01032     /* check for already existing definition */
01033 
01034     TRACE("%s => %s\n", typename, debugstr_a(ptr));
01035     ptd.module = module;
01036     ptd.idx = 0;
01037 #ifdef PTS_DEBUG
01038     ptd.err_idx = 0;
01039 #endif
01040     for (ptd.ptr = ptr - 1; ;)
01041     {
01042         ptd.ptr = strchr(ptd.ptr + 1, ':');
01043         if (ptd.ptr == NULL || *++ptd.ptr != ':') break;
01044     }
01045     if (ptd.ptr)
01046     {
01047     if (*ptd.ptr != '(') ptd.ptr++;
01048         /* most of type definitions take one char, except Tt */
01049     if (*ptd.ptr != '(') ptd.ptr++;
01050     ret = stabs_pts_read_type_def(&ptd, typename, &dt);
01051     }
01052 
01053     if (ret == -1 || *ptd.ptr) 
01054     {
01055 #ifdef PTS_DEBUG
01056         int     i;
01057     TRACE("Failure on %s\n", debugstr_a(ptr));
01058         if (ret == -1)
01059         {
01060             for (i = 0; i < ptd.err_idx; i++)
01061             {
01062                 TRACE("[%d]: line %d => %s\n", 
01063                       i, ptd.errors[i].line, debugstr_a(ptd.errors[i].ptr));
01064             }
01065         }
01066         else
01067             TRACE("[0]: => %s\n", debugstr_a(ptd.ptr));
01068             
01069 #else
01070     ERR("Failure on %s at %s\n", debugstr_a(ptr), debugstr_a(ptd.ptr));
01071 #endif
01072     return FALSE;
01073     }
01074 
01075     return TRUE;
01076 }
01077 
01078 static struct symt* stabs_parse_type(const char* stab)
01079 {
01080     const char* c = stab - 1;
01081 
01082     /*
01083      * Look through the stab definition, and figure out what struct symt
01084      * this represents.  If we have something we know about, assign the
01085      * type.
01086      * According to "The \"stabs\" debug format" (Rev 2.130) the name may be
01087      * a C++ name and contain double colons e.g. foo::bar::baz:t5=*6.
01088      */
01089     do
01090     {
01091         if ((c = strchr(c + 1, ':')) == NULL) return NULL;
01092     } while (*++c == ':');
01093 
01094     /*
01095      * The next characters say more about the type (i.e. data, function, etc)
01096      * of symbol.  Skip them.  (C++ for example may have Tt).
01097      * Actually this is a very weak description; I think Tt is the only
01098      * multiple combination we should see.
01099      */
01100     while (*c && *c != '(' && !isdigit(*c))
01101         c++;
01102     /*
01103      * The next is either an integer or a (integer,integer).
01104      * The stabs_read_type_enum() takes care that stab_types is large enough.
01105      */
01106     return *stabs_read_type_enum(&c);
01107 }
01108 
01109 enum pending_obj_kind
01110 {
01111     PENDING_VAR,
01112     PENDING_LINE,
01113 };
01114 
01115 struct pending_loc_var
01116 {
01117     char                name[256];
01118     struct symt*        type;
01119     enum DataKind       kind;
01120     struct location     loc;
01121 };
01122 
01123 struct pending_line
01124 {
01125     int                 source_idx;
01126     int                 line_num;
01127     unsigned long       offset;
01128     unsigned long       load_offset;
01129 };
01130 
01131 struct pending_object
01132 {
01133     enum pending_obj_kind               tag;
01134     union {
01135         struct pending_loc_var  var;
01136         struct pending_line     line;
01137     }                                   u;
01138 };
01139 
01140 struct pending_list
01141 {
01142     struct pending_object*      objs;
01143     unsigned                    num;
01144     unsigned                    allocated;
01145 };
01146 
01147 static inline void pending_make_room(struct pending_list* pending)
01148 {
01149     if (pending->num == pending->allocated)
01150     {
01151         if (!pending->objs)
01152         {
01153             pending->allocated = 8;
01154             pending->objs = HeapAlloc(GetProcessHeap(), 0,
01155                                      pending->allocated * sizeof(pending->objs[0]));
01156         }
01157         else
01158         {
01159             pending->allocated *= 2;
01160             pending->objs = HeapReAlloc(GetProcessHeap(), 0, pending->objs,
01161                                        pending->allocated * sizeof(pending->objs[0]));
01162         }
01163     }
01164 }
01165 
01166 static inline void pending_add_var(struct pending_list* pending, const char* name,
01167                                    enum DataKind dt, const struct location* loc)
01168 {
01169     pending_make_room(pending);
01170     pending->objs[pending->num].tag = PENDING_VAR;
01171     stab_strcpy(pending->objs[pending->num].u.var.name,
01172                 sizeof(pending->objs[pending->num].u.var.name), name);
01173     pending->objs[pending->num].u.var.type  = stabs_parse_type(name);
01174     pending->objs[pending->num].u.var.kind  = dt;
01175     pending->objs[pending->num].u.var.loc   = *loc;
01176     pending->num++;
01177 }
01178 
01179 static inline void pending_add_line(struct pending_list* pending, int source_idx,
01180                                     int line_num, unsigned long offset,
01181                                     unsigned long load_offset)
01182 {
01183     pending_make_room(pending);
01184     pending->objs[pending->num].tag = PENDING_LINE;
01185     pending->objs[pending->num].u.line.source_idx   = source_idx;
01186     pending->objs[pending->num].u.line.line_num     = line_num;
01187     pending->objs[pending->num].u.line.offset       = offset;
01188     pending->objs[pending->num].u.line.load_offset  = load_offset;
01189     pending->num++;
01190 }
01191 
01192 static void pending_flush(struct pending_list* pending, struct module* module,
01193                           struct symt_function* func, struct symt_block* block)
01194 {
01195     unsigned int i;
01196 
01197     for (i = 0; i < pending->num; i++)
01198     {
01199         switch (pending->objs[i].tag)
01200         {
01201         case PENDING_VAR:
01202             symt_add_func_local(module, func,
01203                                 pending->objs[i].u.var.kind, &pending->objs[i].u.var.loc,
01204                                 block, pending->objs[i].u.var.type, pending->objs[i].u.var.name);
01205             break;
01206         case PENDING_LINE:
01207             if (module->type == DMT_MACHO)
01208                 pending->objs[i].u.line.offset -= func->address - pending->objs[i].u.line.load_offset;
01209             symt_add_func_line(module, func, pending->objs[i].u.line.source_idx,
01210                                pending->objs[i].u.line.line_num, pending->objs[i].u.line.offset);
01211             break;
01212         default:
01213             ERR("Unknown pending object tag %u\n", (unsigned)pending->objs[i].tag);
01214             break;
01215         }
01216     }
01217     pending->num = 0;
01218 }
01219 
01220 /******************************************************************
01221  *      stabs_finalize_function
01222  *
01223  * Ends function creation: mainly:
01224  * - cleans up line number information
01225  * - tries to set up a debug-start tag (FIXME: heuristic to be enhanced)
01226  * - for stabs which have absolute address in them, initializes the size of the
01227  *   function (assuming that current function ends where next function starts)
01228  */
01229 static void stabs_finalize_function(struct module* module, struct symt_function* func,
01230                                     unsigned long size)
01231 {
01232     IMAGEHLP_LINE64     il;
01233     struct location     loc;
01234 
01235     if (!func) return;
01236     symt_normalize_function(module, func);
01237     /* To define the debug-start of the function, we use the second line number.
01238      * Not 100% bullet proof, but better than nothing
01239      */
01240     if (symt_fill_func_line_info(module, func, func->address, &il) &&
01241         symt_get_func_line_next(module, &il))
01242     {
01243         loc.kind = loc_absolute;
01244         loc.offset = il.Address - func->address;
01245         symt_add_function_point(module, func, SymTagFuncDebugStart, 
01246                                 &loc, NULL);
01247     }
01248     if (size) func->size = size;
01249 }
01250 
01251 static inline void stabbuf_append(char **buf, unsigned *buf_size, const char *str)
01252 {
01253     unsigned str_len, buf_len;
01254 
01255     str_len = strlen(str);
01256     buf_len = strlen(*buf);
01257 
01258     if(str_len+buf_len >= *buf_size) {
01259         *buf_size += buf_len + str_len;
01260         *buf = HeapReAlloc(GetProcessHeap(), 0, *buf, *buf_size);
01261     }
01262 
01263     strcpy(*buf+buf_len, str);
01264 }
01265 
01266 BOOL stabs_parse(struct module* module, unsigned long load_offset, 
01267                  const void* pv_stab_ptr, int stablen,
01268                  const char* strs, int strtablen,
01269                  stabs_def_cb callback, void* user)
01270 {
01271     struct symt_function*       curr_func = NULL;
01272     struct symt_block*          block = NULL;
01273     struct symt_compiland*      compiland = NULL;
01274     char*                       srcpath = NULL;
01275     int                         i;
01276     int                         nstab;
01277     const char*                 ptr;
01278     char*                       stabbuff;
01279     unsigned int                stabbufflen;
01280     const struct stab_nlist*    stab_ptr = pv_stab_ptr;
01281     const char*                 strs_end;
01282     int                         strtabinc;
01283     char                        symname[4096];
01284     unsigned                    incl[32];
01285     int                         incl_stk = -1;
01286     int                         source_idx = -1;
01287     struct pending_list         pending_block;
01288     struct pending_list         pending_func;
01289     BOOL                        ret = TRUE;
01290     struct location             loc;
01291     unsigned char               type;
01292 
01293     nstab = stablen / sizeof(struct stab_nlist);
01294     strs_end = strs + strtablen;
01295 
01296     memset(stabs_basic, 0, sizeof(stabs_basic));
01297     memset(&pending_block, 0, sizeof(pending_block));
01298     memset(&pending_func, 0, sizeof(pending_func));
01299 
01300     /*
01301      * Allocate a buffer into which we can build stab strings for cases
01302      * where the stab is continued over multiple lines.
01303      */
01304     stabbufflen = 65536;
01305     stabbuff = HeapAlloc(GetProcessHeap(), 0, stabbufflen);
01306 
01307     strtabinc = 0;
01308     stabbuff[0] = '\0';
01309     for (i = 0; i < nstab; i++, stab_ptr++)
01310     {
01311         ptr = strs + stab_ptr->n_strx;
01312         if ((ptr > strs_end) || (ptr + strlen(ptr) > strs_end))
01313         {
01314             WARN("Bad stabs string %p\n", ptr);
01315             continue;
01316         }
01317         if (*ptr != '\0' && (ptr[strlen(ptr) - 1] == '\\'))
01318         {
01319             /*
01320              * Indicates continuation.  Append this to the buffer, and go onto the
01321              * next record.  Repeat the process until we find a stab without the
01322              * '/' character, as this indicates we have the whole thing.
01323              */
01324             stabbuf_append(&stabbuff, &stabbufflen, ptr);
01325             continue;
01326         }
01327         else if (stabbuff[0] != '\0')
01328         {
01329             stabbuf_append(&stabbuff, &stabbufflen, ptr);
01330             ptr = stabbuff;
01331         }
01332 
01333         if (stab_ptr->n_type & N_STAB)
01334             type = stab_ptr->n_type;
01335         else
01336             type = (stab_ptr->n_type & N_TYPE);
01337 
01338         /* only symbol entries contain a typedef */
01339         switch (type)
01340         {
01341         case N_GSYM:
01342         case N_LCSYM:
01343         case N_STSYM:
01344         case N_RSYM:
01345         case N_LSYM:
01346         case N_ROSYM:
01347         case N_PSYM:
01348             if (strchr(ptr, '=') != NULL)
01349             {
01350                 /*
01351                  * The stabs aren't in writable memory, so copy it over so we are
01352                  * sure we can scribble on it.
01353                  */
01354                 if (ptr != stabbuff)
01355                 {
01356                     stabbuff[0] = 0;
01357                     stabbuf_append(&stabbuff, &stabbufflen, ptr);
01358                     ptr = stabbuff;
01359                 }
01360                 stab_strcpy(symname, sizeof(symname), ptr);
01361                 if (!stabs_parse_typedef(module, ptr, symname))
01362                 {
01363                     /* skip this definition */
01364                     stabbuff[0] = '\0';
01365                     continue;
01366                 }
01367             }
01368         }
01369 
01370         switch (type)
01371         {
01372         case N_GSYM:
01373             /*
01374              * These are useless with ELF.  They have no value, and you have to
01375              * read the normal symbol table to get the address.  Thus we
01376              * ignore them, and when we process the normal symbol table
01377              * we should do the right thing.
01378              *
01379              * With a.out or mingw, they actually do make some amount of sense.
01380              */
01381             stab_strcpy(symname, sizeof(symname), ptr);
01382             loc.kind = loc_absolute;
01383             loc.reg = 0;
01384             loc.offset = load_offset + stab_ptr->n_value;
01385             symt_new_global_variable(module, compiland, symname, TRUE /* FIXME */,
01386                                      loc, 0, stabs_parse_type(ptr));
01387             break;
01388         case N_LCSYM:
01389         case N_STSYM:
01390             /* These are static symbols and BSS symbols. */
01391             stab_strcpy(symname, sizeof(symname), ptr);
01392             loc.kind = loc_absolute;
01393             loc.reg = 0;
01394             loc.offset = load_offset + stab_ptr->n_value;
01395             symt_new_global_variable(module, compiland, symname, TRUE /* FIXME */,
01396                                      loc, 0, stabs_parse_type(ptr));
01397             break;
01398         case N_LBRAC:
01399             if (curr_func)
01400             {
01401                 block = symt_open_func_block(module, curr_func, block,
01402                                              stab_ptr->n_value, 0);
01403                 pending_flush(&pending_block, module, curr_func, block);
01404             }
01405             break;
01406         case N_RBRAC:
01407             if (curr_func)
01408                 block = symt_close_func_block(module, curr_func, block,
01409                                               stab_ptr->n_value);
01410             break;
01411         case N_PSYM:
01412             /* These are function parameters. */
01413             if (curr_func != NULL)
01414             {
01415                 struct symt*    param_type = stabs_parse_type(ptr);
01416                 stab_strcpy(symname, sizeof(symname), ptr);
01417                 loc.kind = loc_regrel;
01418                 loc.reg = dbghelp_current_cpu->frame_regno;
01419                 loc.offset = stab_ptr->n_value;
01420                 symt_add_func_local(module, curr_func,
01421                                     (int)stab_ptr->n_value >= 0 ? DataIsParam : DataIsLocal,
01422                                     &loc, NULL, param_type, symname);
01423                 symt_add_function_signature_parameter(module, 
01424                                                       (struct symt_function_signature*)curr_func->type, 
01425                                                       param_type);
01426             }
01427             break;
01428         case N_RSYM:
01429             /* These are registers (as local variables) */
01430             if (curr_func != NULL)
01431             {
01432                 loc.kind = loc_register;
01433                 loc.offset = 0;
01434 
01435                 switch (stab_ptr->n_value)
01436                 {
01437                 case  0: loc.reg = CV_REG_EAX; break;
01438                 case  1: loc.reg = CV_REG_ECX; break;
01439                 case  2: loc.reg = CV_REG_EDX; break;
01440                 case  3: loc.reg = CV_REG_EBX; break;
01441                 case  4: loc.reg = CV_REG_ESP; break;
01442                 case  5: loc.reg = CV_REG_EBP; break;
01443                 case  6: loc.reg = CV_REG_ESI; break;
01444                 case  7: loc.reg = CV_REG_EDI; break;
01445                 case 11:
01446                 case 12:
01447                 case 13:
01448                 case 14:
01449                 case 15:
01450                 case 16:
01451                 case 17:
01452                 case 18:
01453                 case 19: loc.reg = CV_REG_ST0 + stab_ptr->n_value - 12; break;
01454                 case 21:
01455                 case 22:
01456                 case 23:
01457                 case 24:
01458                 case 25:
01459                 case 26:
01460                 case 27:
01461                 case 28: loc.reg = CV_REG_XMM0 + stab_ptr->n_value - 21; break;
01462                 case 29:
01463                 case 30:
01464                 case 31:
01465                 case 32:
01466                 case 33:
01467                 case 34:
01468                 case 35:
01469                 case 36: loc.reg = CV_REG_MM0 + stab_ptr->n_value - 29; break;
01470                 default:
01471                     FIXME("Unknown register value (%u)\n", stab_ptr->n_value);
01472                     loc.reg = CV_REG_NONE;
01473                     break;
01474                 }
01475                 stab_strcpy(symname, sizeof(symname), ptr);
01476                 if (ptr[strlen(symname) + 1] == 'P')
01477                 {
01478                     struct symt*    param_type = stabs_parse_type(ptr);
01479                     stab_strcpy(symname, sizeof(symname), ptr);
01480                     symt_add_func_local(module, curr_func, DataIsParam, &loc,
01481                                         NULL, param_type, symname);
01482                     symt_add_function_signature_parameter(module, 
01483                                                           (struct symt_function_signature*)curr_func->type, 
01484                                                           param_type);
01485                 }
01486                 else
01487                     pending_add_var(&pending_block, ptr, DataIsLocal, &loc);
01488             }
01489             break;
01490         case N_LSYM:
01491             /* These are local variables */
01492             loc.kind = loc_regrel;
01493             loc.reg = dbghelp_current_cpu->frame_regno;
01494             loc.offset = stab_ptr->n_value;
01495             if (curr_func != NULL) pending_add_var(&pending_block, ptr, DataIsLocal, &loc);
01496             break;
01497         case N_SLINE:
01498             /*
01499              * This is a line number.  These are always relative to the start
01500              * of the function (N_FUN), and this makes the lookup easier.
01501              */
01502             assert(source_idx >= 0);
01503             if (curr_func != NULL)
01504             {
01505                 unsigned long offset = stab_ptr->n_value;
01506                 if (module->type == DMT_MACHO)
01507                     offset -= curr_func->address - load_offset;
01508                 symt_add_func_line(module, curr_func, source_idx, 
01509                                    stab_ptr->n_desc, offset);
01510             }
01511             else pending_add_line(&pending_func, source_idx, stab_ptr->n_desc,
01512                                   stab_ptr->n_value, load_offset);
01513             break;
01514         case N_FUN:
01515             /*
01516              * For now, just declare the various functions.  Later
01517              * on, we will add the line number information and the
01518              * local symbols.
01519              */
01520             /*
01521              * Copy the string to a temp buffer so we
01522              * can kill everything after the ':'.  We do
01523              * it this way because otherwise we end up dirtying
01524              * all of the pages related to the stabs, and that
01525              * sucks up swap space like crazy.
01526              */
01527             stab_strcpy(symname, sizeof(symname), ptr);
01528             if (*symname)
01529             {
01530                 struct symt_function_signature* func_type;
01531 
01532                 if (curr_func)
01533                 {
01534                     /* First, clean up the previous function we were working on.
01535                      * Assume size of the func is the delta between current offset
01536                      * and offset of last function
01537                      */
01538                     stabs_finalize_function(module, curr_func, 
01539                                             stab_ptr->n_value ?
01540                                                 (load_offset + stab_ptr->n_value - curr_func->address) : 0);
01541                 }
01542                 func_type = symt_new_function_signature(module, 
01543                                                         stabs_parse_type(ptr), -1);
01544                 curr_func = symt_new_function(module, compiland, symname, 
01545                                               load_offset + stab_ptr->n_value, 0,
01546                                               &func_type->symt);
01547                 pending_flush(&pending_func, module, curr_func, NULL);
01548             }
01549             else
01550             {
01551                 /* some versions of GCC to use a N_FUN "" to mark the end of a function
01552                  * and n_value contains the size of the func
01553                  */
01554                 stabs_finalize_function(module, curr_func, stab_ptr->n_value);
01555                 curr_func = NULL;
01556             }
01557             break;
01558         case N_SO:
01559             /*
01560              * This indicates a new source file.  Append the records
01561              * together, to build the correct path name.
01562              */
01563             if (*ptr == '\0') /* end of N_SO file */
01564             {
01565                 /* Nuke old path. */
01566                 HeapFree(GetProcessHeap(), 0, srcpath);
01567                 srcpath = NULL;
01568                 stabs_finalize_function(module, curr_func, 0);
01569                 curr_func = NULL;
01570                 source_idx = -1;
01571                 incl_stk = -1;
01572                 assert(block == NULL);
01573                 compiland = NULL;
01574             }
01575             else
01576             {
01577                 int len = strlen(ptr);
01578                 if (ptr[len-1] != '/')
01579                 {
01580                     stabs_reset_includes();
01581                     source_idx = source_new(module, srcpath, ptr);
01582                     compiland = symt_new_compiland(module, 0 /* FIXME */, source_idx);
01583                 }
01584                 else
01585                 {
01586                     srcpath = HeapAlloc(GetProcessHeap(), 0, len + 1);
01587                     strcpy(srcpath, ptr);
01588                 }
01589             }
01590             break;
01591         case N_SOL:
01592             source_idx = source_new(module, srcpath, ptr);
01593             break;
01594         case N_UNDF:
01595             strs += strtabinc;
01596             strtabinc = stab_ptr->n_value;
01597             /* I'm not sure this is needed, so trace it before we obsolete it */
01598             if (curr_func)
01599             {
01600                 FIXME("UNDF: curr_func %s\n", curr_func->hash_elt.name);
01601                 stabs_finalize_function(module, curr_func, 0); /* FIXME */
01602                 curr_func = NULL;
01603             }
01604             break;
01605         case N_OPT:
01606             /* Ignore this. We don't care what it points to. */
01607             break;
01608         case N_BINCL:
01609             stabs_add_include(stabs_new_include(ptr, stab_ptr->n_value));
01610             assert(incl_stk < (int)(sizeof(incl) / sizeof(incl[0])) - 1);
01611             incl[++incl_stk] = source_idx;
01612             source_idx = source_new(module, NULL, ptr);
01613             break;
01614         case N_EINCL:
01615             assert(incl_stk >= 0);
01616             source_idx = incl[incl_stk--];
01617             break;
01618     case N_EXCL:
01619             if (stabs_add_include(stabs_find_include(ptr, stab_ptr->n_value)) < 0)
01620             {
01621                 ERR("Excluded header not found (%s,%d)\n", ptr, stab_ptr->n_value);
01622                 module_reset_debug_info(module);
01623                 ret = FALSE;
01624                 goto done;
01625             }
01626             break;
01627         case N_MAIN:
01628             /* Always ignore these. GCC doesn't even generate them. */
01629             break;
01630         case N_BNSYM:
01631         case N_ENSYM:
01632         case N_OSO:
01633             /* Always ignore these, they seem to be used only on Darwin. */
01634             break;
01635         case N_ABS:
01636 #ifdef N_SECT
01637         case N_SECT:
01638 #endif
01639             /* FIXME: Other definition types (N_TEXT, N_DATA, N_BSS, ...)? */
01640             if (callback)
01641             {
01642                 BOOL is_public = (stab_ptr->n_type & N_EXT);
01643                 BOOL is_global = is_public;
01644 
01645 #ifdef N_PEXT
01646                 /* "private extern"; shared among compilation units in a shared
01647                  * library, but not accessible from outside the library. */
01648                 if (stab_ptr->n_type & N_PEXT)
01649                 {
01650                     is_public = FALSE;
01651                     is_global = TRUE;
01652                 }
01653 #endif
01654 
01655                 if (*ptr == '_') ptr++;
01656                 stab_strcpy(symname, sizeof(symname), ptr);
01657 
01658                 callback(module, load_offset, symname, stab_ptr->n_value,
01659                          is_public, is_global, stab_ptr->n_other, compiland, user);
01660             }
01661             break;
01662         default:
01663             ERR("Unknown stab type 0x%02x\n", type);
01664             break;
01665         }
01666         stabbuff[0] = '\0';
01667         TRACE("0x%02x %x %s\n",
01668               stab_ptr->n_type, stab_ptr->n_value, debugstr_a(strs + stab_ptr->n_strx));
01669     }
01670     module->module.SymType = SymDia;
01671     module->module.CVSig = 'S' | ('T' << 8) | ('A' << 16) | ('B' << 24);
01672     /* FIXME: we could have a finer grain here */
01673     module->module.LineNumbers = TRUE;
01674     module->module.GlobalSymbols = TRUE;
01675     module->module.TypeInfo = TRUE;
01676     module->module.SourceIndexed = TRUE;
01677     module->module.Publics = TRUE;
01678 done:
01679     HeapFree(GetProcessHeap(), 0, stabbuff);
01680     stabs_free_includes();
01681     HeapFree(GetProcessHeap(), 0, pending_block.objs);
01682     HeapFree(GetProcessHeap(), 0, pending_func.objs);
01683 
01684     return ret;
01685 }

Generated on Thu May 24 2012 04:23:46 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.