support.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,334 行 · 第 1/3 页

C
1,334
字号
            header_base += head.mod_size;
            header_base -= 512;
        }
        /* fall through to P3 */
    case EXE_P2:
    case EXE_P3:
        /* exeImageOffset is in bytes */
        seek_off = header_base + offsetof( extended_header, load_offset );
        lseek( exeFH, seek_off, SEEK_SET );
        read( exeFH, &dummy_32, sizeof( dummy_32 ) );
        exeImageOffset = dummy_32;
        seek_off = header_base + offsetof( extended_header, offset );
        lseek( exeFH, seek_off, SEEK_SET );
        read( exeFH, &dummy_32, sizeof( dummy_32 ) );
        exeImageOffset -= dummy_32;                     /* 09-aug-90 AFS */
        exeImageOffset += header_base;
        break;
    case EXE_NW:
        /* exeImageOffset is in bytes */
        lseek( exeFH, offsetof( nlm_header, codeImageOffset ), SEEK_SET );
        read( exeFH, &dummy_32, sizeof( dummy_32 ) );
        exeImageOffset = dummy_32;
        break;
    case EXE_OS2:
        /* offset into "reserved for future use" portion of the DOS EXE hdr */
        lseek( exeFH, sizeof( dos_exe_header ) + 32, SEEK_SET );
        read( exeFH, &dummy_32, sizeof( dummy_32 ) );
        new_header = dummy_32;
        lseek(exeFH,new_header + offsetof(os2_exe_header,segment_off),SEEK_SET);
        read( exeFH, &dummy_16, sizeof( dummy_16 ) );
        /* exeImageOffset is in bytes and points to the segment table */
        exeImageOffset = new_header + dummy_16;
        lseek( exeFH, new_header + offsetof( os2_exe_header, align ), SEEK_SET);
        read( exeFH, &dummy_16, sizeof( dummy_16 ) );
        segmentShift = dummy_16;
        if( segmentShift == 0 ) {
            segmentShift = OS2_DEF_SEGMENT_SHIFT;
        }
        cacheSegment = 0;       /* no 0 segment in OS/2 (03-may-90 AFS) */
        break;
    case EXE_OS2_FLAT:
    case EXE_OS2_LX:
        lseek( exeFH, sizeof( head ) + 32, SEEK_SET );
        read( exeFH, &dummy_32, sizeof(dummy_32) );
        /* exeImageOffset is in bytes and points to the OS/2 FLAT header */
        exeImageOffset = dummy_32;
        cacheSegment = 0;       /* no 0 segment in OS/2 FLAT */
        break;
    case EXE_QNX:
    case EXE_QNX_386:
    case EXE_QNX_386_FLAT:
        /* exeImageOffset is in bytes and points to the end of the header */
        exeImageOffset = sizeof( lmf_record ) + sizeof( lmf_header );
        cacheSegment = 0;
        break;
    case EXE_PE:
    case EXE_PL:
        /* offset into "reserved for future use" portion of the DOS EXE hdr */
        lseek( exeFH, sizeof( dos_exe_header ) + 32, SEEK_SET );
        read( exeFH, &dummy_32, sizeof( dummy_32 ) );
        new_header = dummy_32;
#if 0
        lseek(exeFH,new_header + offsetof(pe_header,num_objects),SEEK_SET);
        read( exeFH, &dummy_16, sizeof( dummy_16 ) );
        lseek(exeFH,new_header + offsetof(pe_header,header_size),SEEK_SET);
        read( exeFH, &dummy_32, sizeof( dummy_32 ) );
        /* exeImageOffset is in bytes and points to the object table */
        exeImageOffset = dummy_32 - dummy_16 * sizeof( pe_object );
#else
        lseek(exeFH,new_header + offsetof(pe_header,nt_hdr_size),SEEK_SET);
        read( exeFH, &dummy_16, sizeof( dummy_16 ) );
        /* exeImageOffset is in bytes and points to the object table */
        exeImageOffset = new_header + offsetof(pe_header,magic) + dummy_16;
