dumpwv.c

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

C
990
字号
/****************************************************************************
*
*                            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:  Watcom debug format dump routines.
*
****************************************************************************/


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

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


static  int     currSect;

static  char    *sdh_msg[] = {
    "4  Module info offset   = ",
    "4  Global info offset   = ",
    "4  Address info offset  = ",
    "4  Section size         = ",
    NULL
};

/*
 * print_info_title - print out a title for an info section
 */
static void print_info_title( char *title )
/*****************************************/
{
    char        buff[80];
    char        sec;

    strcpy( buff, title );
    strcat( buff, " Info (section " );
    strcat( buff, itoa( currSect, &sec, 10 ) );
    strcat( buff, ")" );
    Banner( buff );

} /* print_info_title */

/*
 * get_len_prefix_string - make a length-prefixed string a 0 terminated string
 */
static void get_len_prefix_string( char *res, char *str )
/*******************************************************/
{
    {
        int     i;      // WTF?!
        i = 1;
    }
    memcpy( res, &str[1], str[0] );
    res[ str[0] ] = 0;

} /* get_len_prefix_string */

/*
 * dump_line_numbers - dump line number info
 */
static void dump_line_numbers( mod_info *mi )
/*******************************************/
{
    int                 i,j;
    unsigned_32         *offs;
    int                 cnt;
    v3_line_segment     *li;
    unsigned_32         coff;
    unsigned_16         size;

    cnt = mi->di[DMND_LINES].u.entries;
    if( cnt == 0 ) {
        return;
    }
    Wdputslc( "\n" );
    Wdputslc( "   *** Line Numbers ***\n" );
    Wdputslc( "   ====================\n" );

    offs = alloca( (cnt+1) * sizeof( unsigned_32 ) );
    if( offs == NULL ) {
        Wdputslc( "Error! Not enough stack.\n" );
        longjmp( Se_env, 1 );
    }
    Wlseek( Curr_sectoff + mi->di[DMND_LINES].info_off );
    Wread( offs, (cnt+1) * sizeof( unsigned_32 ) );
    Wdputs( "      " );
    Putdec( cnt );
    Wdputslc( " offset entries:\n" );
    for( i = 0; i <= cnt; i++ ) {
        Wdputs( "        offset " );
        Putdec( i );
        Wdputs( " = " );
        Puthex( offs[i], 8 );
        Wdputslc( "H\n" );
    }
    for( i = 0; i < cnt; i++ ) {
        Wlseek( Curr_sectoff + offs[i] );
        Wread( Wbuff, sizeof( v3_line_segment ) );
        li = (v3_line_segment *) Wbuff;
        coff = 0;
        while( 1 ) {
            size = (li->num-1)* sizeof( line_info );
            Wread( Wbuff + sizeof( v3_line_segment ), size );
            Wdputslc( "      -------------------------------------\n" );
            Wdputs( "      Data " );
            Putdec( i );
            Wdputs( ": offset " );
            Puthex( offs[i], 8 );
            Wdputs( "H, addr info off = " );
            Puthex( li->segment, 8 );
            Wdputs( "H, num = " );
            Putdec( li->num );
            Wdputslc( "\n" );
            for( j = 0; j < li->num; j++ ) {
                Wdputs( "        number =" );
                Putdecl( li->line[j].line_number, 5 );
                Wdputs( ",  code offset = " );
                Puthex( li->line[j].code_offset, 8 );
                Wdputslc( "H\n" );
            }
            coff += sizeof( v3_line_segment ) + size;
            if( coff >= (offs[i+1] - offs[i]) ) {
                break;
            }
            Wread( Wbuff, sizeof( v3_line_segment ) );
        }
    }

} /* dump_line_numbers */

/*
 * Get_type_index - get a type index
 */
char *Get_type_index( char *ptr, unsigned_16 *index )
/***************************************************/
{
    unsigned_16 idx;

    if( *ptr & 0x80 ) {
        idx = 0x7f & *ptr;
        idx *= 256;
        idx += *(ptr+1);
        *index = idx;
        return( ptr+2 );
    } else {
        *index = *ptr;
        return( ptr+1 );
    }

} /* Get_type_index */

/*
 * Get_local_name - get a name from a local variable data structure
 */
void Get_local_name( char *name, char *data, char *start )
/********************************************************/
{
    int len;

    len = start[0] - (data - start);
    memcpy( name, data, len );
    name[len] = 0;

} /* Get_local_name */

