Beispiel #1
0
/*
 * Deals with LX and LE images.
 * We must try grab information from the object table.
 */
static dip_status FindHLLInLXImage( imp_image_handle *ii, unsigned long nh_off )
{
    union  {
        os2_flat_header flat;
        object_record   obj;
    }                   buf;
    dip_status          rc;

    /* read the header */
    rc = DCReadAt( ii->sym_file, &buf.flat, sizeof( buf.flat ), nh_off );
    if( rc & DS_ERR ) {
        return( rc );
    }
    rc = DS_FAIL;
    if( buf.flat.debug_off && buf.flat.debug_len ) {
        ii->is_32bit = 1;
        rc = FoundHLLSign( ii, buf.flat.debug_off, buf.flat.debug_len );
        if( rc == DS_OK ) {
            unsigned i;

            /*
             * Get segment info from the object table.
             */
            if ( DCSeek( ii->sym_file, buf.flat.objtab_off + nh_off, DIG_ORG )
              != buf.flat.objtab_off + nh_off ) {
                return( DS_ERR | DS_FSEEK_FAILED );
            }

            ii->seg_count = buf.flat.num_objects;
            ii->segments = DCAlloc( sizeof( hllinfo_seg ) * ii->seg_count );
            if( ii->segments == NULL ) {
                return( DS_ERR | DS_NO_MEM );
            }

            for( i = 0; i < ii->seg_count; i++ ) {
                if( DCRead( ii->sym_file, &buf.obj, sizeof( buf.obj ) )
                 != sizeof( buf.obj )) {
                    return( DS_ERR | DS_FREAD_FAILED );
                }
                ii->segments[i].is_executable = !!( buf.obj.flags & OBJ_EXECUTABLE );
                ii->segments[i].is_16bit = !( buf.obj.flags & OBJ_BIG );
                ii->segments[i].ovl = 0;
                ii->segments[i].map.offset = 0;
                ii->segments[i].map.segment = i + 1;
                ii->segments[i].size = buf.obj.size;
                ii->segments[i].address = buf.obj.addr;
            }
        }
    }
    return( rc );
}
Beispiel #2
0
/*
 * Tries to find the HLL/CV debug info in a image which format we know.
 * This function knows about LX, LE, PE and watcom symfile images.
 */
static dip_status TryFindInImage( imp_image_handle *ii )
{
    union {
        char            sig[HLL_SIG_SIZE]; /* ASSUMES >= 4 */
        unsigned_16     sig_16;
        unsigned_32     sig_32;
        pe_header       pe;
        pe_object       sh;
        debug_directory dbg_dir;
    }                   buf;
    bool                have_mz_header = FALSE;
    unsigned_32         nh_off;
    dip_status          rc;

    /* Read the image header. */
    rc = DCReadAt( ii->sym_file, &buf.sig, sizeof( buf.sig ), 0 );
    if( rc & DS_ERR ) {
        return( rc );
    }
    nh_off = 0;
    if( buf.sig_16 == DOS_SIGNATURE ) {
        have_mz_header = TRUE;
        /* read the new exe header */
        rc = DCReadAt( ii->sym_file, &nh_off, sizeof( nh_off ), NH_OFFSET );
        if( rc & DS_ERR ) {
            return( rc );
        }
        rc = DCReadAt( ii->sym_file, &buf.sig, sizeof( buf.sig ), nh_off );
        if( rc & DS_ERR ) {
            return( rc );
        }
    }

    /*
     * LE/LX executable - Use the debug_off/len members of the header.
     */
    if( buf.sig_16 == OSF_FLAT_LX_SIGNATURE
     || buf.sig_16 == OSF_FLAT_SIGNATURE ) {
        return( FindHLLInLXImage( ii, nh_off ) );
    }

    /*
     * PE executable - Use or scan the debug directory.
     */
    if( buf.sig_32 == PE_SIGNATURE ) {
        return( FindHLLInPEImage( ii, nh_off ) );
    }

    /*
     * NE and MZ executables do not contain any special information
     * in the header. TryFindTrailer() will have to pick up the debug data.
     */
    if( (buf.sig_16 == OS2_SIGNATURE_WORD) || have_mz_header ) {
        ii->is_32bit = 0;
    }

    /*
     * ELF executable - ??????
     */

    /*
     * A watcom .sym file.
     */
    if( IsHllSignature( &buf ) ) {
        return( FoundHLLSign( ii, nh_off, ~0UL ) );
    }

    /* no idea what this is.. */
    return( DS_FAIL );
}
Beispiel #3
0
/*
 * Deals with 32-bit PE images.
 */
