Beispiel #1
0
orl_return CoffLoadFileStructure( coff_file_handle coff_file_hnd )
/****************************************************************/
{
    orl_return          return_val;
    coff_file_header    *f_hdr;
    coff_quantity       sec_header_table_size;
    coff_quantity       buf_size;
    coff_sec_offset     string_table_index;
    coff_sec_handle     last_sec_hnd;
    coff_sec_handle     coff_sec_hnd;
    coff_quantity       i;
    coff_quantity       num_sections;
    pe_header           *pe_hdr;
    char                *PE;
    orl_file_offset     PEoffset = 0;
    coff_sec_size       *string_sec_size;

    pe_hdr = _ClientRead( coff_file_hnd, 2 );
    _ClientSeek( coff_file_hnd, -2, SEEK_CUR );
    if( pe_hdr->MZ[0] == 'M' && pe_hdr->MZ[1] == 'Z' ) {
        pe_hdr = _ClientRead( coff_file_hnd, sizeof( pe_header ) );
        _ClientSeek( coff_file_hnd, pe_hdr->offset - sizeof( pe_header ), SEEK_CUR );
        PE = _ClientRead( coff_file_hnd, 4 );
        if( PE[0] == 'P' && PE[1] == 'E' && PE[2] == '\0' && PE[3] == '\0' ) {
            PEoffset = pe_hdr->offset + 4;
        } else {
            _ClientSeek( coff_file_hnd, -(long)(pe_hdr->offset - 4), SEEK_CUR );
        }
    }
    coff_file_hnd->f_hdr_buffer = _ClientRead( coff_file_hnd, sizeof( coff_file_header ) );
    if( coff_file_hnd->f_hdr_buffer == NULL )
        return( ORL_OUT_OF_MEMORY );
    f_hdr = (coff_file_header *)coff_file_hnd->f_hdr_buffer;
    if( determine_file_specs( coff_file_hnd, f_hdr ) ) {
        // we have identified an import_object_header
        // convert short import library structures to long import
        // library structures, change _ClientRead and _ClientSeek
        // macros to read from converted metadata
        return_val = convert_import_library_init( coff_file_hnd );
        if ( return_val != ORL_OKAY ) {
            return( return_val );
        }
        // reread new converted file header and next process as normal
        coff_file_hnd->f_hdr_buffer = _ClientRead( coff_file_hnd, sizeof( coff_file_header ) );
        if( coff_file_hnd->f_hdr_buffer == NULL )
            return( ORL_OUT_OF_MEMORY );
        f_hdr = (coff_file_header *)coff_file_hnd->f_hdr_buffer;
        determine_file_specs( coff_file_hnd, f_hdr );
    }
    if( f_hdr->opt_hdr_size > 0 ) {     // skip/process optional header
        pe_opt_hdr *opt_hdr = (pe_opt_hdr *)_ClientRead( coff_file_hnd, f_hdr->opt_hdr_size );
        switch( opt_hdr->magic ) {
        case 0x10b:
            // PE  (32-bit)
            coff_file_hnd->export_table_rva = opt_hdr->pe32.export_table_rva;
            break;
        case 0x20b:
            // PE+ (64-bit)
            coff_file_hnd->flags |= ORL_FILE_FLAG_64BIT_MACHINE;
            coff_file_hnd->pe64 = true;
            coff_file_hnd->export_table_rva = opt_hdr->pe64.export_table_rva;
            break;
        default:
            coff_file_hnd->export_table_rva = 0;
            break;
        }
    }
    coff_file_hnd->initial_size = sizeof( coff_file_header ) + f_hdr->opt_hdr_size + PEoffset;
    switch( coff_file_hnd->machine_type ) {
    case ORL_MACHINE_TYPE_UNKNOWN:
        return( ORL_ERROR );
    default:
        break;
    }
    coff_file_hnd->num_symbols = f_hdr->num_symbols;
    coff_file_hnd->num_sections = f_hdr->num_sections;
    sec_header_table_size = coff_file_hnd->num_sections * sizeof( coff_section_header );
    if( coff_file_hnd->num_sections > 0 ) {
        coff_file_hnd->s_hdr_table_buffer = _ClientRead( coff_file_hnd, sec_header_table_size);
        if( coff_file_hnd->s_hdr_table_buffer == NULL ) {
            return( ORL_ERROR );
        }
    }
    return_val = load_coff_sec_handles( coff_file_hnd, f_hdr );
    if( return_val != ORL_OKAY ) {
        return( return_val );
    }
    last_sec_hnd = coff_file_hnd->coff_sec_hnd[coff_file_hnd->num_sections - 1];
    coff_file_hnd->initial_size += sec_header_table_size;

    buf_size = 0;
    for( i = 0; i < coff_file_hnd->num_sections; ++i ) {
        coff_sec_hnd = coff_file_hnd->coff_sec_hnd[i];
        if( (coff_sec_hnd->offset + coff_sec_hnd->size) > buf_size && (coff_sec_hnd->flags & ORL_SEC_FLAG_UNINITIALIZED_DATA) == 0 ) {
            buf_size = coff_sec_hnd->offset + coff_sec_hnd->size;
        }
    }
    coff_file_hnd->size = buf_size;
    buf_size -= coff_file_hnd->initial_size;
    coff_file_hnd->rest_of_file_buffer = _ClientRead( coff_file_hnd, buf_size );
    if( coff_file_hnd->rest_of_file_buffer == NULL ) {
        return( ORL_ERROR );
    }
    num_sections = coff_file_hnd->num_sections;
    // read string table; always follows the symbol table, but may not exist
    if( last_sec_hnd == coff_file_hnd->string_table ) {
        // read the string table size; if that fails, there isn't any
        if( f_hdr->sym_table ) {
            string_sec_size = _ClientRead( coff_file_hnd, sizeof( coff_sec_size ) );
            if( string_sec_size != NULL ) {
                last_sec_hnd->size = *string_sec_size;
            }
        }
        if( last_sec_hnd->size <= sizeof( coff_sec_size ) || last_sec_hnd->size > MAX_STRTAB_SIZE ) {
            last_sec_hnd->size = 0;
        }
        if( last_sec_hnd->size != 0 ) {
            last_sec_hnd->size -= sizeof( coff_sec_size );
        }
        if( last_sec_hnd->size > 0 && last_sec_hnd->offset != 0 ) {
            if( last_sec_hnd->offset == buf_size + coff_file_hnd->initial_size ) {
                last_sec_hnd->contents = _ClientRead( coff_file_hnd, last_sec_hnd->size );
                coff_file_hnd->size += last_sec_hnd->size;
            } else {
                last_sec_hnd->contents = coff_file_hnd->rest_of_file_buffer + last_sec_hnd->offset - coff_file_hnd->initial_size + sizeof( coff_sec_size );
            }
            if( last_sec_hnd->contents == NULL ) {
                return( ORL_ERROR );
            }
        } else {
            last_sec_hnd->contents = NULL;
        }
        num_sections--;
    }
    // determine contents pointers of all sections
    for( i = 0; i < num_sections; ++i ) {
        coff_sec_hnd = coff_file_hnd->coff_sec_hnd[i];
        if( (coff_sec_hnd->size > 0 || coff_sec_hnd->type == ORL_SEC_TYPE_STR_TABLE) && coff_sec_hnd->offset != 0 ) {
            coff_sec_hnd->contents = coff_file_hnd->rest_of_file_buffer + coff_sec_hnd->offset - coff_file_hnd->initial_size;
        }
    }
    if( last_sec_hnd != coff_file_hnd->string_table ) {
        memcpy( &(coff_file_hnd->string_table->size), coff_file_hnd->string_table->contents, sizeof( coff_sec_size ) );
        if( coff_file_hnd->string_table->size != 0 ) {
            coff_file_hnd->string_table->size -= sizeof( coff_sec_size );
            coff_file_hnd->string_table->contents += sizeof( coff_sec_size );
        }
    }
    // determine section names
    for( i = 0; i < coff_file_hnd->num_sections; ++i ) {
        coff_sec_hnd = coff_file_hnd->coff_sec_hnd[i];
        if( coff_sec_hnd->name[0] == '/' ) {
            // change pointer to point into string table
            string_table_index = atoi( coff_sec_hnd->name + 1 ) - sizeof( coff_sec_size );
            coff_sec_hnd->name = (char *)( coff_file_hnd->string_table->contents + string_table_index );
        }
    }
    return( ORL_OKAY );
}
Beispiel #2
0
orl_return CoffLoadFileStructure( coff_file_handle coff_file_hnd )
/****************************************************************/
{
    orl_return          error;
    coff_file_header *  f_hdr;
    coff_quantity       sec_header_table_size;
    coff_quantity       buf_size;
    coff_sec_offset     string_table_index;
    coff_sec_handle     last_sec_hnd;
    coff_sec_handle     coff_sec_hnd;
    int                 loop;
    int                 loop_limit;
    pe_header *         pe_hdr;
    char *              PE;
    orl_file_offset     PEoffset = 0;

    pe_hdr = _ClientRead( coff_file_hnd, 2 );
    _ClientSeek( coff_file_hnd, -2, SEEK_CUR );
    if( pe_hdr->MZ[0] == 'M' && pe_hdr->MZ[1] == 'Z' ) {
        pe_hdr = _ClientRead( coff_file_hnd, sizeof( pe_header ) );
        _ClientSeek( coff_file_hnd, pe_hdr->offset - sizeof( pe_header ), SEEK_CUR );
        PE = _ClientRead( coff_file_hnd, 4 );
        if( PE[0] == 'P' && PE[1] == 'E' && PE[2] == '\0' && PE[3] == '\0' ) {
            PEoffset = pe_hdr->offset + 4;
        } else {
            _ClientSeek( coff_file_hnd, -pe_hdr->offset-4, SEEK_CUR );
        }
    }
    coff_file_hnd->f_hdr_buffer = _ClientRead( coff_file_hnd, sizeof( coff_file_header ) );
    if( !(coff_file_hnd->f_hdr_buffer) ) return( ORL_OUT_OF_MEMORY );
    f_hdr = (coff_file_header *) coff_file_hnd->f_hdr_buffer;
    if( determine_file_specs( coff_file_hnd, f_hdr ) ) {
        // we have identified an import_object_header
        // convert short import library structures to long import
        // library structures, change _ClientRead and _ClientSeek
        // macros to read from converted metadata
        error = convert_import_library( coff_file_hnd );
        if ( error != ORL_OKAY ) {
            return( error );
        }
        // reread new converted file header and next process as normal
        coff_file_hnd->f_hdr_buffer = _ClientRead( coff_file_hnd, sizeof( coff_file_header ) );
        if( !(coff_file_hnd->f_hdr_buffer) ) return( ORL_OUT_OF_MEMORY );
        f_hdr = (coff_file_header *) coff_file_hnd->f_hdr_buffer;
        determine_file_specs( coff_file_hnd, f_hdr );
    }
    if( f_hdr->opt_hdr_size > 0 ) {     // skip optional header
        pe_opt_hdr *opt_hdr = (pe_opt_hdr *)_ClientRead( coff_file_hnd, f_hdr->opt_hdr_size );

        if( (opt_hdr->magic == 0x10b) || (opt_hdr->magic == 0x20b) ) {
            coff_file_hnd->export_table_rva = opt_hdr->export_table_rva;
        } else {
            coff_file_hnd->export_table_rva = 0L;
        }
    }
    coff_file_hnd->initial_size = sizeof( coff_file_header ) + f_hdr->opt_hdr_size + PEoffset;
    switch( coff_file_hnd->machine_type ) {
    case ORL_MACHINE_TYPE_UNKNOWN:
        return( ORL_ERROR );
    default:
        break;
    }
    coff_file_hnd->num_symbols = f_hdr->num_symbols;
    coff_file_hnd->num_sections = f_hdr->num_sections;
    sec_header_table_size = coff_file_hnd->num_sections * sizeof( coff_section_header );
    if( coff_file_hnd->num_sections > 0 ) {
        coff_file_hnd->s_hdr_table_buffer = _ClientRead( coff_file_hnd,
                                                         sec_header_table_size);
        if( !(coff_file_hnd->s_hdr_table_buffer) ) {
            return( ORL_ERROR );
        }
    }
    error = load_coff_sec_handles( coff_file_hnd, f_hdr );
    if( error != ORL_OKAY ) {
        return( error );
    }
    last_sec_hnd = coff_file_hnd->coff_sec_hnd[coff_file_hnd->num_sections - 1];
    coff_file_hnd->initial_size += sec_header_table_size;

    buf_size = 0;
    for( loop=0; loop < coff_file_hnd->num_sections; loop++ ) {
        coff_sec_hnd = coff_file_hnd->coff_sec_hnd[loop];
        if( (coff_sec_hnd->offset + coff_sec_hnd->size) > buf_size &&
                !(coff_sec_hnd->flags & ORL_SEC_FLAG_UNINITIALIZED_DATA) ) {
            buf_size = coff_sec_hnd->offset + coff_sec_hnd->size;
        }
    }
    coff_file_hnd->size = buf_size;
    buf_size -= coff_file_hnd->initial_size;
    coff_file_hnd->rest_of_file_buffer = _ClientRead( coff_file_hnd, buf_size );
    if( !(coff_file_hnd->rest_of_file_buffer ) ) {
        return( ORL_ERROR );
    }
    loop_limit = coff_file_hnd->num_sections;
    if( last_sec_hnd == coff_file_hnd->string_table ) {
        if( f_hdr->sym_table ) {
            memcpy( &(last_sec_hnd->size),
                    coff_file_hnd->rest_of_file_buffer + last_sec_hnd->offset - coff_file_hnd->initial_size,
                    sizeof( coff_sec_size ) );
        }
        if( last_sec_hnd->size < 4 ) {
            last_sec_hnd->size = 0;
        }
        if( last_sec_hnd->size != 0 ) {
            last_sec_hnd->size -= sizeof( coff_sec_size );
        }
        if( last_sec_hnd->size > 0 && last_sec_hnd->offset != 0 ) {
            if( last_sec_hnd->offset == buf_size +
                        coff_file_hnd->initial_size - 4 ) {
                last_sec_hnd->contents = _ClientRead( coff_file_hnd,
                                                  last_sec_hnd->size );
                coff_file_hnd->size += last_sec_hnd->size;
            } else {
                last_sec_hnd->contents = coff_file_hnd->rest_of_file_buffer +
                        last_sec_hnd->offset - coff_file_hnd->initial_size +
                        sizeof( coff_sec_size );
            }
            if( !(last_sec_hnd->contents ) ) {
                return( ORL_ERROR );
            }
        } else {
            last_sec_hnd->contents = NULL;
        }
        loop_limit--;
    }
    // determine contents pointers of all sections
    for( loop = 0; loop < loop_limit; loop++ ) {
        coff_sec_hnd = coff_file_hnd->coff_sec_hnd[loop];
        if( (coff_sec_hnd->size > 0
                        || coff_sec_hnd->type == ORL_SEC_TYPE_STR_TABLE)
                        && coff_sec_hnd->offset != 0 ) {
            coff_sec_hnd->contents = coff_file_hnd->rest_of_file_buffer +
                coff_sec_hnd->offset - coff_file_hnd->initial_size;
        }
    }
    if( last_sec_hnd != coff_file_hnd->string_table ) {
        memcpy( &(coff_file_hnd->string_table->size),
                 coff_file_hnd->string_table->contents, sizeof(coff_sec_size) );
        if( coff_file_hnd->string_table->size != 0 ) {
            coff_file_hnd->string_table->size -= sizeof( coff_sec_size );
            coff_file_hnd->string_table->contents += sizeof( coff_sec_size );
        }
    }
    // determine section names
    for( loop = 0; loop < coff_file_hnd->num_sections; loop++ ) {
        coff_sec_hnd = coff_file_hnd->coff_sec_hnd[loop];
        if( coff_sec_hnd->name[0] == '/' ) {
            // change pointer to point into string table
            string_table_index = atoi( &(coff_sec_hnd->name[1]) )
                                        - sizeof(coff_sec_size);
            coff_sec_hnd->name = &(coff_file_hnd->string_table->contents[string_table_index]);
        }
    }
    return( ORL_OKAY );
}