wdata.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 391 行

C
391
字号
/****************************************************************************
*
*                            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:  Raw segment data dump routines.
*
****************************************************************************/


#include <stdio.h>
#include <setjmp.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include "walloca.h"

#include "wdglb.h"
#include "wdfunc.h"


static  char    *reloc_addr_type[] = {
    "OFF",
    "BAS",
    "PTR",
    "?04",
    "LDR"
};


/*
 * Dump a segment
 */
static void dmp_segment( struct segment_record *seg )
/***************************************************/
{
    unsigned_32           file_off;
    unsigned_32           iter;
    unsigned_32           seg_len;

    if( seg->address == 0 ) {
        Wdputslc( "\n" );
        Wdputslc( "\n" );
        return;
    }
    if( seg->size == 0 ) {
        seg_len = 0x00010000;
    } else {
        seg_len = seg->size;
    }
    file_off = (unsigned_32)seg->address <<
                   Os2_head.align;
    Wlseek( file_off );
    if( seg->info & SEG_ITERATED ) {
        Wdputslc( "Segment is iterated: NYI because of lack of examples\n" );
        Wread( &iter, sizeof( unsigned_32 ) );
        Wdputs( "        number of iterations = " );
        Putdec( iter & 0xffff );
        Wdputs( ", byte length of data = " );
        Putdec( iter > 16 );
        Wdputslc( "\n" );
    }
    Wdputslc( "        segment data =\n" );
    Dmp_seg_data( file_off, seg_len );
    Wdputslc( "\n" );
}

/*
 * Dump a relocation item
 */
static void dmp_reloc_item( struct relocation_item *reloc )
/*********************************************************/
{
    unsigned_16             seg_num;
    unsigned_16             ord_off;
    unsigned_32             imp_off;
    unsigned_8              string_len;
    char                    *imp_nam;

    switch( reloc->reloc_type ) {
    case REL_INTERNAL_REFERENCE :
        seg_num = reloc->xtrnl.internal.seg_num;
        ord_off = reloc->xtrnl.internal.ord_off;
        if( seg_num != MOVABLE_ENTRY_PNT ) {
            Wdputs( "seg " );
            Puthex( seg_num, 4 );
            Wdputs( " offset " );
            Puthex( ord_off, 4 );
            if( seg_num > Os2_head.segments ) {
                Wdputs( " *** invalid segment" );
            } else if( ord_off > Int_seg_tab[ seg_num - 1 ].min ) {
                Wdputs( " *** invalid offset" );
            }
        } else {
            Wdputs( "movable " );
            Dmp_ordinal( ord_off );
        }
        break;
    case REL_IMPORTED_ORDINAL :
        Wdputs( "ord " );
        Wdputs( Int_mod_ref_tab[ reloc->xtrnl.ordinal.modref_idx - 1 ] );
        Wdputc( '.' );
        Putdec( reloc->xtrnl.ordinal.ord_num );
        break;
    case REL_IMPORTED_NAME :
        Wdputs( "nam " );
        Wdputs( Int_mod_ref_tab[ reloc->xtrnl.name.modref_idx - 1 ] );
        Wdputc( '.' );
        /* One of Os2_386_head.impproc_off and Os2_head.import_off will be set */
        imp_off = reloc->xtrnl.name.impnam_off + Os2_386_head.impproc_off
                + Os2_head.import_off + New_exe_off;
        Wlseek( imp_off );
        Wread( &string_len, sizeof( unsigned_8 ) );
        imp_nam = Wmalloc( string_len + 1 );
        Wread( imp_nam, string_len );
        imp_nam[ string_len ] = '\0';
        if( imp_nam == NULL ) {
            Wdputs( "*** import table error" );
        } else {
            Wdputs( imp_nam );
            free( imp_nam );
        }
        Wdputc( '(' );
        Puthex( reloc->xtrnl.name.impnam_off, 4 );
        Wdputc( ')' );
        break;
    default :
        Wdputs( "osfixup :" );
        Puthex( reloc->xtrnl.data, 8 );
        Wdputc( 'H' );
        break;
    }
}

/*
 * Dump a Segment's relocation info
 */
static void dmp_reloc_info( unsigned_32 reloc_off )
/*************************************************/
{
    unsigned_16                     num_relocs;
    struct relocation_item          *reloc_tab;
    struct relocation_item          *reloc;
    unsigned_16                     size_reloc_tab;

    Wlseek( reloc_off );
    Wread( &num_relocs, sizeof( unsigned_16 ) );
    size_reloc_tab = num_relocs * sizeof( struct relocation_item );
    Wdputslc( "\nNumber of relocations: " );
    Putdec( num_relocs );
    Wdputs( "     Total size of relocations: " );
    Putdec( size_reloc_tab );
    reloc_tab = Wmalloc( size_reloc_tab );
    Wread( reloc_tab, size_reloc_tab );
    Wdputslc( "\n  typ off  target" );
    Wdputslc( "\n  === ==== ====" );
    for( reloc = reloc_tab; num_relocs-- != 0; ++reloc ) {
        Wdputslc( "\n  " );
        if( (reloc->addr_type > REL_SEGMENT_OFFSET + 2)
            || reloc->addr_type == 0  ) {
            Wdputc( '?' );
            Puthex( reloc->addr_type, 2 );
        } else {
            Wdputs( reloc_addr_type[ reloc->addr_type -1 ] );
        }
        Wdputc( ' ' );
        Puthex( reloc->reloc_offset, 4 );
        Wdputc( ' ' );
        if( reloc->reloc_type & REL_ADDITIVE ) {
            Wdputs( "ADDITIVE " );
            reloc->reloc_type &= ~REL_ADDITIVE;
        }
        dmp_reloc_item( reloc );
    }
    Wdputslc( "\n" );
    free( reloc_tab );
}