/*
 * dump_block - dump local block record
 */
static void dump_block( char *buff, bool is32 )
/*********************************************/
{
    block_386   *blk386;
    block       *blk;

    if( is32 ) {
        blk386 = (block_386 *) buff;
        Wdputs( "          start off = " );
        Puthex( blk386->start_offset, 8 );
        Wdputs( ", code size = " );
        Puthex( blk386->code_size, 8 );
        Wdputs( ", parent off = " );
        Puthex( blk386->parent_block_offset, 4 );
        Wdputslc( "\n" );
    } else {
        blk = (block *) buff;
        Wdputs( "          start off = " );
        Puthex( blk->start_offset, 4 );
        Wdputs( ", code size = " );
        Puthex( blk->code_size, 4 );
        Wdputs( ", parent off = " );
        Puthex( blk->parent_block_offset, 4 );
        Wdputslc( "\n" );
    }

} /* dump_block */

static char *regLocStrs[] =
{
    "AL",
    "AH",
    "BL",
    "BH",
    "CL",
    "CH",
    "DL",
    "DH",
    "AX",
    "BX",
    "CX",
    "DX",
    "SI",
    "DI",
    "BP",
    "SP",
    "CS",
    "SS",
    "DS",
    "ES",
    "ST0",
    "ST1",
    "ST2",
    "ST3",
    "ST4",
    "ST5",
    "ST6",
    "ST7",
    "EAX",
    "EBX",
    "ECX",
    "EDX",
    "ESI",
    "EDI",
    "EBP",
    "ESP",
    "FS",
    "GS"
};

/*
 * dump_single_location_entry - dump a single location expression entry
 */