static dip_status FindHLLInPEImage( imp_image_handle *ii, unsigned long nh_off )
{
    dip_status          rc;
    unsigned_32         debug_rva;
    unsigned_32         debug_len;
    unsigned_32         image_base;
    unsigned            i;
    unsigned_32         sh_off;
    union {
        char            sig[HLL_SIG_SIZE]; /* ASSUMES >= 4 */
        unsigned_16     sig_16;
        unsigned_32     sig_32;
        pe_header       pe;
        pe_object       sh;
        debug_directory dbg_dir;
    }                   buf;

    /* read the header */
    rc = DCReadAt( ii->sym_file, &buf.pe, sizeof( buf.pe ), nh_off );
    if( rc & DS_ERR ) {
        return( rc );
    }

    debug_rva = buf.pe.table[ PE_TBL_DEBUG ].rva;
    debug_len = buf.pe.table[ PE_TBL_DEBUG ].size;
    if( !debug_rva || !debug_len ) {
        return( DS_FAIL );
    }
    ii->is_32bit = 1;
    image_base = buf.pe.image_base;

    /*
     * Translate the rva to a file offset and read necessary
     * segment information at the same time.
     */
    ii->seg_count = buf.pe.num_objects;
    ii->segments = DCAlloc( sizeof( hllinfo_seg ) * buf.pe.num_objects );
    if( ii->segments == NULL ) {
        return( DS_ERR | DS_NO_MEM );
    }

    sh_off = nh_off /* vv -- watcom mixes the headers :-( */
           + offsetof( pe_header, flags ) + sizeof( buf.pe.flags )
           + buf.pe.nt_hdr_size;

    for ( i = 0; i < ii->seg_count; i++, sh_off += sizeof( buf.sh ) ) {
        rc = DCReadAt( ii->sym_file, &buf.sh, sizeof( buf.sh ), sh_off );
        if ( rc & DS_ERR ) {
            return( rc );
        }

        /* collect segment info. */
        ii->segments[i].is_executable = !!( buf.sh.flags & PE_OBJ_CODE );
        ii->segments[i].ovl = 0;
        ii->segments[i].map.offset = 0;
        ii->segments[i].map.segment = i + 1;
        ii->segments[i].size = buf.sh.virtual_size; // FIXME: alignment?
        ii->segments[i].address = buf.sh.rva + image_base;

        /* is the debug directory section? */
        if( !ii->bias
         && debug_rva - buf.sh.rva < buf.sh.virtual_size ) {
            unsigned_32 debug_off;
            int         left;
            debug_off = buf.sh.physical_offset + debug_rva - buf.sh.rva;

            /*
             * The IBM linker screw up here. It will omit the debug
             * directory and put the debug info there instead.
             * So, before scanning we'll have to check for any HLL sign.
             */
            rc = DCReadAt( ii->sym_file, &buf.dbg_dir, sizeof( buf.dbg_dir ), debug_off );
            if( rc & DS_ERR ) {
                return( rc );
            }
            if( IsHllSignature( &buf ) ) {
                rc = FoundHLLSign( ii, debug_off, debug_len );
            } else {
                left = debug_len / sizeof( debug_directory );
                if( left < 16 )
                    left = 16;
                for ( ;; ) {
                    if( buf.dbg_dir.debug_type == DEBUG_TYPE_CODEVIEW ) {
                        /* found something? */
                        rc = FoundHLLSign( ii, buf.dbg_dir.data_seek, buf.dbg_dir.data_seek );
                        if( rc == DS_OK || rc & DS_ERR ) {
                            break;
                        }
                    }

                    /* next */
                    --left;
                    if( left <= 0) {
                        break;
                    }
                    if ( DCRead( ii->sym_file, &buf.dbg_dir, sizeof( buf.dbg_dir ) ) != sizeof( buf.dbg_dir ) ) {
                        break;
                    }
                }
            }
            if( rc & DS_ERR ) {
                return( rc );
            }
        }
    }

    return( ii->bias ? DS_OK : DS_FAIL );
}
Beispiel #4
0
/*
 * Validates the signatures of a HLL debug info block, determining
 * the length if necessary.
 */
