Ignore:
Timestamp:
Apr 28, 2006, 10:10:49 AM (13 years ago)
Author:
gb
Message:

Create fake stack frames (sort of ...) when calling back for an exception.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/ccl/lisp-kernel/x86-exceptions.c

    r4422 r4457  
    252252}
    253253
     254
     255void
     256push_on_lisp_stack(ExceptionInformation *xp, LispObj value)
     257{
     258  LispObj *vsp = (LispObj *)xpGPR(xp,Isp);
     259  *--vsp = value;
     260  xpGPR(xp,Isp) = (LispObj)vsp;
     261}
     262
     263
     264/* Hard to know if or whether this is necessary in general.  For now,
     265   do it when we get a "wrong number of arguments" trap.
     266*/
     267void
     268finish_function_entry(ExceptionInformation *xp)
     269{
     270  natural nargs = (xpGPR(xp,Inargs)&0xffff)>> fixnumshift;
     271  signed_natural disp = nargs-3;
     272  LispObj *vsp =  (LispObj *) xpGPR(xp,Isp);
     273   
     274 
     275  if (disp > 0) {               /* implies that nargs > 3 */
     276    vsp[disp] = xpGPR(xp,Irbp);
     277    vsp[disp+1] = xpGPR(xp,Ira0);
     278    xpGPR(xp,Irbp) = (LispObj)(vsp+disp);
     279    push_on_lisp_stack(xp,xpGPR(xp,Iarg_x));
     280    push_on_lisp_stack(xp,xpGPR(xp,Iarg_y));
     281    push_on_lisp_stack(xp,xpGPR(xp,Iarg_z));
     282  } else {
     283    push_on_lisp_stack(xp,xpGPR(xp,Ira0));
     284    push_on_lisp_stack(xp,xpGPR(xp,Irbp));
     285    xpGPR(xp,Irbp) = xpGPR(xp,Isp);
     286    if (nargs == 3) {
     287      push_on_lisp_stack(xp,xpGPR(xp,Iarg_x));
     288    }
     289    if (nargs >= 2) {
     290      push_on_lisp_stack(xp,xpGPR(xp,Iarg_y));
     291    }
     292    if (nargs >= 1) {
     293      push_on_lisp_stack(xp,xpGPR(xp,Iarg_z));
     294    }
     295  }
     296}
     297
     298Boolean
     299object_contains_pc(LispObj container, LispObj addr)
     300{
     301  if (fulltag_of(container) >= fulltag_misc) {
     302    natural elements = header_element_count(header_of(container));
     303    if ((addr >= container) &&
     304        (addr < ((LispObj)&(deref(container,1+elements))))) {
     305      return true;
     306    }
     307  }
     308  return false;
     309}
     310
     311LispObj
     312create_exception_callback_frame(ExceptionInformation *xp)
     313{
     314  LispObj containing_uvector = 0,
     315    relative_pc,
     316    nominal_function = lisp_nil,
     317    f, tra, tra_f = 0, abs_pc;
     318
     319  f = xpGPR(xp,Ifn);
     320  tra = xpGPR(xp,Ira0);
     321  if (tag_of(tra) == tag_tra) {
     322    tra_f = tra - ((int *)tra)[-1];
     323    if (fulltag_of(tra_f) != fulltag_function) {
     324      tra_f = 0;
     325    }
     326  }
     327
     328  abs_pc = (LispObj)xpPC(xp);
     329
     330  if (fulltag_of(f) == fulltag_function) {
     331    nominal_function = f;
     332  } else {
     333    if (tra_f) {
     334      nominal_function = tra_f;
     335    }
     336  }
     337 
     338  f = xpGPR(xp,Ifn);
     339  if (object_contains_pc(f, abs_pc)) {
     340    containing_uvector = untag(f)+fulltag_misc;
     341  } else {
     342    f = xpGPR(xp,Ixfn);
     343    if (object_contains_pc(f, abs_pc)) {
     344      containing_uvector = untag(f)+fulltag_misc;
     345    } else {
     346      if (tra_f) {
     347        f = tra_f;
     348        if (object_contains_pc(f, abs_pc)) {
     349          containing_uvector = untag(f)+fulltag_misc;
     350          relative_pc = (abs_pc - f) << fixnumshift;
     351        }
     352      }
     353    }
     354  }
     355  if (containing_uvector) {
     356    relative_pc = (abs_pc - (LispObj)&(deref(containing_uvector,1))) << fixnumshift;
     357  } else {
     358    containing_uvector = lisp_nil;
     359    relative_pc = abs_pc << fixnumshift;
     360  }
     361 
     362  push_on_lisp_stack(xp,tra);
     363  push_on_lisp_stack(xp,(LispObj)xp);
     364  push_on_lisp_stack(xp,containing_uvector);
     365  push_on_lisp_stack(xp,relative_pc);
     366  push_on_lisp_stack(xp,nominal_function);
     367  push_on_lisp_stack(xp,0);
     368  push_on_lisp_stack(xp,xpGPR(xp,Irbp));
     369  xpGPR(xp,Irbp) = xpGPR(xp,Isp);
     370  return xpGPR(xp,Isp);
     371}
     372
     373
     374 
    254375int
    255376callback_to_lisp (TCR * tcr, LispObj callback_macptr, ExceptionInformation *xp,
     
    259380  natural  callback_ptr, i;
    260381  int delta;
    261 
    262 
    263382
    264383  /* Put the active stack pointers where .SPcallback expects them */
     
    268387
    269388
    270   /* Call back.
    271      Lisp will handle trampolining through some code that
    272      will push lr/fn & pc/nfn stack frames for backtrace.
     389  /* Call back.  The caller of this function may have modified stack/frame
     390     pointers (and at least should have called prepare_for_callback()).
    273391  */
    274392  callback_ptr = ((macptr *)ptr_from_lispobj(untag(callback_macptr)))->address;
     
    282400callback_for_interrupt(TCR *tcr, ExceptionInformation *xp)
    283401{
    284   callback_to_lisp(tcr, nrs_CMAIN.vcell,xp, 0, Ifn, 0, 0, 0);
     402  LispObj save_rbp = xpGPR(xp,Irbp),
     403    save_vsp = xpGPR(xp,Isp),
     404    xcf = create_exception_callback_frame(xp);
     405 
     406  callback_to_lisp(tcr, nrs_CMAIN.vcell,xp, xcf, 0, 0, 0, 0);
     407  xpGPR(xp,Irbp) = save_rbp;
     408  xpGPR(xp,Isp) = save_vsp;
    285409}
    286410
     
    289413{
    290414  pc program_counter = (pc)xpPC(xp);
    291   unsigned char op0 = program_counter[0], op1 = program_counter[1], op2 = program_counter[2];
    292   LispObj rpc = (LispObj) program_counter, current_function, errdisp = nrs_ERRDISP.vcell;
    293   int rfn = 0, skip;
     415  unsigned char op0 = program_counter[0], op1 = program_counter[1];
     416  LispObj rpc = (LispObj) program_counter, errdisp = nrs_ERRDISP.vcell,
     417    save_rbp = xpGPR(xp,Irbp), save_vsp = xpGPR(xp,Isp), xcf;
     418  int skip;
    294419
    295420  if ((fulltag_of(errdisp) == fulltag_misc) &&
    296421      (header_subtag(header_of(errdisp)) == subtag_macptr)) {
    297     LispObj current_function = xpGPR(xp, Ifn), elements;
    298  
    299     if (fulltag_of(current_function) == fulltag_function) {
    300       elements = header_element_count(header_of(current_function));
    301       if ((rpc > current_function) &&
    302           (rpc < ((LispObj)&(deref(current_function,1+elements))))) {
    303         rfn = Ifn;
    304         rpc -= current_function;
    305       } else {
    306         current_function = xpGPR(xp, Itemp1); /* temp1 aka xfn */
    307         if (fulltag_of(current_function) == fulltag_function) {
    308           elements = header_element_count(header_of(current_function));
    309           if ((rpc > current_function) &&
    310               (rpc < ((LispObj)&(deref(current_function,1+elements))))) {
    311             rfn = Itemp1;
    312             rpc -= current_function;
    313           }
    314         }
    315       }
    316     }
    317     skip = callback_to_lisp(tcr, errdisp, xp, rfn, rpc, op0, op1, op2);
     422
     423    if ((op0 == 0xcd) && (op1 >= 0xc0) && (op1 <= 0xc2)) {
     424      finish_function_entry(xp);
     425    }
     426    xcf = create_exception_callback_frame(xp);
     427    skip = callback_to_lisp(tcr, errdisp, xp, xcf, 0, 0, 0, 0);
     428    xpGPR(xp,Irbp) = save_rbp;
     429    xpGPR(xp,Isp) = save_vsp;
    318430    xpPC(xp) += skip;
    319431    return true;
     
    334446  int code = info->si_code, rfn = 0, skip;
    335447  pc program_counter = (pc)xpPC(xp);
    336   LispObj rpc = (LispObj) program_counter, current_function, cmain = nrs_CMAIN.vcell;
     448  LispObj rpc = (LispObj) program_counter, xcf, cmain = nrs_CMAIN.vcell,
     449    save_rbp = xpGPR(xp,Irbp), save_vsp = xpGPR(xp,Isp);
    337450
    338451  if ((fulltag_of(cmain) == fulltag_misc) &&
    339452      (header_subtag(header_of(cmain)) == subtag_macptr)) {
    340         LispObj current_function = xpGPR(xp, Ifn), elements;
    341  
    342     if (fulltag_of(current_function) == fulltag_function) {
    343       elements = header_element_count(header_of(current_function));
    344       if ((rpc > current_function) &&
    345           (rpc < ((LispObj)&(deref(current_function,1+elements))))) {
    346         rfn = Ifn;
    347         rpc -= current_function;
    348       } else {
    349         current_function = xpGPR(xp, Itemp1); /* temp1 aka xfn */
    350         if (fulltag_of(current_function) == fulltag_function) {
    351           elements = header_element_count(header_of(current_function));
    352           if ((rpc > current_function) &&
    353               (rpc < ((LispObj)&(deref(current_function,1+elements))))) {
    354             rfn = Itemp1;
    355             rpc -= current_function;
    356           }
    357         }
    358       }
    359     }
    360     skip = callback_to_lisp(tcr, cmain, xp, SIGFPE, rfn, rpc, code, 0);
     453    xcf = create_exception_callback_frame(xp);
     454    skip = callback_to_lisp(tcr, cmain, xp, xcf, SIGFPE, code, 0, 0);
    361455    xpPC(xp) += skip;
     456    xpGPR(xp,Irbp) = save_rbp;
     457    xpGPR(xp,Isp) = save_vsp;
    362458    return true;
    363459  } else {
Note: See TracChangeset for help on using the changeset viewer.