/*
 * Dump the Segments
 */
void Dmp_relocs( void )
/*********************/
{
    struct segment_record   *seg;
    unsigned_16             segnum;
    unsigned_16             num_segs;
    unsigned_32             reloc_off;

    if( !(Options_dmp & FIX_DMP) ) {
        return;
    }
    Wdputslc( "\n" );
    Banner( "The Relocations" );
    seg = Int_seg_tab;
    num_segs = Os2_head.segments + 1;
    for( segnum = 1; segnum != num_segs; segnum++ ) {
        reloc_off = (unsigned_32)seg->address <<
                       Os2_head.align;
        reloc_off += seg->size;
        if( seg->info & SEG_RELOC ) {
            Wdputs( "segment # " );
            Putdec( segnum );
            dmp_reloc_info( reloc_off );
        }
    seg++;
    }
}

/*
 * Dump the Segments
 */
void Dmp_segments( void )
/***********************/
{
    struct segment_record   *seg;
    unsigned_16             segnum;
    unsigned_16             num_segs;

    Wdputslc( "\n" );
    Banner( "The Segments" );
    if( Segspec != 0 ) {
        if( Segspec > Os2_head.segments ) {
            Wdputslc( "segment specified was too large\n" );
            return;
        }
        Wdputs( "segment # " );
        Putdec( Segspec );
        seg = &Int_seg_tab[ Segspec - 1 ];
        dmp_segment( seg );
        return;
    }
    seg = Int_seg_tab;
    num_segs = Os2_head.segments + 1;
    for( segnum = 1; segnum != num_segs; segnum++ ) {
        Wdputs( "segment # " );
        Putdec( segnum );
        dmp_segment( seg++ );
    }
}

/*
 * Dump the Segments
 */
void Dmp_le_page_seg( void )
/**************************/
{
    unsigned_32     offset;

    if( Segspec == 0 || Segspec == Data_count ) {
        Wdputslc( "\n" );
        offset = ( Data_count - 1 ) * Os2_386_head.page_size;
        offset += Os2_386_head.page_off;
        Wdputslc( "\n" );
        Wdputs( "segment # " );
        if( Segspec == 0 ) {
            Putdec( Data_count );
        } else {
            Putdec( Segspec );
        }
        Wdputs( "   offset: " );
        Puthex( offset, 8 );
        Wdputslc( "\n" );
        Wdputslc( "===========\n" );
        if( Data_count == Os2_386_head.num_pages ) {
            Dmp_seg_data( offset, Os2_386_head.l.last_page );
        } else {
            Dmp_seg_data( offset, Os2_386_head.page_size );
        }
    }
}

/*
 * Dump the Segments
 */
void Dmp_lx_page_seg( map_entry map )
/***********************************/
{
    unsigned_32     offset;

    if( Segspec == 0 || Segspec == Data_count ) {
        Wdputslc( "\n" );
        offset = map.lx.page_offset << Os2_386_head.l.page_shift;
        offset += Os2_386_head.page_off;
        Wdputslc( "\n" );
        Wdputs( "segment # " );
        if( Segspec == 0 ) {
            Putdec( Data_count );
        } else {
            Putdec( Segspec );
        }
        Wdputs( "   offset: " );
        Puthex( offset, 8 );
        Wdputslc( "\n" );
        Wdputslc( "===========\n" );
        Dmp_seg_data( offset, map.lx.data_size );
    }
}


/*
 * Dump a segment's data
 */
void Dmp_seg_data( unsigned_32 seg_off, unsigned_32 seg_len )
/***********************************************************/
{
    unsigned_16             address, amount;
    char                    buf[ PERLINE + 1 ];

    Wlseek( seg_off );
    address = 0;
    amount = PERLINE;
    for( ; seg_len != 0ul; ) {
        if( seg_len < PERLINE ) {
            amount = seg_len;
        }
        Wread( buf, amount );
        dmp_data_line( buf, address, amount );
        address += amount;
        seg_len -= amount;
    }
    Wdputslc( "\n" );
}

extern void dmp_mult_data_line( char *buf, unsigned_16 address,
                                unsigned_16 amount )
/*************************************************************/
{
    unsigned chunk;

    while( amount > 0 ) {
        if( amount >= 16 ) {
            chunk = 16;
        } else {
            chunk = amount;
        }
        dmp_data_line( buf, address, chunk );
        buf += chunk;
        address += chunk;
        amount -= chunk;
    }
}

extern void dmp_data_line( char *data, unsigned_16 address, unsigned_16 amount )
/******************************************************************************/
{
    unsigned_16     idx;
    char            *buf;

    buf = alloca( amount + 1 );
    memcpy( buf, data, amount );
    Puthex( address, 4 );
    Wdputc( ':' );
    for( idx = 0; idx < amount; ++idx ) {
        Wdputc( ' ' );
        if( (idx & 0x0007) == 0 )  Wdputc( ' ' );
            Puthex( buf[ idx ], 2 );
        if( !isprint( buf[ idx ] ) )  buf[ idx ] = ' ';
    }
    buf[ idx ] = '\0';
    while( idx < 16 ) {
        Wdputs( "   " );
        if( (idx & 0x0007) == 0 )  Wdputc( ' ' );
        ++idx;
    }
    Wdputs( "    " );
    Wdputs( buf );
    Wdputslc( "\n" );
}

⌨️ 快捷键说明

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