/** * Scans the bytecode and adds source level information to * the abc info object */ bool Debugger::scanCode(AbcFile* file, PoolObject* pool, MethodInfo* m) { const byte *abc_start = &m->pool()->code()[0]; const byte *pos = m->abc_body_pos(); m->setFile(file); AvmCore::skipU32(pos, 4); // max_stack; local_count; init_stack_depth; max_stack_depth; int code_len = AvmCore::readU32(pos); const byte *start = pos; const byte *end = pos + code_len; int size = 0; int op_count; SourceFile* active = NULL; // current source file for (const byte* pc=start; pc < end; pc += size) { op_count = opcodeInfo[*pc].operandCount; if (op_count == -1 && *pc != OP_lookupswitch) return false; // ohh very bad, verifier will catch this size = AvmCore::calculateInstructionWidth(pc); if (pc+size > end) return false; // also bad, let the verifier will handle it switch (*pc) { case OP_lookupswitch: { // variable length instruction const byte *pc2 = pc+4; int case_count = 1 + readU32(pc2); size += case_count*3; break; } case OP_debug: { // form is 8bit type followed by pool entry // then 4Byte extra info int type = (uint8)*(pc+1); switch(type) { case DI_LOCAL: { // in this case last word contains // register and line number const byte* pc2 = pc+2; int index = readU32(pc2); int slot = (uint8)*(pc2); //int line = readS24(pc+5); //Atom str = pool->cpool[index]; Stringp s = pool->getString(index); m->setRegName(slot, s); } } break; } case OP_debugline: { // this means that we have a new source line for the given offset const byte* pc2 = pc+1; int line = readU32(pc2); if (active != NULL) active->addLine(line, m, (int)(pc - abc_start)); // else, OP_line occurred before OP_file: fix the compiler! break; } case OP_debugfile: { // new or existing source file const byte* pc2 = pc+1; Stringp name = pool->getString(readU32(pc2)); active = file->sourceNamed(name); if (active == NULL) { active = new (core->GetGC()) SourceFile(core->GetGC(), name); file->sourceAdd(active); } break; } } } return true; }
/** * Scans the bytecode and adds source level information to * the abc info object */ bool Debugger::scanCode(AbcFile* file, PoolObject* pool, MethodInfo* m) { const uint8_t *abc_start = &m->pool()->code()[0]; const uint8_t *pos = m->abc_body_pos(); m->setFile(file); AvmCore::skipU32(pos, 4); // max_stack; local_count; init_stack_depth; max_stack_depth; uint32_t code_len = AvmCore::readU32(pos); // checked earlier by AbcParser::parseMethodInfos() const uint8_t *start = pos; const uint8_t *end = pos + code_len; uintptr_t size = 0; int op_count; SourceFile* active = NULL; // current source file for (const uint8_t* pc=start; pc < end; pc += size) { op_count = opcodeInfo[*pc].operandCount; if (op_count == -1 && *pc != OP_lookupswitch) return false; // ohh very bad, verifier will catch this size = AvmCore::calculateInstructionWidth(pc); // if pc+size overflows, we're definitely hosed if (uintptr_t(pc) > uintptr_t(-1) - size) return false; if (pc+size > end) return false; // also bad, let the verifier will handle it switch (*pc) { case OP_lookupswitch: { // variable length instruction const uint8_t *pc2 = pc+4; // case_count is a U30, so if the high bits are set, // bail and let Verifier throw the error uint32_t const case_count = readU32(pc2); if (case_count & 0xc0000000) return false; // case_count*3 can't overflow a U32... uint32_t const case_skip = (case_count + 1) * 3; // ...but size could, so check to see if it will. if (size > uintptr_t(-1) - case_skip) return false; size += case_skip; break; } case OP_debug: { // form is 8bit type followed by pool entry // then 4Byte extra info int type = (uint8_t)*(pc+1); switch(type) { case DI_LOCAL: { // in this case last word contains // register and line number const uint8_t* pc2 = pc+2; uint32_t index = AvmCore::readU32(pc2); int slot = (uint8_t)*(pc2); //int line = readS24(pc+5); if (index >= pool->constantStringCount) break; // let the verifier handle this //Atom str = pool->cpool[index]; Stringp s = pool->getString(index); m->setRegName(slot, s); } } break; } case OP_debugline: { // this means that we have a new source line for the given offset const uint8_t* pc2 = pc+1; int line = readU32(pc2); if (active != NULL) active->addLine(line, m, (int)(pc - abc_start)); // else, OP_line occurred before OP_file: fix the compiler! break; } case OP_debugfile: { // new or existing source file const uint8_t* pc2 = pc+1; uint32_t index = AvmCore::readU32(pc2); if (index >= pool->constantStringCount) break; // let the verifier handle this Stringp name = pool->getString(index); active = file->sourceNamed(name); if (active == NULL) { active = SourceFile::create(core->GetGC(), name); file->sourceAdd(active); } break; } } } return true; }