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

dwarfcfa.c
Go to the documentation of this file.
00001 /*
00002  * Dwarf call frame unwinding.
00003  *
00004  * The call frame unwinding values are encoded using a state machine
00005  * like the pc<->line mapping, but it's a different machine.
00006  * The expressions to generate the old values are similar in function to the
00007  * ``dwarf expressions'' used for locations in the code, but of course not
00008  * the same encoding.
00009  */
00010 
00011 #define NTOSAPI
00012 #include <ntddk.h>
00013 #include <reactos/rossym.h>
00014 #include "rossympriv.h"
00015 #include <ntimage.h>
00016 
00017 #define NDEBUG
00018 #include <debug.h>
00019 
00020 #include "dwarf.h"
00021 
00022 #define trace 0
00023 
00024 typedef struct State State;
00025 struct State
00026 {
00027     ulong loc;
00028     ulong endloc;
00029     ulong iquantum;
00030     ulong dquantum;
00031     char *augmentation;
00032     int version;
00033     ulong rareg;
00034     DwarfBuf init;
00035     DwarfExpr *cfa;
00036     DwarfExpr *ra;
00037     DwarfExpr *r;
00038     DwarfExpr *initr;
00039     int nr;
00040     DwarfExpr **stack;
00041     int nstack;
00042 };
00043 
00044 static int findfde(Dwarf*, ulong, State*, DwarfBuf*);
00045 static int dexec(DwarfBuf*, State*, int);
00046 
00047 int
00048 dwarfunwind(Dwarf *d, ulong pc, DwarfExpr *cfa, DwarfExpr *ra, DwarfExpr *r, int nr)
00049 {
00050     int i, ret;
00051     DwarfBuf fde, b;
00052     DwarfExpr *initr;
00053     State s;
00054 
00055     initr = mallocz(nr*sizeof(initr[0]), 1);
00056     if(initr == 0)
00057         return -1;
00058 
00059     memset(&s, 0, sizeof s);
00060     s.loc = 0;
00061     s.cfa = cfa;
00062     s.ra = ra;
00063     s.r = r;
00064     s.nr = nr;
00065 
00066     if(findfde(d, pc, &s, &fde) < 0){
00067         free(initr);
00068         return -1;
00069     }
00070 
00071     memset(r, 0, nr*sizeof(r[0]));
00072     for(i=0; i<nr; i++)
00073         r[i].type = RuleSame;
00074     if(trace) werrstr("s.init %p-%p, fde %p-%p\n", s.init.p, s.init.ep, fde.p, fde.ep);
00075     b = s.init;
00076     if(dexec(&b, &s, 0) < 0)
00077         goto err;
00078 
00079     s.initr = initr;
00080     memmove(initr, r, nr*sizeof(initr[0]));
00081 
00082     if(trace) werrstr("s.loc 0x%lux pc 0x%lux\n", s.loc, pc);
00083     while(s.loc < pc){
00084         if(trace) werrstr("s.loc 0x%lux pc 0x%lux\n", s.loc, pc);
00085         if(dexec(&fde, &s, 1) < 0)
00086             goto err;
00087     }
00088     *ra = s.r[s.rareg];
00089 
00090     ret = 0;
00091     goto out;
00092 
00093 err:
00094     ret = -1;
00095 out:
00096     free(initr);
00097     for(i=0; i<s.nstack; i++)
00098         free(s.stack[i]);
00099     free(s.stack);
00100     return ret;
00101 }
00102 
00103 /*
00104  * XXX This turns out to be much more expensive than the actual
00105  * running of the machine in dexec.  It probably makes sense to
00106  * cache the last 10 or so fde's we've found, since stack traces
00107  * will keep asking for the same info over and over.
00108  */
00109 static int
00110 findfde(Dwarf *d, ulong pc, State *s, DwarfBuf *fde)
00111 {
00112     static int nbad;
00113     char *aug;
00114     uchar *next;
00115     int i, vers;
00116     ulong len, id, base, size;
00117     DwarfBuf b;
00118 
00119     if(d->frame.data == nil){
00120         werrstr("no frame debugging information");
00121         return -1;
00122     }
00123     b.d = d;
00124     b.p = d->frame.data;
00125     b.ep = b.p + d->frame.len;
00126     b.addrsize = d->addrsize;
00127     if(b.addrsize == 0)
00128         b.addrsize = 4; /* where should i find this? */
00129 
00130     for(; b.p < b.ep; b.p = next){
00131         if((i = (b.p - d->frame.data) % b.addrsize))
00132             b.p += b.addrsize - i;
00133         len = dwarfget4(&b);
00134         if(len > b.ep-b.p){
00135             werrstr("bad length in cie/fde header");
00136             return -1;
00137         }
00138         next = b.p+len;
00139         id = dwarfget4(&b);
00140         if(id == 0xFFFFFFFF){   /* CIE */
00141             vers = dwarfget1(&b);
00142             if(vers != 1 && vers != 2 && vers != 3){
00143                 if(++nbad == 1)
00144                     werrstr("unknown cie version %d (wanted 1-3)\n", vers);
00145                 continue;
00146             }
00147             aug = dwarfgetstring(&b);
00148             if(aug && *aug){
00149                 if(++nbad == 1)
00150                     werrstr("unknown augmentation: %s\n", aug);
00151                 continue;
00152             }
00153             s->iquantum = dwarfget128(&b);
00154             s->dquantum = dwarfget128s(&b);
00155             s->rareg = dwarfget128(&b);
00156             if(s->rareg > s->nr){
00157                 werrstr("return address is register %d but only have %d registers",
00158                     s->rareg, s->nr);
00159                 return -1;
00160             }
00161             s->init.p = b.p;
00162             s->init.ep = next;
00163         }else{  /* FDE */
00164             base = dwarfgetaddr(&b);
00165             size = dwarfgetaddr(&b);
00166             fde->p = b.p;
00167             fde->ep = next;
00168             s->loc = base;
00169             s->endloc = base+size;
00170             if(base <= pc && pc < base+size)
00171                 return 0;
00172         }
00173     }
00174     werrstr("cannot find call frame information for pc 0x%lux", pc);
00175     return -1;
00176 
00177 }
00178 
00179 static int
00180 checkreg(State *s, long r)
00181 {
00182     if(r < 0 || r >= s->nr){
00183         werrstr("bad register number 0x%lux", r);
00184         return -1;
00185     }
00186     return 0;
00187 }
00188 
00189 static int
00190 dexec(DwarfBuf *b, State *s, int locstop)
00191 {
00192     int c;
00193     long arg1, arg2;
00194     DwarfExpr *e;
00195 
00196     for(;;){
00197         if(b->p == b->ep){
00198             if(s->initr)
00199                 s->loc = s->endloc;
00200             return 0;
00201         }
00202         c = dwarfget1(b);
00203         if(b->p == nil){
00204             werrstr("ran out of instructions during cfa program");
00205             if(trace) werrstr("%r\n");
00206             return -1;
00207         }
00208         if(trace) werrstr("+ loc=0x%lux op 0x%ux ", s->loc, c);
00209         switch(c>>6){
00210         case 1: /* advance location */
00211             arg1 = c&0x3F;
00212         advance:
00213             if(trace) werrstr("loc += %ld\n", arg1*s->iquantum);
00214             s->loc += arg1 * s->iquantum;
00215             if(locstop)
00216                 return 0;
00217             continue;
00218 
00219         case 2: /* offset rule */
00220             arg1 = c&0x3F;
00221             arg2 = dwarfget128(b);
00222         offset:
00223             if(trace) werrstr("r%ld += %ld\n", arg1, arg2*s->dquantum);
00224             if(checkreg(s, arg1) < 0)
00225                 return -1;
00226             s->r[arg1].type = RuleCfaOffset;
00227             s->r[arg1].offset = arg2 * s->dquantum;
00228             continue;
00229 
00230         case 3: /* restore initial setting */
00231             arg1 = c&0x3F;
00232         restore:
00233             if(trace) werrstr("r%ld = init\n", arg1);
00234             if(checkreg(s, arg1) < 0)
00235                 return -1;
00236             s->r[arg1] = s->initr[arg1];
00237             continue;
00238         }
00239 
00240         switch(c){
00241         case 0: /* nop */
00242             if(trace) werrstr("nop\n");
00243             continue;
00244 
00245         case 0x01:  /* set location */
00246             s->loc = dwarfgetaddr(b);
00247             if(trace) werrstr("loc = 0x%lux\n", s->loc);
00248             if(locstop)
00249                 return 0;
00250             continue;
00251 
00252         case 0x02:  /* advance loc1 */
00253             arg1 = dwarfget1(b);
00254             goto advance;
00255 
00256         case 0x03:  /* advance loc2 */
00257             arg1 = dwarfget2(b);
00258             goto advance;
00259 
00260         case 0x04:  /* advance loc4 */
00261             arg1 = dwarfget4(b);
00262             goto advance;
00263 
00264         case 0x05:  /* offset extended */
00265             arg1 = dwarfget128(b);
00266             arg2 = dwarfget128(b);
00267             goto offset;
00268 
00269         case 0x06:  /* restore extended */
00270             arg1 = dwarfget128(b);
00271             goto restore;
00272 
00273         case 0x07:  /* undefined */
00274             arg1 = dwarfget128(b);
00275             if(trace) werrstr("r%ld = undef\n", arg1);
00276             if(checkreg(s, arg1) < 0)
00277                 return -1;
00278             s->r[arg1].type = RuleUndef;
00279             continue;
00280 
00281         case 0x08:  /* same value */
00282             arg1 = dwarfget128(b);
00283             if(trace) werrstr("r%ld = same\n", arg1);
00284             if(checkreg(s, arg1) < 0)
00285                 return -1;
00286             s->r[arg1].type = RuleSame;
00287             continue;
00288 
00289         case 0x09:  /* register */
00290             arg1 = dwarfget128(b);
00291             arg2 = dwarfget128(b);
00292             if(trace) werrstr("r%ld = r%ld\n", arg1, arg2);
00293             if(checkreg(s, arg1) < 0 || checkreg(s, arg2) < 0)
00294                 return -1;
00295             s->r[arg1].type = RuleRegister;
00296             s->r[arg1].reg = arg2;
00297             continue;
00298 
00299         case 0x0A:  /* remember state */
00300             e = malloc(s->nr*sizeof(e[0]));
00301             if(trace) werrstr("push\n");
00302             if(e == nil)
00303                 return -1;
00304             void *newstack = malloc(s->nstack*sizeof(s->stack[0]));
00305             RtlMoveMemory(newstack, s->stack, s->nstack*sizeof(s->stack[0]));
00306             if (newstack) {
00307                 free(s->stack);
00308                 s->stack = newstack;
00309             } else {
00310                 free(e);
00311                 return -1;
00312             }
00313             if(b->p == nil){
00314                 free(e);
00315                 return -1;
00316             }
00317             s->stack[s->nstack++] = e;
00318             memmove(e, s->r, s->nr*sizeof(e[0]));
00319             continue;
00320 
00321         case 0x0B:  /* restore state */
00322             if(trace) werrstr("pop\n");
00323             if(s->nstack == 0){
00324                 werrstr("restore state underflow");
00325                 return -1;
00326             }
00327             e = s->stack[s->nstack-1];
00328             memmove(s->r, e, s->nr*sizeof(e[0]));
00329             free(e);
00330             s->nstack--;
00331             continue;
00332 
00333         case 0x0C:  /* def cfa */
00334             arg1 = dwarfget128(b);
00335             arg2 = dwarfget128(b);
00336         defcfa:
00337             if(trace) werrstr("cfa %ld(r%ld)\n", arg2, arg1);
00338             if(checkreg(s, arg1) < 0)
00339                 return -1;
00340             s->cfa->type = RuleRegOff;
00341             s->cfa->reg = arg1;
00342             s->cfa->offset = arg2;
00343             continue;
00344 
00345         case 0x0D:  /* def cfa register */
00346             arg1 = dwarfget128(b);
00347             if(trace) werrstr("cfa reg r%ld\n", arg1);
00348             if(s->cfa->type != RuleRegOff){
00349                 werrstr("change CFA register but CFA not in register+offset form");
00350                 return -1;
00351             }
00352             if(checkreg(s, arg1) < 0)
00353                 return -1;
00354             s->cfa->reg = arg1;
00355             continue;
00356 
00357         case 0x0E:  /* def cfa offset */
00358             arg1 = dwarfget128(b);
00359         cfaoffset:
00360             if(trace) werrstr("cfa off %ld\n", arg1);
00361             if(s->cfa->type != RuleRegOff){
00362                 werrstr("change CFA offset but CFA not in register+offset form");
00363                 return -1;
00364             }
00365             s->cfa->offset = arg1;
00366             continue;
00367 
00368         case 0x0F:  /* def cfa expression */
00369             if(trace) werrstr("cfa expr\n");
00370             s->cfa->type = RuleLocation;
00371             s->cfa->loc.len = dwarfget128(b);
00372             s->cfa->loc.data = dwarfgetnref(b, s->cfa->loc.len);
00373             continue;
00374 
00375         case 0x10:  /* def reg expression */
00376             arg1 = dwarfget128(b);
00377             if(trace) werrstr("reg expr r%ld\n", arg1);
00378             if(checkreg(s, arg1) < 0)
00379                 return -1;
00380             s->r[arg1].type = RuleLocation;
00381             s->r[arg1].loc.len = dwarfget128(b);
00382             s->r[arg1].loc.data = dwarfgetnref(b, s->r[arg1].loc.len);
00383             continue;
00384 
00385         case 0x11:  /* offset extended */
00386             arg1 = dwarfget128(b);
00387             arg2 = dwarfget128s(b);
00388             goto offset;
00389 
00390         case 0x12:  /* cfa sf */
00391             arg1 = dwarfget128(b);
00392             arg2 = dwarfget128s(b);
00393             goto defcfa;
00394 
00395         case 0x13:  /* cfa offset sf */
00396             arg1 = dwarfget128s(b);
00397             goto cfaoffset;
00398 
00399         default:    /* unknown */
00400             werrstr("unknown opcode 0x%ux in cfa program", c);
00401             return -1;
00402         }
00403     }
00404     /* not reached */
00405 }
00406 
00407 

Generated on Sat May 26 2012 04:35:17 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.