expld.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,081 行 · 第 1/3 页
C
1,081 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Export DIP Loading/unloading of symbolic information.
*
****************************************************************************/
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include "walloca.h"
#include "exp.h"
#include "exedos.h"
#include "exeos2.h"
#include "exeflat.h"
#include "exepe.h"
#include "exenov.h"
#include "exeelf.h"
#if defined( __WATCOMC__ ) && defined( __386__ )
/* WD looks for this symbol to determine module bitness */
int __nullarea;
#pragma aux __nullarea "*";
#endif
typedef union {
dos_exe_header mz;
os2_exe_header ne;
os2_flat_header lx;
pe_header pe;
} any_header;
static struct {
unsigned long fpos;
unsigned len;
unsigned off;
unsigned_8 data[256];
} Buff;
unsigned long BSeek( dig_fhandle h, unsigned long p, dig_seek w )
{
unsigned long bpos;
unsigned long npos;
bpos = Buff.fpos - Buff.len;
switch( w ) {
case DIG_END:
return( -1UL ); /* unsupported */
case DIG_CUR:
npos = bpos + p + Buff.off;
break;
case DIG_ORG:
npos = p;
break;
}
if( npos >= bpos && npos < (bpos+Buff.len) ) {
Buff.off = npos - bpos;
return( npos );
}
Buff.fpos = DCSeek( h, npos, DIG_ORG );
Buff.off = 0;
Buff.len = 0;
return( Buff.fpos );
}
unsigned BRead( dig_fhandle h, void *b, unsigned s )
{
unsigned got;
unsigned want;
if( s > sizeof( Buff.data ) ) {
Buff.fpos = DCSeek( h, (int)Buff.fpos + (int)Buff.off - (int)Buff.len, DIG_ORG );
Buff.len = 0;
Buff.off = 0;
if( Buff.fpos == -1UL ) return( 0 );
got = DCRead( h, b, s );
Buff.fpos += got;
return( got );
}
want = s;
got = Buff.len - Buff.off;
if( got > want ) got = want;
memcpy( b, &Buff.data[Buff.off], got );
Buff.off += got;
want -= got;
if( want > 0 ) {
Buff.len = DCRead( h, &Buff.data[0], sizeof( Buff.data ) );
if( Buff.len == (unsigned)-1 ) {
Buff.fpos = -1UL;
Buff.off = 0;
Buff.len = 0;
return( (unsigned)-1 );
}
Buff.fpos += Buff.len;
b = (unsigned_8 *)b + got;
memcpy( b, &Buff.data[0], want );
Buff.off = want;
}
return( s );
}
#define ROUND_UP( d, r ) (((d)+(r)-1) & ~((r)-1))
static void *HunkAlloc( imp_image_handle *ii, unsigned size )
{
exp_hunk *hunk;
unsigned alloc;
size = ROUND_UP( size, sizeof( void * ) );
hunk = ii->hunks;
if( hunk == NULL || size > hunk->left ) {
alloc = max( HUNK_SIZE, size );
hunk = DCAlloc( (sizeof( *hunk ) - HUNK_SIZE) + alloc );
if( hunk == NULL ) return( NULL );
hunk->next = ii->hunks;
ii->hunks = hunk;
hunk->left = alloc;
}
hunk->left -= size;
return( &hunk->data[ hunk->left ] );
}
static void ImpUnloadInfo( imp_image_handle *ii )
{
exp_hunk *curr;
exp_hunk *next;
for( curr = ii->hunks; curr != NULL; curr = next ) {
next = curr->next;
DCFree( curr );
}
ii->hunks = NULL;
}
exp_block *FindAddrBlock( imp_image_handle *ii, addr_ptr addr )
{
exp_block *b;
for( b = ii->addr; b != NULL; b = b->next ) {
if( SameAddrSpace( b->start, addr )
&& b->start.offset <= addr.offset
&& (b->start.offset+b->len) > addr.offset ) {
return( b );
}
}
return( NULL );
}
static dip_status AddName( imp_image_handle *ii, unsigned len, char *name )
{
char *start;
char *end;
end = NULL;
start = name;
for( ;; ) {
if( len == 0 ) break;
switch( *name ) {
case ':':
case '\\':
case '/':
start = name + 1;
end = NULL;
break;
case '.':
end = name;
break;
}
++name;
--len;
}
if( end == NULL ) end = name;
ii->len = end - start;
ii->name = HunkAlloc( ii, ii->len );
if( ii->name == NULL ) return( DS_ERR|DS_NO_MEM );
memcpy( ii->name, start, ii->len );
return( DS_OK );
}
static dip_status AddBlock( imp_image_handle *ii, addr_seg seg, addr_off off,
unsigned_32 len, unsigned_8 code )
{
exp_block *new;
new = HunkAlloc( ii, sizeof( *new ) );
if( new == NULL ) return( DS_ERR|DS_NO_MEM );
new->start.segment = seg;
new->start.offset = off;
new->len = len;
new->code = code;
new->next = ii->addr;
ii->addr = new;
return( DS_OK );
}
static dip_status AddSymbol( imp_image_handle *ii, addr_seg seg, addr_off off,
unsigned len, char *name )
{
exp_sym *new;
new = HunkAlloc( ii, (sizeof( *new ) - 1) + len );
if( new == NULL ) return( DS_ERR|DS_NO_MEM );
new->addr.segment = seg;
new->addr.offset = off;
new->len = len;
memcpy( new->name, name, len );
new->next = ii->gbl;
ii->gbl = new;
return( DS_OK );
}
static dip_status ProcTable( dig_fhandle h, imp_image_handle *ii,
unsigned resident )
{
unsigned_8 len;
char buff[256+sizeof(unsigned_16)];
unsigned first;
unsigned ord;
dip_status ds;
first = 1;
for( ;; ) {
if( BRead( h, &len, sizeof( len ) ) != sizeof( len ) ) {
return( DS_ERR|DS_FREAD_FAILED );
}
if( len == 0 ) break;
if( BRead( h, buff, len + 2 ) != len + 2 ) {
return( DS_ERR|DS_FREAD_FAILED );
}
ord = *(unsigned_16 *)&buff[len];
if( resident && first ) {
first = 0;
ds = AddName( ii, len, buff );
if( ds != DS_OK ) return( ds );
} else if( ord != 0 ) {
/* this is putting in entry number, we'll get real addr later */
ds = AddSymbol( ii, 0, ord, len, buff );
if( ds != DS_OK ) return( ds );
}
}
return( DS_OK );
}
static dip_status TryNE( dig_fhandle h, imp_image_handle *ii,
any_header *head, unsigned_32 off )
{
segment_record seg;
dip_status ds;
unsigned ord;
bundle_prefix pref;
union {
movable_record mov;
fixed_record fix;
} entry;
unsigned i;
exp_sym *s;
if( BSeek( h, off + head->ne.segment_off, DIG_ORG ) != off + head->ne.segment_off ) {
return( DS_ERR|DS_FSEEK_FAILED );
}
for( i = 0; i < head->ne.segments; ++i ) {
if( BRead( h, &seg, sizeof( seg ) ) != sizeof( seg ) ) {
return( DS_ERR|DS_FREAD_FAILED );
}
ds = AddBlock( ii, i + 1, 0, seg.size == 0 ? 0x10000 : seg.size,
!(seg.info & SEG_DATA) );
if( ds != DS_OK ) return( ds );
}
if( BSeek( h, off + head->ne.resident_off, DIG_ORG ) != off + head->ne.resident_off ) {
return( DS_ERR|DS_FSEEK_FAILED );
}
ds = ProcTable( h, ii, 1 );
if( ds != DS_OK ) return( ds );
if( head->ne.nonres_size != 0 ) {
if( BSeek( h, head->ne.nonres_off, DIG_ORG ) != head->ne.nonres_off ) {
return( DS_ERR|DS_FSEEK_FAILED );
}
ds = ProcTable( h, ii, 0 );
if( ds != DS_OK ) return( ds );
}
/* change all the symbol addresses from entry numbers to seg/offsets */
if( BSeek( h, off + head->ne.entry_off, DIG_ORG ) != off + head->ne.entry_off ) {
return( DS_ERR|DS_FSEEK_FAILED );
}
ord = 1;
for( ;; ) {
if( BRead( h, &pref, sizeof( pref ) ) != sizeof( pref ) ) {
return( DS_ERR|DS_FREAD_FAILED );
}
if( pref.number == 0 ) break;
if( pref.type == 0 ) {
ord += pref.number;
} else {
for( i = 0; i < pref.number; ++i ) {
if( pref.type == MOVABLE_ENTRY_PNT ) {
if( BRead( h, &entry.mov, sizeof( entry.mov ) ) != sizeof( entry.mov ) ) {
return( DS_ERR|DS_FREAD_FAILED );
}
} else {
if( BRead( h, &entry.fix, sizeof( entry.fix ) ) != sizeof( entry.fix ) ) {
return( DS_ERR|DS_FREAD_FAILED );
}
entry.mov.entry = entry.fix.entry;
entry.mov.entrynum = pref.type;
}
if( entry.mov.info & ENTRY_EXPORTED ) {
s = ii->gbl;
for( ;; ) {
if( s == NULL ) break;
if( s->addr.segment == 0 && s->addr.offset == ord ) {
s->addr.segment = entry.mov.entrynum;
s->addr.offset = entry.mov.entry;
break;
}
s = s->next;
}
}
++ord;
}
}
}
return( DS_OK );
}
static dip_status TryLX( dig_fhandle h, imp_image_handle *ii,
any_header *head, unsigned_32 off )
{
object_record seg;
dip_status ds;
unsigned ord;
flat_bundle_prefix pref;
union {
flat_bundle_entry32 e32;
flat_bundle_entry16 e16;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?