Exemple #1
0
/*
 *   Load a method header list block 
 */
void CVmImageLoader::load_mhls(VMG_ ulong siz)
{
    char buf[512];
    ulong cnt;
    ulong i;

    /* read the count */
    read_data(buf, 4, &siz);
    cnt = t3rp4u(buf);

    /* allocate space for the list */
    G_debugger->alloc_method_header_list(cnt);

    /* read the entries */
    for (i = 0 ; cnt != 0 ; )
    {
        size_t cur;
        char *p;
        
        /* read as many as we can fit, up to the number remaining */
        cur = sizeof(buf) / 4;
        if (cur > cnt)
            cur = (size_t)cnt;

        /* read the chunk */
        read_data(buf, cur * 4, &siz);

        /* deduct the number we just read from the number remaining */
        cnt -= cur;

        /* process these entries */
        for (p = buf ; cur != 0 ; --cur, ++i, p += 4)
            G_debugger->set_method_header(i, t3rp4u(p));
    }
}
Exemple #2
0
/* load image data */
void CVmObjClass::load_image_data(VMG_ vm_obj_id_t self,
                                  const char *ptr, size_t siz)
{
    /* make sure the length is valid */
    if (siz < 8)
        err_throw(VMERR_INVAL_METACLASS_DATA);

    /* allocate or reallocate the extension */
    vm_intcls_ext *ext = alloc_ext(vmg0_);

    /* 
     *   read the metaclass index and modifier object ID; note that modifier
     *   objects are always root set objects, so there's no need to worry
     *   about fixups 
     */
    ext->meta_idx = osrp2(ptr+2);
    ext->mod_obj = (vm_obj_id_t)t3rp4u(ptr+4);

    /* if we have a class state value, read it */
    ext->class_state.set_nil();
    if (siz >= 2+4+VMB_DATAHOLDER)
        vmb_get_dh(ptr+8, &ext->class_state);
        
    /* register myself */
    register_meta(vmg_ self);
}
Exemple #3
0
/*
 *   Get only the value portion of a vm_val_t from a portable data holder 
 */
void vmb_get_dh_val(const char *buf, vm_val_t *val)
{
    /* read the format appropriate to the type */
    switch((vm_datatype_t)buf[0])
    {
    case VM_OBJ:
    case VM_OBJX:
        /* get the object ID from the UINT4 */
        val->val.obj = (vm_obj_id_t)t3rp4u(buf+1);
        break;

    case VM_PROP:
        /* get the property ID from the UINT2 */
        val->val.prop = (vm_prop_id_t)osrp2(buf+1);
        break;

    case VM_INT:
        val->val.intval = osrp4(buf+1);
        break;

    case VM_BIFPTR:
    case VM_BIFPTRX:
        /* read the function index and set index as UINT2s */
        val->val.bifptr.func_idx = osrp2(buf+1);
        val->val.bifptr.set_idx = osrp2(buf+3);
        break;

    case VM_ENUM:
        /* get the enumerated constant value from the UINT4 */
        val->val.enumval = t3rp4u(buf+1);
        break;

    case VM_SSTRING:
    case VM_DSTRING:
    case VM_LIST:
    case VM_CODEOFS:
    case VM_FUNCPTR:
        /* get the offset value from the UINT4 */
        val->val.ofs = t3rp4u(buf+1);
        break;

    default:
        /* other types have no additional data or cannot be put in a DH */
        break;
    }
}
Exemple #4
0
/*
 *   Show an exception table 
 */
void CTcT3Unasm::show_exc_table(class CTcUnasSrc *src, class CTcUnasOut *out,
                                unsigned long base_ofs)
{
    unsigned entries;
    char ch[10];
    
    /* read the number of entries */
    src->next_byte(ch);
    src->next_byte(ch+1);

    /* show the entries */
    for (entries = osrp2(ch) ; entries != 0 ; --entries)
    {
        unsigned long start_ofs;
        unsigned long end_ofs;
        unsigned exc_obj_id;
        unsigned long catch_ofs;
        
        /* read the code start offset */
        src->next_byte(ch);
        src->next_byte(ch+1);
        start_ofs = base_ofs + osrp2(ch);

        /* read the code end offset */
        src->next_byte(ch);
        src->next_byte(ch+1);
        end_ofs = base_ofs + osrp2(ch);

        /* read the object ID */
        src->next_byte(ch);
        src->next_byte(ch+1);
        src->next_byte(ch+2);
        src->next_byte(ch+3);
        exc_obj_id = base_ofs + t3rp4u(ch);

        /* read the catch offset */
        src->next_byte(ch);
        src->next_byte(ch+1);
        catch_ofs = base_ofs + osrp2(ch);

        /* show it */
        out->print("    from %lx to %lx object %x catch %lx\n",
                   start_ofs, end_ofs, exc_obj_id, catch_ofs);
    }
}
/*
 *   Read a fixup list from an object file 
 */
void CTcAbsFixup::
   load_fixup_list_from_object_file(CVmFile *fp,
                                    const textchar_t *obj_fname,
                                    CTcAbsFixup **list_head)
{
    uint fixup_cnt;

    /* read the fixups */
    for (fixup_cnt = fp->read_uint2() ; fixup_cnt != 0 ; --fixup_cnt)
    {
        char buf[5];
        char stream_id;
        ulong fixup_ofs;
        CTcDataStream *stream;

        /* read the fixup data */
        fp->read_bytes(buf, 5);
        stream_id = buf[0];
        fixup_ofs = t3rp4u(buf+1);

        /* find the stream for the ID */
        stream = CTcDataStream::get_stream_from_id(stream_id, obj_fname);

        /* if the stream is invalid, ignore this record */
        if (stream == 0)
            continue;

        /* 
         *   the fixup offset is relative to the starting offset of the
         *   stream for the current object file - adjust it accordingly 
         */
        fixup_ofs += stream->get_object_file_start_ofs();

        /* create the fixup and add it to the list */
        add_abs_fixup(list_head, stream, fixup_ofs);
    }
}
Exemple #6
0
/*
 *   load a Global Symbols block
 */
void CVmImageLoader::load_gsym(VMG_ ulong siz)
{
    char buf[TOK_SYM_MAX_LEN + 128];

    /* 
     *   if there's no global symbol table, merely load into the runtime
     *   symbol table, since we don't seem to need the information for
     *   debugging 
     */
    if (G_prs->get_global_symtab() == 0)
    {
        /* load it into the runtime reflection symbol table */
        load_runtime_symtab_from_gsym(vmg_ siz);

        /* we're done */
        return;
    }

    /* 
     *   remember the starting seek position and size, so we can re-read the
     *   block into the runtime symbol table 
     */
    long init_seek_pos = fp_->get_seek();
    ulong init_siz = siz;

    /* 
     *   note that we have a GSYM block - this implies that the image was
     *   linked for debugging 
     */
    has_gsym_ = TRUE;

    /* read the symbol count */
    read_data(buf, 4, &siz);
    ulong cnt = t3rp4u(buf);

    /* read the symbols and populate the global symbol table */
    for ( ; cnt != 0 ; --cnt)
    {
        char *sym_name;
        size_t sym_len;
        size_t dat_len;
        CTcSymbol *sym;
        tc_symtype_t sym_type;
        char *dat;
        
        /* read the symbol's length, extra data length, and type code */
        read_data(buf, 6, &siz);
        sym_len = osrp2(buf);
        dat_len = osrp2(buf + 2);
        sym_type = (tc_symtype_t)osrp2(buf + 4);

        /* check the lengths to make sure they don't overflow our buffer */
        if (sym_len > TOK_SYM_MAX_LEN)
        {
            /* 
             *   this symbol name is too long - skip the symbol and its
             *   extra data entirely
             */
            skip_data(sym_len + dat_len, &siz);

            /* go on to the next symbol */
            continue;
        }
        else if (dat_len + sym_len > sizeof(buf))
        {
            /* 
             *   the extra data block is too long - truncate the extra
             *   data so that we don't overflow our buffer, but proceed
             *   anyway with the truncated extra data 
             */
            read_data(buf, sizeof(buf), &siz);

            /* skip the remainder of the extra data */
            skip_data(sym_len + dat_len - sizeof(buf), &siz);
        }
        else
        {
            /* read the symbol's name and its type-specific data */
            read_data(buf, sym_len + dat_len, &siz);
        }

        /* get the pointer to the extra data (after the name) */
        dat = buf + sym_len;

        /* 
         *   allocate a copy of the symbol name in parser memory - this is
         *   necessary because the symbol objects themselves always come
         *   from parser memory, and hence never get individually deleted 
         */
        sym_name = (char *)G_prsmem->alloc(sym_len);
        memcpy(sym_name, buf, sym_len);

        /* create the new symbol table entry, depending on its type */
        switch(sym_type)
        {
        case TC_SYM_FUNC:
            /* create the function symbol */
            sym = new CTcSymFunc(
                sym_name, sym_len, FALSE,
                (int)osrp2(dat + 4),                                /* argc */

                /* 
                 *   the optional argument count is present in 3.1+ records,
                 *   which are at least 10 bytes; otherwise there aren't any
                 *   optional arguments 
                 */
                (dat_len >= 10 ? osrp2(dat+8) : 0),             /* opt_argc */
                
                dat[6] != 0,                                     /* varargs */
                dat[7] != 0,                                  /* has_retval */
                FALSE,                                    /* is_multimethod */
                FALSE,                               /* is_multimethod_base */
                FALSE);                                        /* is_extern */

            /* add the reverse mapping entry */
            G_debugger->add_rev_sym(sym_name, sym_len, sym_type, t3rp4u(dat));

            /* set the function's absolute address */
            ((CTcSymFunc *)sym)->set_abs_addr(t3rp4u(dat));
            break;

        case TC_SYM_OBJ:
            /* create the object symbol */
            sym = new CTcSymObj(sym_name, sym_len, FALSE, t3rp4u(dat), FALSE,
                                TC_META_TADSOBJ, 0);

            /* if there's a modifying object, store it */
            if (dat_len >= 8)
                ((CTcSymObj *)sym)->set_modifying_obj_id(t3rp4u(dat + 4));
            else
                ((CTcSymObj *)sym)->set_modifying_obj_id(VM_INVALID_OBJ);

            /* add the reverse mapping entry */
            G_debugger->add_rev_sym(sym_name, sym_len, sym_type, t3rp4u(dat));
            break;

        case TC_SYM_PROP:
            /* create the property symbol */
            sym = new CTcSymProp(sym_name, sym_len, FALSE, osrp2(dat));

            /* set the 'dictionary property' flag if present */
            if (dat_len >= 3 && (buf[2] & 1) != 0)
                ((CTcSymProp *)sym)->set_vocab(TRUE);

            /* add the reverse mapping entry */
            G_debugger->add_rev_sym(sym_name, sym_len, sym_type, osrp2(dat));
            break;

        case TC_SYM_ENUM:
            /* create the enumerator symbol */
            sym = new CTcSymEnum(sym_name, sym_len, FALSE,
                                 t3rp4u(dat),
                                 (dat_len >= 5 && (buf[4] & 1) != 0));

            /* add the reverse mapping entry */
            G_debugger->add_rev_sym(sym_name, sym_len, sym_type, t3rp4u(dat));
            break;

        case TC_SYM_BIF:
            /* create the built-in function symbol */
            sym = new CTcSymBif(sym_name, sym_len, FALSE,
                                osrp2(dat + 2),          /* function set ID */
                                osrp2(dat),               /* function index */
                                dat[4] != 0,                  /* has_retval */
                                osrp2(dat + 5),                 /* min_argc */
                                osrp2(dat + 7),                 /* max_argc */
                                dat[9] != 0);                    /* varargs */

            /* add the reverse mapping entry */
            G_debugger->add_rev_sym(sym_name, sym_len, sym_type,
                                    (osrp2(dat+2) << 16) | osrp2(dat));
            break;

        case TC_SYM_EXTFN:
            /* not currently supported */
            sym = 0;
            break;

        case TC_SYM_METACLASS:
            /* create the metaclass symbol */
            sym = new CTcSymMetaclass(sym_name, sym_len, FALSE,
                                      osrp2(dat), t3rp4u(dat + 2));

            /* 
             *   add a reverse mapping symbol for the object instance
             *   (note that we add this as an object, not a metaclass,
             *   since it refers to the IntrinsicClass instance) 
             */
            if ((vm_obj_id_t)t3rp4u(dat + 2) != VM_INVALID_OBJ)
                G_debugger->add_rev_sym(sym_name, sym_len,
                                        TC_SYM_OBJ, t3rp4u(dat + 2));
            break;

        default:
            /* ignore other types of symbols */
            sym = 0;
            break;
        }

        /* if the symbol was valid, add it to the global symbol table */
        if (sym != 0)
            G_prs->get_global_symtab()->add_entry(sym);
    }

    /*
     *   Seek back to the starting position, and then load the GSYM data
     *   into the runtime reflection symbol table 
     */
    fp_->seek(init_seek_pos);
    load_runtime_symtab_from_gsym(vmg_ init_siz);
}
/*
 *   Read a stream from an object file 
 */
