Exemplo n.º 1
0
    /**
     * 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;
    }
Exemplo n.º 2
0
    /**
     * 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;
    }