#endif
        cacheSegment = 0;       /* no 0 segment in OS/2 (03-may-90 AFS) */
        break;
    case EXE_OVL:
        /* overlay file (not an exe) */
        exeImageOffset = 0;
        break;
    case EXE_ELF:
        lseek(exeFH,offsetof(Elf32_Ehdr,e_phoff),SEEK_SET);
        read( exeFH, &dummy_32, sizeof( dummy_32 ) );
        exeImageOffset = dummy_32;
        lseek(exeFH,offsetof(Elf32_Ehdr,e_phentsize),SEEK_SET);
        read( exeFH, &dummy_16, sizeof( dummy_16 ) );
        cacheLo = dummy_16;             /* entry size */
        read( exeFH, &dummy_16, sizeof( dummy_16 ) );
        cacheSegment = dummy_16;        /* number of entries */
        break;
    default:
        return( B_FALSE );
    }
    exePosition = 0;
    exeCurrent = 0;
    exeAmount = 0;
    currAddr.mach.segment = 0;
    currAddr.mach.offset = 0;
    return( B_TRUE );
}



STATIC void readEntry( uint_32 *v, size_t mini_off )
/**************************************************/
{
    lseek( exeFH, exeImageOffset + mini_off, SEEK_SET );
    read( exeFH, v, sizeof( *v ) );
}



STATIC void searchQNX( uint_16 seg, uint_32 off )
/***********************************************/
{
    int                 st;
    uint_16             seg_idx;
    uint_32             hi;
    uint_32             lo;
    lmf_record          rec_head;
    lmf_data            load_data;
    uint_32             hole_lo;
    uint_32             hole_hi;

    cacheSegment = seg;
    seg_idx = seg >> 3;
    cacheLo = 0;
    cacheHi = ULONG_MAX;
    hole_lo = 0;
    hole_hi = ULONG_MAX;
    isHole = B_FALSE;
    lseek( exeFH, 0, SEEK_SET );
    for( ;; ) {
        st = read( exeFH, &rec_head, sizeof( rec_head ) );
        if( st != sizeof( rec_head ) ) break;
        nbytes = rec_head.data_nbytes;
        if( rec_head.rec_type == LMF_IMAGE_END_REC ) break;
        if( rec_head.rec_type != LMF_LOAD_REC ) {
            lseek( exeFH, rec_head.data_nbytes, SEEK_CUR );
            continue;
        }
        st = read( exeFH, &load_data, sizeof( load_data ) );
        if( st != sizeof( load_data ) ) break;
        rec_head.data_nbytes -= sizeof( load_data );
        lo = load_data.offset;
        hi = lo + ( rec_head.data_nbytes - 1 );
        if( load_data.segment == seg_idx ) {
            if( lo <= off && off <= hi ) {
                cacheLo = lo;
                cacheHi = hi;
                cacheExeOffset = tell( exeFH );
                return;
            }
            if( hole_lo < hi && hi < off ) {
                hole_lo = hi + 1;
            }
            if( hole_hi > lo && lo > off ) {
                hole_hi = lo - 1;
            }
        }
        lseek( exeFH, rec_head.data_nbytes, SEEK_CUR );
    }
    isHole = B_TRUE;
    cacheLo = hole_lo;
    cacheHi = hole_hi;
    exeFlags.end_of_segment = B_TRUE;
}



STATIC uint_32 TransformExeOffset( uint_16 seg, uint_32 off, uint_16 sect_id )
/****************************************************************************/
{
    ovl_entry               *entry;
    segment_record          segment;
    map_entry               mapping;
    off_t                   tmp_offset;
    image_info              *curr_image;
    uint_32                 subresult;
    uint_32                 page_offset_shift;
    uint_32                 object_table;
    uint_32                 objmap_table;
    uint_32                 map_idx;
    uint_32                 page_num;
    uint_32                 page_off;
    uint_32                 page_size;
    uint_32                 seg_start;

    if( sect_id != ROOT_SECTION ) {
        curr_image = CurrSIOData->curr_image;
        if( sect_id > curr_image->ovl_count ) {
            return( -1 );
        }
        entry = curr_image->ovl_data;
        entry += sect_id - 1;
        subresult = seg * 16L + off;
        subresult += entry->disk_addr;
        subresult -= entry->start_para * 16L;
        return( subresult );
    }
    switch( exeType ) {
    case EXE_NW:
    case EXE_P3:
    case EXE_P3_BOUND:
    case EXE_MP:
    case EXE_MP_BOUND:
        subresult = exeImageOffset + off;
        break;
    case EXE_OS2:
        if( seg != cacheSegment ) {
            tmp_offset = exeImageOffset + (seg-1) * sizeof(segment_record);
            lseek( exeFH, tmp_offset, SEEK_SET );
            read( exeFH, &segment, sizeof( segment ) );
            cacheSegment = seg;
            cacheExeOffset = ((off_t) segment.address) << segmentShift;
        }
        subresult = cacheExeOffset + off;
        break;
    case EXE_OS2_FLAT:
    case EXE_OS2_LX:
        if( seg != cacheSegment ) {
            readEntry( &page_offset_shift,
                       offsetof(os2_flat_header,l.page_shift));
            readEntry( &object_table, offsetof(os2_flat_header,objtab_off));
            tmp_offset = object_table + exeImageOffset;
            tmp_offset += (seg - 1) * sizeof( object_record );
            tmp_offset += offsetof( object_record, mapidx );
            lseek( exeFH, tmp_offset, SEEK_SET );
            read( exeFH, &map_idx, sizeof( map_idx ) );
            readEntry( &objmap_table, offsetof(os2_flat_header,objmap_off));
            tmp_offset = objmap_table + exeImageOffset;
            if( exeType == EXE_OS2_LX ) {
                tmp_offset += ( map_idx-1 ) * sizeof( lx_map_entry );
            } else {
                tmp_offset += ( map_idx-1 ) * sizeof( le_map_entry );
            }
            lseek( exeFH, tmp_offset, SEEK_SET );
            read( exeFH, &mapping, sizeof( mapping ) );
            readEntry( &page_off, offsetof( os2_flat_header, page_off ) );
            if( exeType == EXE_OS2_LX ) {
                page_off += mapping.lx.page_offset << page_offset_shift;
            } else {
                page_num = ( (uint_32)mapping.le.page_num[0] << 16 ) +
                           ( mapping.le.page_num[1] << 8 ) +
                           ( mapping.le.page_num[2] << 0 );
                --page_num; /* origin 1 -> origin 0 */
                readEntry( &page_size, offsetof( os2_flat_header, page_size ) );
                page_off += page_num * page_size;
            }
            cacheExeOffset = page_off;
        }
        subresult = cacheExeOffset + off;
        break;
    case EXE_QNX:
    case EXE_QNX_386:
    case EXE_QNX_386_FLAT:
        if( seg != cacheSegment || off < cacheLo || off > cacheHi ) {
            searchQNX( seg, off );
        }
        subresult = cacheExeOffset + ( off - cacheLo );
        break;
    case EXE_MZ:
        subresult = ( seg + exeImageOffset ) * 16 + off;
        break;
    case EXE_PE:
        if( seg != cacheSegment ) {
            tmp_offset = exeImageOffset;
            tmp_offset += (seg - 1) * sizeof( pe_object );
            tmp_offset += offsetof( pe_object, physical_offset );
            lseek( exeFH, tmp_offset, SEEK_SET );
            read( exeFH, &seg_start, sizeof( seg_start ) );
            cacheExeOffset = seg_start;
        }
        subresult = cacheExeOffset + off;
        break;
    case EXE_ELF:
        /*
         * exeImageOffset:      start of the program header table
         * cacheLo:             size of program header entry
         * cacheSegment:        number of program header entries
         */
        {
            Elf32_Phdr  phe;
            unsigned    i;

            tmp_offset = exeImageOffset;
            i = 0;
            for( ;; ) {
                if( i > cacheSegment ) {
                    return( -1 );
                }
                lseek( exeFH, tmp_offset, SEEK_SET );
                read( exeFH, &phe, sizeof( phe ) );
                if( phe.p_type == PT_LOAD
                 && off >= phe.p_vaddr
                 && off < (phe.p_vaddr+phe.p_memsz) ) break;
                tmp_offset += cacheLo;
                ++i;
            }
            cacheHi = phe.p_memsz;
            cacheExeOffset = phe.p_offset;
            subresult = phe.p_offset + (off - phe.p_vaddr);
        }
        break;
    case EXE_OVL:
/**/    myassert( 0 );
    case EXE_P2:    /* P2 format is not supported 03-may-90 AFS */
    default:
        subresult = -1;
        break;
    }
    return( subresult );
}



extern image_info *AddrImage( address *addr )
/*******************************************/
{
    addr_ptr        closest;
    image_info      *closest_image;
    image_info      *curr_image;
    map_to_actual   *map;
    ovl_entry       *overlay;
    int             count;
    int             count2;

    closest.segment = 0;
    closest.offset = 0;
    count = 0;
    for( ;; ) {
        if( count >= CurrSIOData->image_count ) {
            if( closest.segment != 0 ) break;
            return( NULL );
        }
        curr_image = CurrSIOData->images[count];
        if( addr->sect_id != 0 ) {
            count2 = curr_image->ovl_count;
            overlay = curr_image->ovl_data;
            while( count2-- > 0 ) {
                if( addr->mach.segment == overlay[count2].base_para ) {
                    return( curr_image );
                }
            }
        } else {
            map = curr_image->map_data;
            for( count2 = 0; count2 < curr_image->map_count; ++count2, ++map ) {
                if( map->actual.mach.segment == addr->mach.segment
                 && addr->mach.offset >= map->actual.mach.offset
                 && (addr->mach.offset-map->actual.mach.offset) < map->length ) {
                    if( map->actual.mach.offset > closest.offset ) {
                        closest = map->actual.mach;
                        closest_image = curr_image;
                    }
                }
            }
        }
        count++;
    }
    return( closest_image );
}



extern void MapAddressToActual( image_info *curr_image, addr_ptr *addr )
/**********************************************************************/
{
    map_to_actual       *map;
    int                 count;
    int                 index;
    addr_seg            seg;

    map = curr_image->map_data;
    count = curr_image->map_count;

    if ( count == 0 ) {
        addr->segment = 0;
        addr->offset  = 0;
        return;
    }

/**/myassert( map != NULL );
    index = 0;
    seg = addr->segment;
    switch( seg ) {
    case MAP_FLAT_CODE_SELECTOR:
    case MAP_FLAT_DATA_SELECTOR:
        seg = 1;
        break;
    default:
        break;
    }
    for( ;; ) {
        if( count-- <= 0 ) {
            /* address could be EXTERNAL or in an overlay section */
            addr->segment = seg + map[0].actual.mach.segment;
            break;
        }
        if( map[index].map.mach.segment == seg ) {
            addr->segment = map[index].actual.mach.segment;
            addr->offset += map[index].actual.mach.offset - map[index].map.mach.offset;
            break;
        }
        index++;
    }
}


extern void MapAddressToMap( addr_ptr *addr )
/*******************************************/
{
    map_to_actual   *map;
    int             count;
    int             index;
    bint            first_save;
    addr_ptr        save_addr;

    first_save = B_TRUE;
    map = CurrSIOData->curr_image->map_data;
    count = CurrSIOData->curr_image->map_count;
    for( index = 0; index < count; ++index, ++map ) {
        //NYI: should check map->length
        if( map->actual.mach.segment == addr->segment ) {
            if( first_save
             || (addr->offset >= map->actual.mach.offset
                 && addr->offset >= save_addr.offset) ) {
                save_addr.segment = map->map.mach.segment;
                save_addr.offset = map->actual.mach.offset - map->map.mach.offset;
                first_save = B_FALSE;
            }
        }
    }
    if( first_save ) {
        /* address could be EXTERNAL or in an overlay section */
        addr->segment -= CurrSIOData->curr_image->map_data[0].actual.mach.segment;
    } else {
        addr->segment = save_addr.segment;
        addr->offset -= save_addr.offset;
    }
}



extern void MapAddressIntoSection( address *addr )
/************************************************/

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?