void CTcDataStream::load_object_file(CVmFile *fp,
                                     const textchar_t *fname)
{
    ulong stream_len;
    ulong rem;
    char buf[1024];
    ulong start_ofs;
    ulong anchor_cnt;

    /* read the length of the stream */
    stream_len = fp->read_uint4();

    /* remember my starting offset */
    start_ofs = get_ofs();

    /* read the stream bytes */
    for (rem = stream_len ; rem != 0 ; )
    {
        size_t cur;

        /* read up to a buffer-full, or however much is left */
        cur = sizeof(buf);
        if (cur > rem)
            cur = rem;

        /* read this chunk */
        fp->read_bytes(buf, cur);

        /* add this chunk to the stream */
        write(buf, cur);

        /* deduct the amount we've read from the amount remaining */
        rem -= cur;
    }

    /*
     *   Read the anchors.  For each anchor, we must fix up the anchor by
     *   adding the base address of the stream we just read - the original
     *   anchor offsets in the object file reflect a base stream offset of
     *   zero, but we could be loading the stream after a bunch of other
     *   data have already been loaded into the stream.
     *   
     *   First, read the number of anchors, then loop through the anchors
     *   and read each one.  
     */
    for (anchor_cnt = fp->read_uint4() ; anchor_cnt != 0 ;
         --anchor_cnt)
    {
        ulong anchor_ofs;
        size_t sym_len;
        CTcStreamAnchor *anchor;
        
        /* read this anchor */
        fp->read_bytes(buf, 6);

        /* get the offset, and adjust for the new stream base offset */
        anchor_ofs = t3rp4u(buf) + start_ofs;

        /* get the length of the owning symbol's name, if any */
        sym_len = osrp2(buf+4);

        /* if there's a symbol name, read it */
        if (sym_len != 0)
        {
            CTcSymbol *owner_sym;
            
            /* read the symbol name */
            fp->read_bytes(buf, sym_len);

            /* look it up in the global symbol table */
            owner_sym = G_prs->get_global_symtab()->find(buf, sym_len);
            if (owner_sym == 0)
            {
                /* 
                 *   the owner symbol doesn't exist - this is an internal
                 *   inconsistency in the object file, because the anchor
                 *   symbol must always be defined in the same file and
                 *   hence should have been loaded already; complain and
                 *   go on 
                 */
                G_tcmain->log_error(0, 0, TC_SEV_ERROR,
                                    TCERR_OBJFILE_INT_SYM_MISSING,
                                    (int)sym_len, buf, fname);

                /* we can't create the anchor */
                anchor = 0;
            }
            else
            {
                /* create the anchor based on the symbol */
                anchor = add_anchor(owner_sym,
                                    owner_sym->get_fixup_list_anchor(),
                                    anchor_ofs);

                /* set the anchor in the symbol */
                owner_sym->set_anchor(anchor);
            }
        }
        else
        {
            /* create the anchor with no external references */
            anchor = add_anchor(0, 0, anchor_ofs);
        }

        /* load the fixup list */
        CTcAbsFixup::
            load_fixup_list_from_object_file(fp, fname,
                                             anchor->fixup_list_head_);
    }
}
/*
 *   Read an object ID fixup list from an object file 
 */
void CTcIdFixup::load_object_file(CVmFile *fp,
                                  const void *xlat,
                                  ulong xlat_cnt,
                                  tcgen_xlat_type xlat_type,
                                  size_t stream_element_size,
                                  const textchar_t *fname,
                                  CTcIdFixup **fixup_list_head)
{
    ulong cnt;

    /* read the count, then read the fixups */
    for (cnt = fp->read_uint4() ; cnt != 0 ; --cnt)
    {
        char buf[9];
        ulong ofs;
        ulong old_id;
        ulong new_id;
        CTcDataStream *stream;
        
        /* read the next fixup */
        fp->read_bytes(buf, 9);
        stream = CTcDataStream::get_stream_from_id(buf[0], fname);
        ofs = t3rp4u(buf+1);
        old_id = t3rp4u(buf+5);

        /* if the stream was invalid, ignore this record */
        if (stream == 0)
            continue;

        /* adjust the offset for the stream's start in this object file */
        ofs += stream->get_object_file_start_ofs();

        /* apply the fixup if a translation table was provided */
        if (xlat != 0)
        {
            /* make sure the count is in range - if it's not, ignore it */
            if (old_id >= xlat_cnt)
            {
                /* note the problem */
                G_tcmain->log_error(0, 0, TC_SEV_ERROR,
                                    TCERR_OBJFILE_INVAL_OBJ_ID, fname);
                
                /* ignore the record */
                continue;
            }
            
            /* look up the new ID */
            switch(xlat_type)
            {
            case TCGEN_XLAT_OBJ:
                new_id = ((const tctarg_obj_id_t *)xlat)[old_id];
                break;

            case TCGEN_XLAT_PROP:
                new_id = ((const tctarg_prop_id_t *)xlat)[old_id];
                break;

            case TCGEN_XLAT_ENUM:
                new_id = ((const ulong *)xlat)[old_id];
                break;
            }
            
            /* apply the fixup */
            if (stream_element_size == 2)
                stream->write2_at(ofs, (uint)new_id);
            else
                stream->write4_at(ofs, new_id);
        }
        else
        {
            /* use the original ID for now */
            new_id = old_id;
        }

        /* 
         *   If we're keeping object fixups in the new file, create a
         *   fixup for the reference.  Note that the fixup is for the new
         *   ID, not the old ID, because we've already translated the
         *   value in the stream to the new ID.  
         */
        if (fixup_list_head != 0)
            CTcIdFixup::add_fixup(fixup_list_head, stream, ofs, new_id);
    }
}
Exemple #9
0
/*
 *   Find a resource in a tads 2 game file 
 */
static int t2_find_res(osfildef *fp, const char *resname,
                       tads_resinfo *info)
{
    char buf[300];
    unsigned long startpos;
    size_t resname_len;
    int found;

    /* we haven't found what we're looking for yet */
    found = FALSE;

    /* note the length of the name we're seeking */
    resname_len = strlen(resname);

    /* 
     *   note the seek location of the start of the tads 2 game file stream
     *   within the file - if the game file is embedded in a larger file
     *   stream, the seek locations we find within the file are relative to
     *   this starting location 
     */
    startpos = osfpos(fp);

    /* 
     *   skip past the tads 2 file header (13 bytes for the signature, 7
     *   bytes for the version header, 2 bytes for the flags, 26 bytes for
     *   the timestamp) 
     */
    osfseek(fp, 13 + 7 + 2 + 26, OSFSK_CUR);

    /* 
     *   scan the sections in the file; stop on $EOF, and skip everything
     *   else but HTMLRES, which is the section type that 
     */
    for (;;)
    {
        unsigned long endofs;
        
        /* read the section type and next-section pointer */
        if (osfrb(fp, buf, 1)
            || osfrb(fp, buf + 1, (int)((unsigned char)buf[0] + 4)))
        {
            /* failed to read it - give up */
            return FALSE;
        }

        /* note the ending position of this section */
        endofs = t3rp4u(buf + 1 + (unsigned char)buf[0]);

        /* check the type */
        if (buf[0] == 7 && memcmp(buf+1, "HTMLRES", 7) == 0)
        {
            unsigned long entry_cnt;
            unsigned long i;
            
            /* 
             *   It's a multimedia resource block.  Read the index table
             *   header (which contains the number of entries and a reserved
             *   uint32).  
             */
            if (osfrb(fp, buf, 8))
                return FALSE;

            /* get the number of entries from the header */
            entry_cnt = t3rp4u(buf);

            /* read the entries */
            for (i = 0 ; i < entry_cnt ; ++i)
            {
                unsigned long res_ofs;
                unsigned long res_siz;
                unsigned short name_len;

                /* read the entry header */
                if (osfrb(fp, buf, 10))
                    return FALSE;

                /* parse the header */
                res_ofs = t3rp4u(buf);
                res_siz = t3rp4u(buf + 4);
                name_len = osrp2(buf + 8);

                /* read the entry's name */
                if (name_len > sizeof(buf) || osfrb(fp, buf, name_len))
                    return FALSE;

                /* 
                 *   if it matches the name we're looking for, note that we
                 *   found it 
                 */
                if (name_len == resname_len
                    && memicmp(resname, buf, name_len) == 0)
                {
                    /* 
                     *   note that we found it, and note its resource size
                     *   and offset in the return structure - but keep
                     *   scanning the rest of the directory, since we need
                     *   to know where the directory ends to know where the
                     *   actual resources begin 
                     */
                    found = TRUE;
                    info->seek_pos = res_ofs;
                    info->siz = res_siz;
                }
            }

            /* 
             *   if we found our resource, the current seek position is the
             *   base of the offset we found in the directory; so fix up the
             *   offset to give the actual file location 
             */
            if (found)
            {
                /* fix up the offset with the actual file location */
                info->seek_pos += osfpos(fp);

                /* tell the caller we found it */
                return TRUE;
            }

            /* we didn't find it - seek to the end of this section */
            osfseek(fp, endofs + startpos, OSFSK_SET);
        }
        else if (buf[0] == 4 && memcmp(buf+1, "$EOF", 4) == 0)
        {
            /* 
             *   that's the end of the file - we've finished without finding
             *   the resource, so return failure 
             */
            return FALSE;
        }
        else
        {
            /* 
             *   this isn't a section we're interested in - skip to the end
             *   of the section and keep going
             */
            osfseek(fp, endofs + startpos, OSFSK_SET);
        }
    }
}
Exemple #10
0
/*
 *   Find a resource in a T3 image file
 */
static int t3_find_res(osfildef *fp, const char *resname,
                       tads_resinfo *info)
{
    char buf[256];
    size_t resname_len;
    
    /* note the length of the name we're seeking */
    resname_len = strlen(resname);

    /* 
     *   skip the file header - 11 bytes for the signature, 2 bytes for the
     *   format version, 32 reserved bytes, and 24 bytes for the timestamp 
     */
    osfseek(fp, 11 + 2 + 32 + 24, OSFSK_CUR);

    /* scan the data blocks */
    for (;;)
    {
        unsigned long siz;
        
        /* read the block header */
        if (osfrb(fp, buf, 10))
            return FALSE;

        /* get the block size */
        siz = t3rp4u(buf + 4);

        /* check the type */
        if (memcmp(buf, "MRES", 4) == 0)
        {
            unsigned long base_ofs;
            unsigned int entry_cnt;
            unsigned int i;

            /* 
             *   remember the current seek position - the data seek location
             *   for each index entry is given as an offset from this
             *   location 
             */
            base_ofs = osfpos(fp);

            /* read the number of entries */
            if (osfrb(fp, buf, 2))
                return FALSE;

            /* parse the entry count */
            entry_cnt = osrp2(buf);

            /* read the entries */
            for (i = 0 ; i < entry_cnt ; ++i)
            {
                unsigned long entry_ofs;
                unsigned long entry_siz;
                unsigned int entry_name_len;
                char *p;
                size_t rem;

                /* read this index entry's header */
                if (osfrb(fp, buf, 9))
                    return FALSE;

                /* parse the header */
                entry_ofs = t3rp4u(buf);
                entry_siz = t3rp4u(buf + 4);
                entry_name_len = (unsigned char)buf[8];

                /* read the entry's name */
                if (osfrb(fp, buf, entry_name_len))
                    return FALSE;

                /* XOR the bytes of the name with 0xFF */
                for (p = buf, rem = entry_name_len ; rem != 0 ; ++p, --rem)
                    *p ^= 0xFF;

                /* if this is the one we're looking for, return it */
                if (entry_name_len == resname_len
                    && memicmp(resname, buf, resname_len) == 0)
                {
                    /* 
                     *   fill in the return information - note that the
                     *   entry offset given in the header is an offset from
                     *   data block's starting location, so fix this up to
                     *   an absolute seek location for the return value
                     */
                    info->seek_pos = base_ofs + entry_ofs;
                    info->siz = entry_siz;

                    /* return success */
                    return TRUE;
                }
            }
        }
        else if (memcmp(buf, "EOF ", 4) == 0)
        {
            /* 
             *   end of file - we've finished without finding the resource,
             *   so return failure 
             */
            return FALSE;
        }
        else
        {
            /* 
             *   we don't care about anything else - just skip this block
             *   and keep going; to skip the block, simply seek ahead by the
             *   size of the block's contents as given in the block header 
             */
            osfseek(fp, siz, OSFSK_CUR);
        }
    }
}
Exemple #11
0
/*
 *   disassemble an instruction
 */
