📄 debugger.c
字号:
#endif freeBucket(tmpBucket); } bucketMap[i] = (unsigned long)bucket; if (i < length - 1) { return i; } else if (i >= DEBUGGER_INDEX_MASK) { fatalError(KVM_MSG_OUT_OF_DEBUGGER_ROOT_SLOTS); } else { break; } } } /* We need to expand debugRoot and bucketMap */ { /* We need to expand the table */ const int expansion = 20; int newLength = length + expansion; WEAKPOINTERLIST tmpList = (WEAKPOINTERLIST)callocObject(SIZEOF_WEAKPOINTERLIST(newLength), GCT_WEAKPOINTERLIST); tmpList->length = newLength; memcpy(tmpList->data, debugRoot->data, length << log2CELL); debugRoot = tmpList; tmpPtr = (unsigned long *)mallocBytes(newLength * CELL); memcpy(tmpPtr, bucketMap, length << log2CELL); memset(&tmpPtr[length], 0, expansion << log2CELL); bucketMap = tmpPtr; return i; }}static unsigned long getObjectIDInternal(OBJECT object){ HASHTABLE table; unsigned long index; ID_HASH_ENTRY bucket, *bucketPtr; table = debuggerHashTable; index = debuggerHash(object) % table->bucketCount; bucketPtr = (ID_HASH_ENTRY *)&table->bucket[index]; for (bucket = *bucketPtr; bucket != NULL; bucket = bucket->next) { if (debugRoot->data[bucket->rootIndex].cellp == (cell*)object) return (bucket->key); } return (0);}/*======================================================================== * Function: getObjectID() * Overview: given an object, find/create it's ID * Interface: * parameters: pointer to object * returns: index into array * * Notes: *=======================================================================*/unsigned long getObjectID(OBJECT object){ HASHTABLE table; unsigned long key; unsigned long index; ID_HASH_ENTRY bucket, *bucketPtr; if (!vmDebugReady || object == NULL) { return 0; } if (!inCurrentHeap(object)) { return (unsigned long)object; } key = getObjectIDInternal(object); if (key == 0) { table = debuggerHashTable; index = debuggerHash(object) % table->bucketCount; bucketPtr = (ID_HASH_ENTRY *)&table->bucket[index]; bucket = NULL; /* need to create a new one, first try to find an unused bucket */ if (bucketFreeList != NULL) { bucket = bucketFreeList; bucketFreeList = bucket->next; } if (bucket == NULL) { START_TEMPORARY_ROOTS DECLARE_TEMPORARY_ROOT(void *, objectX, object); bucket = (ID_HASH_ENTRY)callocPermanentObject(SIZEOF_ID_HASH_ENTRY); bucketsAllocated++; object = objectX; /* in case GC occurred */ END_TEMPORARY_ROOTS } bucket->rootIndex = addToDebugRoot(object, bucket); bucket->next = *bucketPtr; *bucketPtr = bucket; bucket->key = NEXT_UNIQUE_DEBUGGER_ID() + ((index & DEBUGGER_INDEX_MASK) << DEBUGGER_INDEX_SHIFT) + 1; key = bucket->key; } return key;}/*======================================================================== * Function: getObjectPtr() * Overview: given an ID, find the object it maps to * Interface: * parameters: ID number * returns: void pointer * * Notes: *=======================================================================*/OBJECT getObjectPtr(unsigned long key){ unsigned long index; ID_HASH_ENTRY bucket, *bucketPtr; if (!vmDebugReady) { return NULL; } else if ((key & 1) == 0) { return ((void *)key); } index = (key >> DEBUGGER_INDEX_SHIFT) & DEBUGGER_INDEX_MASK; bucketPtr = (ID_HASH_ENTRY *)&debuggerHashTable->bucket[index]; for (bucket = *bucketPtr; bucket != NULL; bucket = bucket->next) { if (key == bucket->key) return (OBJECT)(debugRoot->data[bucket->rootIndex].cellp); } return NULL;}/*======================================================================== * Function: getModifier() * Overview: return a specific type of modifier contained within * an event * Interface: * parameters: event pointer, modifier type * returns: pointer to an event modifier struct * * Notes: *=======================================================================*/static EVENTMODIFIER getModifier(VMEventPtr ep, BYTE type){ EVENTMODIFIER mod; for (mod = ep->mods; mod != NIL; mod = mod->next) { if (mod->kind == type) { return mod; } } return NIL;}/*======================================================================== * Function: findBreakEventAndOpcode() * Overview: Search through our list of breakpoints to find this one * that we hit * Interface: * parameters: pointer to opcode, mod, class, method , offset * returns: pointer to breakpoint structure * * Notes: *=======================================================================*/static VMEventPtr findBreakEventAndOpcode(ByteCode *opcode, EVENTMODIFIER *modpp, unsigned long classID, unsigned long thisMethod, unsigned long offset){ VMEventPtr ep = eventHead; EVENTMODIFIER mod; if (ep == NIL) { return (NIL); /* no breakpoints??? */ } do { if (ep->kind == JDWP_EventKind_BREAKPOINT) { if ((mod = getModifier(ep, JDWP_EventRequest_Set_Out_modifiers_Modifier_LocationOnly)) != NIL) { if (mod->u.loc.classID == classID && mod->u.loc.methodIndex == thisMethod && mod->u.loc.offset == offset /*&& mod->u.loc.tag == tag */) { if (opcode != NIL) *opcode = mod->u.loc.opcode; if (modpp != NIL) *modpp = mod; return (ep); } } } } while ((ep = ep->next)); return NIL;}static bool_t checkClassMatch(CEModPtr cep, EVENTMODIFIER em){ bool_t result = TRUE; START_TEMPORARY_ROOTS CLASS clazz = GET_DEBUGGERID_CLASS(cep->loc.classID); DECLARE_TEMPORARY_ROOT(char *, fullName, getClassName(clazz)); char *modName = em->u.classMatch.className; unsigned int modNameLength = strlen(modName); char *p; /* make sure that fullName is a 'standard' classname with '.'s */ p = fullName; while (*p != '\0') { if (*p == '/' || *p == '\\') *p = '.'; p++; } if (modName[0] == '*' || modName[modNameLength - 1] == '*') { /* We have a prefix/suffix match. The rest of match has to be * the same as the tail/head of fullName */ int compLen = modNameLength - 1; int fullNameLength = strlen(fullName); int offset = fullNameLength - compLen; char *start; if (offset < 0) { result = FALSE; } else { if (modName[0] == '*') { /* suffix match */ modName++; start = fullName + offset; } else { start = fullName; } result = (strncmp(modName, start, compLen) == 0); } } else { /* Just compare the two. */ result = (strcmp(modName, fullName) == 0); } END_TEMPORARY_ROOTS return result;}/*======================================================================== * Function: satisfiesModifiers() * Overview: determines whether an event which has occured * satisfies its modifiers * Interface: * parameters: event pointer, current event pointer, mod pointer * * Notes: *=======================================================================*/static bool_t satisfiesModifiers(VMEventPtr ep, CEModPtr cep, EVENTMODIFIER em) { if (em == NIL) return TRUE; switch (em->kind) { case JDWP_EventRequest_Set_Out_modifiers_Modifier_Conditional: /* reserved for future use */ break; case JDWP_EventRequest_Set_Out_modifiers_Modifier_ThreadOnly: if (cep->threadID != em->u.threadID) return FALSE; break; case JDWP_EventRequest_Set_Out_modifiers_Modifier_ClassOnly: return (em->u.classID == cep->loc.classID); case JDWP_EventRequest_Set_Out_modifiers_Modifier_ClassMatch: return checkClassMatch(cep, em); case JDWP_EventRequest_Set_Out_modifiers_Modifier_ClassExclude: break; case JDWP_EventRequest_Set_Out_modifiers_Modifier_LocationOnly: if ((cep->loc.classID != em->u.loc.classID) || (cep->loc.methodIndex != em->u.loc.methodIndex) || (cep->loc.offset != em->u.loc.offset)) return FALSE; break; case JDWP_EventRequest_Set_Out_modifiers_Modifier_ExceptionOnly: { bool_t ret = TRUE; if (em->u.exp.classID != 0) { INSTANCE_CLASS clazz = (INSTANCE_CLASS)GET_DEBUGGERID_CLASS(cep->exp.classID); while (clazz != NULL) { if (GET_CLASS_DEBUGGERID(&clazz->clazz) == em->u.exp.classID) { ret = TRUE; break; } clazz = clazz->superClass; } } ret = ret && ((em->u.exp.sig_caught && cep->exp.sig_caught) || (em->u.exp.sig_uncaught && cep->exp.sig_uncaught)); if (!ret) return FALSE; break; } case JDWP_EventRequest_Set_Out_modifiers_Modifier_FieldOnly: break; case JDWP_EventRequest_Set_Out_modifiers_Modifier_Step: if ((cep->step.threadID != em->u.step.threadID) || (cep->step.size != em->u.step.size) || (cep->step.depth != em->u.step.depth)) { /* || (cep->step.target.cl != em->u.step.target.cl) || (cep->step.target.method != em->u.step.target.method) || (cep->step.target.offset != em->u.step.target.offset)) */ return FALSE; } break; } return TRUE;}/*======================================================================== * Function: checkEventCount() * Overview: deals with events with a count modifier * Interface: * parameters: event kind * returns: nothing * * Notes: *=======================================================================*/static void checkEventCount(VMEventPtr ep){ if (ep->count_active) { if (ep->count == 0) { /* if it's 0 then the count was satisfied */ ep->active = FALSE; ep->count_active = FALSE; clearEvent(ep); } }}/*======================================================================== * Function: findSatisfyingEvent() * Overview: finds a specific type of event that also satisfies * its modifiers * Interface: * parameters: event kind, pointer to current event structure * pointer to return list of events, count of events * returns: true if event to process, false otherwise * * Notes: *=======================================================================*/static bool_t findSatisfyingEvent(BYTE kind, CEModPtr cep, VMEventPtr *epp, int *eventCount, BYTE *suspendPolicy){ VMEventPtr ep = eventHead; EVENTMODIFIER em; *epp = NULL; *eventCount = 0; *suspendPolicy = 0; if (ep == NIL) return (FALSE); /* no events */ do { if (!ep->active) continue; if (ep->kind == kind) { /* * The count modifier is a global modifier that filters all * other modifiers, hence it's in the VMEvent structure */ if (ep->count_active) { if (ep->count-- > 1) { continue; } } /* check modifiers */ em = ep->mods; do { if (em == NULL || satisfiesModifiers(ep, cep, em)) { /* add to list of events to send */ ep->sendNext = NULL; if (*epp == NULL) { *epp = ep; } else { ep->sendNext = *epp; *epp = ep; } (*eventCount)++; if (ep->suspendPolicy > *suspendPolicy) *suspendPolicy = ep->suspendPolicy; break; } } while (em && (em = em->next) != NULL); } } while ((ep = ep->next)); if (*epp != NULL) return TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -