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 + -
显示快捷键?