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 ); }
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 ); }