static char *dump_single_location_entry( char *buff )
/***************************************************/
{
    char        type;
    addr32_ptr  *p32;
    addr48_ptr  *p48;
    int         i;
    int         num;

    type = *buff;
    buff++;
    switch( type ) {
    case 0:
        Wdputslc( "<none>\n" );
        break;
    case BP_OFFSET_BYTE:
        Wdputs( "BP_OFFSET_BYTE( " );
        Puthex( *buff, 2 );
        Wdputslc( " )\n" );
        buff++;
        break;
    case BP_OFFSET_WORD:
        Wdputs( "BP_OFFSET_WORD( " );
        Puthex( *buff, 4 );
        Wdputslc( " )\n" );
        buff += sizeof( unsigned_16 );
        break;
    case BP_OFFSET_DWORD:
        Wdputs( "BP_OFFSET_DWORD( " );
        Puthex( *buff, 8 );
        Wdputslc( " )\n" );
        buff += sizeof( unsigned_32 );
        break;
    case CONST_ADDR286:
        p32 = (addr32_ptr *) buff;
        buff += sizeof( addr32_ptr );
        Wdputs( "CONST_ADDR286( " );
        Puthex( p32->segment, 4 );
        Wdputc( ':' );
        Puthex( p32->offset, 4 );
        Wdputslc( " )\n" );
        break;
    case CONST_ADDR386:
        p48 = (addr48_ptr *) buff;
        buff += sizeof( addr48_ptr );
        Wdputs( "CONST_ADDR386( " );
        Puthex( p48->segment, 4 );
        Wdputc( ':' );
        Puthex( p48->offset, 8 );
        Wdputslc( " )\n" );
        break;
    case CONST_INT_1:
        Wdputs( "CONST_INT_1( " );
        Puthex( *buff, 2 );
        Wdputslc( " )\n" );
        buff++;
        break;
    case CONST_INT_2:
        Wdputs( "CONST_INT_2( " );
        Puthex( *buff, 4 );
        Wdputslc( " )\n" );
        buff += sizeof( unsigned_16 );
        break;
    case CONST_INT_4:
        Wdputs( "CONST_INT_4( " );
        Puthex( *buff, 8 );
        Wdputslc( " )\n" );
        buff += sizeof( unsigned_32 );
        break;
    case IND_REG_CALLOC_NEAR:
        Wdputs( "IND_REG_CALLOC_NEAR( " );
        Wdputs( regLocStrs[ *buff ] );
        Wdputslc( " )\n" );
        buff++;
        break;
    case IND_REG_CALLOC_FAR:
        Wdputs( "IND_REG_CALLOC_FAR( " );
        Wdputs( regLocStrs[ *buff ] );
        Wdputc( ':' );
        Wdputs( regLocStrs[ *(buff+1) ] );
        Wdputslc( " )\n" );
        buff += 2;
        break;
    case IND_REG_RALLOC_NEAR:
        Wdputs( "IND_REG_RALLOC_NEAR( " );
        Wdputs( regLocStrs[ *buff ] );
        Wdputslc( " )\n" );
        buff++;
        break;
    case IND_REG_RALLOC_FAR:
        Wdputs( "IND_REG_RALLOC_FAR( " );
        Wdputs( regLocStrs[ *buff ] );
        Wdputc( ':' );
        Wdputs( regLocStrs[ *(buff+1) ] );
        Wdputslc( " )\n" );
        buff += 2;
        break;
    case OPERATOR_IND_2:
        Wdputslc( "OPERATOR_IND_2\n" );
        break;
    case OPERATOR_IND_4:
        Wdputslc( "OPERATOR_IND_4\n" );
        break;
    case OPERATOR_IND_ADDR286:
        Wdputslc( "OPERATOR_IND_ADDR286\n" );
        break;
    case OPERATOR_IND_ADDR386:
        Wdputslc( "OPERATOR_IND_ADDR386\n" );
        break;
    case OPERATOR_ZEB:
        Wdputslc( "OPERATOR_ZEB\n" );
        break;
    case OPERATOR_ZEW:
        Wdputslc( "OPERATOR_ZEW\n" );
        break;
    case OPERATOR_MK_FP:
        Wdputslc( "OPERATOR_MK_FP\n" );
        break;
    case OPERATOR_POP:
        Wdputslc( "OPERATOR_POP\n" );
        break;
    case OPERATOR_XCHG:
        Wdputs( "OPERATOR_XCHG: " );
        Puthex( *buff, 2 );
        Wdputslc( "\n" );
        buff++;
        break;
    case OPERATOR_ADD:
        Wdputslc( "OPERATOR_ADD\n" );
        break;
    case OPERATOR_DUP:
        Wdputslc( "OPERATOR_DUP\n" );
        break;
    case OPERATOR_NOP:
        Wdputslc( "OPERATOR_NOP\n" );
        break;
    default:
        if( type & 0x30 ) {
            num = (type & 0x0f)+1;
            Wdputs( "MULTI_REG(" );
            Putdec( num );
            Wdputs( "): " );
            for( i=0;i<num;i++ ) {
                Wdputs( regLocStrs[ *buff ] );
                if( i != num-1 ) {
                    Wdputs( ", " );
                } else {
                    Wdputslc( "\n" );
                }
                buff++;
            }
        } else if( type & 0x40 ) {
            Wdputs( "REG: " );
            Wdputs( regLocStrs[ type & 0x0f ] );
            Wdputslc( "\n" );
        } else {
            Wdputslc( "**** UNKNOWN LOCATION EXPRESSION!! ****\n" );
        }
        break;
    }

    return( buff );

} /* dump_single_location_entry */

/*
 * Dump_location_expression - dump out a location expression
 */
char *Dump_location_expression( char *buff, char *spacing )
/*********************************************************/
{
    int         multi;
    char        *end;

    if( *buff & 0x80 ) {
        end = buff + (*buff & 0x7f);
        buff++;
        multi = 1;
    } else {
        end = buff + 1;
        multi = 0;
    }
    while( buff < end ) {
        switch( multi ) {
        case 1:
            multi = 2;
            Wdputslc( "\n" );
            /* fall through */
        case 2:
            Wdputslc( spacing );
            break;
        }
        buff = dump_single_location_entry( buff );
    }
    return( buff );
} /* Dump_location_expression */

/*
 * dump_rtn - dump a near or far routine defn
 */
static void dump_rtn( char *buff )
/********************************/
{
    int         pro,epi;
    unsigned_16 ret_off;
    char        *ptr;
    int         num_parms;
    unsigned_16 index;
    char        name[256];
    int         i;

    dump_block( buff, FALSE );

    ptr = buff + sizeof( block );
    pro = *ptr++;
    epi = *ptr++;
    Wdputs( "          prologue size = " );
    Putdec( pro );
    Wdputs( ",  epilogue size = " );
    Putdec( epi );
    Wdputslc( "\n" );

    ret_off = *(unsigned_16 *) ptr;
    ptr += sizeof( unsigned_16 );
    Wdputs( "          return address offset (from bp) = " );
    Puthex( ret_off, 4 );

⌨️ 快捷键说明

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