static dip_status FoundHLLSign( imp_image_handle *ii, unsigned long off,
                                unsigned long size )
{
    dip_status          rc;
    hll_trailer         hdr;
    unsigned long       off_dirent, off_trailer;

    /* read the header. */
    rc = DCReadAt( ii->sym_file, &hdr, sizeof( hdr ), off );
    if( rc & DS_ERR) {
        return rc;
    }
    if( !IsHllSignature( &hdr ) ) {
        return DS_FAIL;
    }

    /*
     * Read the directory info - both to verify it and to find the trailer.
     */
    off_dirent = off + hdr.offset;
    if( !memcmp( hdr.sig, HLL_NB04, HLL_SIG_SIZE ) ) {
        hll_dirinfo     dir_hdr;

        rc = DCReadAt( ii->sym_file, &dir_hdr, sizeof( dir_hdr ), off_dirent );
        if( rc & DS_ERR) {
            return rc;
        }
        if( dir_hdr.cbDirHeader != sizeof( hll_dirinfo )
         || dir_hdr.cbDirEntry != sizeof( hll_dir_entry ) ) {
            return DS_FAIL;
        }
        ii->dir_count = dir_hdr.cDir;
        off_dirent += sizeof( dir_hdr );
        off_trailer = off_dirent + sizeof( hll_dir_entry ) * dir_hdr.cDir;
    } else {
        /* Old CV3 directory. */
        cv3_dirinfo     dir_hdr;

        rc = DCReadAt( ii->sym_file, &dir_hdr, sizeof( dir_hdr ), off_dirent );
        if( rc & DS_ERR) {
            return rc;
        }
        ii->dir_count = dir_hdr.cDir;
        off_dirent += sizeof( dir_hdr );
        off_trailer = off_dirent + sizeof( cv3_dir_entry ) * dir_hdr.cDir;
    }

    /* is the trailer following the directory? It usually is with wlink. */
    rc = DCReadAt( ii->sym_file, &hdr, sizeof( hdr ), off_trailer );
    if( rc & DS_ERR) {
        return rc;
    }
    if( !IsHllSignature( &hdr ) ) {
        /*
         * No it isn't, seek from the end (off + size).
         * Adjust the length first.
         */
        long        cur;
        unsigned    overlap = 0;

        cur = DCSeek( ii->sym_file, 0, DIG_END );
        if( cur > size + off && size + off > size ) {
            cur = off + size;
        }

        hdr.sig[0] = 0;
        do {
            char        buf[1024 + sizeof( hdr )];
            size_t      to_read;
            char        *ptr;

            /* read block */
            to_read = 1024 + overlap;
            cur    -= 1024;
            if( cur  < off_trailer ) {
                to_read += off_trailer - cur;
                cur = off_trailer;
            }
            if( to_read < sizeof( hdr) ) {
                return DS_FAIL;
            }
            rc = DCReadAt( ii->sym_file, buf, to_read, cur );
            if( rc & DS_ERR ) {
                return rc;
            }

            /* search it */
            for( ptr = &buf[to_read - sizeof( hdr )];
                 ptr >= &buf[0];
                 ptr--) {
                if( IsHllSignature(ptr) ) {
                    off_trailer = cur + ptr - &buf[0];
                    hdr = *(hll_trailer *)ptr;
                    break;
                }
            }

            /* next */
            overlap = sizeof( hdr );
        } while( hdr.sig[0] == 0 );
    }

    /*
     * Validate the trailer offset (=size).
     */
    if( off_trailer == off
     || hdr.offset != off_trailer - off + sizeof( hdr ) ) {
        return( DS_FAIL );
    }

    /*
     * We're good.
     */
    ii->bias = off;
    ii->size = off_trailer - off + sizeof( hdr );
    if ( !memcmp( hdr.sig, HLL_NB04, HLL_SIG_SIZE ) ) {
        ii->format_lvl = HLL_LVL_NB04;
    } else if ( !memcmp( hdr.sig, HLL_NB02, HLL_SIG_SIZE ) ) {
        ii->format_lvl = HLL_LVL_NB02;
    } else if( !memcmp( hdr.sig, HLL_NB00, HLL_SIG_SIZE ) ) {
        ii->format_lvl = ii->is_32bit ? HLL_LVL_NB00_32BIT : HLL_LVL_NB00;
    } else {
        hllConfused();
    }

    /*
     * Since we already know where the directory is, we load it here.
     */
    rc = LoadDirectory( ii, off_dirent );
    return( rc );
}