void CTcT3Unasm::disasm_instr(CTcUnasSrc *src, CTcUnasOut *out, char ch_op)
{
    t3_instr_info_t *info;
    int i;
    ulong acc;
    char ch[10];
    ulong prv_ofs = src->get_ofs();
    
    /* get the information on this instruction */
    info = &instr_info[(int)(uchar)ch_op];
    out->print("%8lx  %-14.14s ", src->get_ofs() - 1, info->nm);

    /* check the instruction type */
    switch((uchar)ch_op)
    {
    case OPC_SWITCH:
        /* 
         *   It's a switch instruction - special handling is required,
         *   since this instruction doesn't fit any of the normal
         *   patterns.  First, get the number of elements in the case
         *   table - this is a UINT2 value at the start of the table.  
         */
        src->next_byte(ch);
        src->next_byte(ch+1);
        acc = osrp2(ch);

        /* display the count */
        out->print("0x%x\n", (uint)acc);

        /* display the table */
        for (i = 0 ; i < (int)acc ; ++i)
        {
            const char *dt;
            char valbuf[128];
            const char *val = valbuf;

            /* note the current offset */
            prv_ofs = src->get_ofs();
            
            /* read the DATAHOLDER value */
            src->next_byte(ch);
            src->next_byte(ch+1);
            src->next_byte(ch+2);
            src->next_byte(ch+3);
            src->next_byte(ch+4);

            /* read the jump offset */
            src->next_byte(ch+5);
            src->next_byte(ch+6);

            /* 
             *   stop looping if the offset hasn't changed - this probably
             *   means we're stuck trying to interpret as a "switch" some
             *   data at the end of the stream that happens to look like a
             *   switch but really isn't (such as an exception table, or
             *   debug records) 
             */
            if (src->get_ofs() == prv_ofs)
                break;

            /* show the value */
            switch(ch[0])
            {
            case VM_NIL:
                dt = "nil";
                val = "";
                break;
                
            case VM_TRUE:
                dt = "true";
                val = "";
                break;
                
            case VM_OBJ:
                dt = "object";
                sprintf(valbuf, "0x%08lx", t3rp4u(ch+1));
                break;
                
            case VM_PROP:
                dt = "prop";
                sprintf(valbuf, "0x%04x", osrp2(ch+1));
                break;
                
            case VM_INT:
                dt = "int";
                sprintf(valbuf, "0x%08lx", t3rp4u(ch+1));
                break;

            case VM_ENUM:
                dt = "enum";
                sprintf(valbuf, "0x%08lx", t3rp4u(ch+1));
                break;
                
            case VM_SSTRING:
                dt = "sstring";
                sprintf(valbuf, "0x%08lx", t3rp4u(ch+1));
                break;
                
            case VM_LIST:
                dt = "list";
                sprintf(valbuf, "0x%08lx", t3rp4u(ch+1));
                break;
                
            case VM_FUNCPTR:
                dt = "funcptr";
                sprintf(valbuf, "0x%08lx", t3rp4u(ch+1));
                break;

            default:
                dt = "???";
                val = "???";
                break;
            }

            /* show the slot data */
            out->print("          0x%08lx      %-8.8s(%-10.10s) "
                       "-> +0x%04lx (0x%08lx)\n",
                       src->get_ofs() - 7, dt, val, osrp2(ch+5),
                       src->get_ofs() - 2 + osrp2s(ch+5));
        }

        /* read and show the 'default' jump offset */
        src->next_byte(ch);
        src->next_byte(ch+1);
        out->print("          0x%08lx      default              "
                   "-> +0x%04lx (0x%08lx)\n",
                   src->get_ofs() - 2, osrp2(ch),
                   src->get_ofs() - 2 + osrp2s(ch));

        /* done */
        break;

    default:
        /* show all parameters */
        for (i = 0 ; i < info->op_cnt ; ++i)
        {
            /* add a separator if this isn't the first one */
            if (i != 0)
                out->print(", ");
            
            /* display the operand */
            switch(info->op_type[i])
            {
            case T3OP_TYPE_8S:
                /* 8-bit signed integer */
                src->next_byte(ch);
                out->print("0x%x", (int)ch[0]);
                break;

            case T3OP_TYPE_8U:
                /* 8-bit unsigned integer */
                src->next_byte(ch);
                out->print("0x%x", (uint)(uchar)ch[0]);
                break;

            case T3OP_TYPE_16S:
                /* 16-bit signed integer */
                src->next_byte(ch);
                src->next_byte(ch+1);
                acc = osrp2s(ch);
                out->print("0x%x", (int)acc);
                break;

            case T3OP_TYPE_16U:
                /* 16-bit unsigned integer */
                src->next_byte(ch);
                src->next_byte(ch+1);
                acc = osrp2(ch);
                out->print("0x%x", (uint)acc);
                break;

            case T3OP_TYPE_32S:
                /* 32-bit signed integer */
                src->next_byte(ch);
                src->next_byte(ch+1);
                src->next_byte(ch+2);
                src->next_byte(ch+3);
                acc = t3rp4u(ch);
                out->print("0x%lx", acc);
                break;

            case T3OP_TYPE_32U:
                /* 32-bit unsigned integer */
                src->next_byte(ch);
                src->next_byte(ch+1);
                src->next_byte(ch+2);
                src->next_byte(ch+3);
                acc = t3rp4u(ch);
                out->print("0x%lx", acc);
                break;

            case T3OP_TYPE_STR:
                /* string offset */
                src->next_byte(ch);
                src->next_byte(ch+1);
                src->next_byte(ch+2);
                src->next_byte(ch+3);
                acc = t3rp4u(ch);
                out->print("string(0x%lx)", acc);
                break;

            case T3OP_TYPE_LIST:
                /* list offset */
                src->next_byte(ch);
                src->next_byte(ch+1);
                src->next_byte(ch+2);
                src->next_byte(ch+3);
                acc = t3rp4u(ch);
                out->print("list(0x%lx)", acc);
                break;

            case T3OP_TYPE_CODE_ABS:
                /* 32-bit absolute code address */
                src->next_byte(ch);
                src->next_byte(ch+1);
                src->next_byte(ch+2);
                src->next_byte(ch+3);
                acc = t3rp4u(ch);
                out->print("code(0x%08lx)", acc);
                break;

            case T3OP_TYPE_CODE_REL:
                /* 16-bit relative code address */
                src->next_byte(ch);
                src->next_byte(ch+1);
                acc = osrp2s(ch);
                if ((long)acc < 0)
                    out->print("-0x%04x (0x%08lx)",
                               -(int)acc, src->get_ofs() - 2 + acc);
                else
                    out->print("+0x%04x (0x%08lx)",
                               acc, src->get_ofs() - 2 + acc);
                break;

            case T3OP_TYPE_OBJ:
                /* object ID */
                src->next_byte(ch);
                src->next_byte(ch+1);
                src->next_byte(ch+2);
                src->next_byte(ch+3);
                acc = t3rp4u(ch);
                out->print("object(0x%lx)", acc);
                break;

            case T3OP_TYPE_PROP:
                /* property ID */
                src->next_byte(ch);
                src->next_byte(ch+1);
                acc = osrp2(ch);
                out->print("property(0x%x)", (uint)acc);
                break;

            case T3OP_TYPE_ENUM:
                /* enum */
                src->next_byte(ch);
                src->next_byte(ch+1);
                src->next_byte(ch+2);
                src->next_byte(ch+3);
                acc = t3rp4u(ch);
                out->print("enum(0x%lx)", acc);
                break;

            case T3OP_TYPE_CTX_ELE:
                /* context element identifier */
                src->next_byte(ch);
                switch(ch[0])
                {
                case PUSHCTXELE_TARGPROP:
                    out->print("targetprop");
                    break;

                case PUSHCTXELE_TARGOBJ:
                    out->print("targetobj");
                    break;

                case PUSHCTXELE_DEFOBJ:
                    out->print("definingobj");
                    break;

                default:
                    out->print("0x%x", (int)ch[0]);
                    break;
                }
                break;

            case T3OP_TYPE_INLINE_STR:
                /* get the string length */
                src->next_byte(ch);
                src->next_byte(ch+1);

                /* show it */
                out->print("string(inline)");

                /* skip the string */
                for (acc = osrp2(ch) ; acc != 0 ; --acc)
                    src->next_byte(ch);

                /* done */
                break;

            default:
                out->print("...unknown type...");
                break;
            }
        }

        /* end the line */
        out->print("\n");
    }
}