jitdump.c

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

C
363
字号
/****************************************************************************
*
*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "watcom.h"
#include "jit.h"
#include "dis.h"

static const char       *archTypes[ JIT_ARCH_LAST ] = {
        "JIT_ARCH_I86",
        "JIT_ARCH_SPARC" };

static const char       *relocTypes[ JIT_RELOC_LAST ] = {
    #define _str( x ) #x
    #define JitReloc(x) _str( JIT_RELOC_##x ),
    JitRelocs
    #undef JitReloc
    #undef _str
};

static const char       *helperTypes[ JIT_RTC_end ] = {
    #define JitRtc(x) #x,
    JitRtcs
    #undef JitRtc
};

static void myPrintf( void (*output)( char ), char *fmt, ... )
{
    va_list     args;
    char        buffer[ 1024 ];
    char        *ptr;

    va_start( args, fmt );
    vsprintf( &buffer[ 0 ], fmt, args );
    va_end( args );
    ptr = &buffer[ 0 ];
    while( *ptr ) {
        output( *ptr++ );
    }
}

static void FmtHexNum( char *buff, unsigned prec, unsigned long value )
{
    sprintf( buff, "0x%*.*lx", prec, prec, value );
}

static void FmtSizedHexNum( char *buff, dis_dec_ins *ins, unsigned op_num )
{
    unsigned            size;
    unsigned            i;
    unsigned            len;

    static const unsigned long mask[] = {
        0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff, 0xffffffff
    };

    size = 0;
    for( i = 0; i < ins->num_ops; ++i ) {
        switch( ins->op[i].ref_type ) {
        case DRT_X86_BYTE:
            len = 1;
            break;
        case DRT_X86_WORD:
            len = 2;
            break;
        case DRT_X86_DWORD:
        case DRT_X86_DWORDF:
            len = 4;
            break;
        default:
            len = 0;
            break;
        }
        if( len > size ) size = len;
    }
    if( size == 0 ) size = 4;
    FmtHexNum( buff, size * 2, mask[size] & ins->op[op_num].value );
}

typedef struct {
    char const  *start;
    int         offset;
    int         length;
    dis_cpu     cpu;
}code_buff;

extern dis_return DisCliGetData( void *d, unsigned off, int size, void *data )
{
    code_buff   *header;

    header = (code_buff *)d;
    if( ( off + size + header->offset ) > header->length ) {
        size = header->length - ( header->offset + off );
    }
    memcpy( data, header->start+header->offset+off, size );
    return( DR_OK );
}

extern unsigned DisCliValueString( void *d, dis_dec_ins *ins, unsigned op_num, char *buff )
{
    dis_operand         *op;
    code_buff   *header;

    header = (code_buff *)d;
    buff[0] = '\0';
    op = &ins->op[op_num];
    switch( op->type & DO_MASK ) {
    case DO_RELATIVE:
    case DO_MEMORY_REL:
    case DO_ABSOLUTE:
    case DO_MEMORY_ABS:
        switch( op->type & DO_MASK ) {
            case DO_RELATIVE:
            case DO_MEMORY_REL:
                op->value += header->offset;
                break;
        }
        if( op->base == DR_NONE && op->index == DR_NONE ) {
            FmtSizedHexNum( buff, ins, op_num );
        } else if( op->value > 0 ) {
            FmtHexNum( buff, 0, op->value );
        } else if( op->value < 0 ) {
            buff[0] = '-';
            FmtHexNum( &buff[1], 0, -op->value );
        }
        break;
    case DO_IMMED:
        // FmtSizedHexNum( buff, ins, op_num );
        if( op->value < 0 ) {
            buff[0] = '-';
            FmtHexNum( &buff[1], 0, -op->value );
        } else {
            FmtHexNum( buff, 0, op->value );
        }
        break;
    }
    return( strlen( buff ) );
}

static void dumpSection( void (*output)( char ), char *type, jit_data_sec *section )
{
    myPrintf( output, "\t%s.offset\t=%d\n", type, section->offset );
    myPrintf( output, "\t%s.size  \t=%d\n", type, section->size );
}

static void dumpOpcodes( void (*output)( char ), char const *what, unsigned size )
{
    unsigned            i;

    myPrintf( output, "\t" );
    for( i = 0; i < size; i++ ) {
        myPrintf( output, "%2.2x ", what[i] );
    }
    while( i < 10 ) {
        myPrintf( output, "   " );
        i++;
    }
}

#define MAX_INS_NAME    24
#define MAX_OBJ_NAME    1024

static void dumpCodeBuff( void (*output)( char ),
                          code_buff *buff )
{
    dis_handle          handle;
    dis_dec_ins         ins;
    char                name[ MAX_INS_NAME ];
    char                ops[ MAX_OBJ_NAME + 24 ];

    DisInit( buff->cpu, &handle );
    while( buff->offset < buff->length ){
        DisDecodeInit( &handle, &ins );
        if( buff->cpu == DISCPU_x86 ) {
            ins.flags |= DIF_X86_USE32_FLAGS;
        }
        DisDecode( &handle, buff, &ins );
        DisFormat( &handle, buff, &ins, DFF_AXP_SYMBOLIC_REG|DFF_PSEUDO, &name, &ops );
        myPrintf( output, "\t%4.4x:", buff->offset );
        dumpOpcodes( output, buff->start+buff->offset, ins.size );
        myPrintf( output, "\t%s\t%s\n", name, ops );
        buff->offset += ins.size;
    }
    DisFini( &handle );
}

static void dumpCode( void (*output)( char ), jit_code_str *header )
{
    code_buff           buff;

    buff.cpu = DISCPU_x86;
    if( header->arch == JIT_ARCH_SPARC ) {
        buff.cpu = DISCPU_sparc;
    }
    buff.offset = 0;
    buff.length = header->code.size;
    buff.start = (char *)header+header->code.offset;
    dumpCodeBuff( output, &buff );
}

extern void DumpCodeStr(
             char const *buffer,
             unsigned   len,
             void       (*output)( char ) )
{
    code_buff           buff;

    buff.cpu = DISCPU_x86;
    buff.offset = 0;
    buff.length = len;
    buff.start = buffer;
    dumpCodeBuff( output, &buff );
}

static void dumpData( void (*output)( char ), jit_code_str *header )
{
    int offset;
    char *curr;
    curr = (char *)header + header->data.offset;
    for( offset = 0; offset < header->data.size; offset += 4 ) {
        myPrintf( output, "\t%4.4x:%4.4x\n", offset, *(long*)curr );
        curr+= 4;
    }
}
static void dumpOneReloc( void (*output)( char ), jit_code_str *header, jit_reloc *reloc )
{
    assert( reloc->type < JIT_RELOC_LAST );
    myPrintf( output, "\ttype:   %d (%s)\n", reloc->type, relocTypes[ reloc->type ] );
    myPrintf( output, "\toffset: 0x%4.4x\n", reloc->location - header->code.offset );
    myPrintf( output, "\ttarget: " );
    switch( reloc->type ) {
    case JIT_RELOC_METHOD_OFFSET:
    case JIT_RELOC_FIELD_OFFSET:
    case JIT_RELOC_METHOD_ADDR:
    case JIT_RELOC_FIELD_ADDR:
        myPrintf( output, "cp_index=%d\n", reloc->u.cp_index );
        break;
    case JIT_RELOC_DATA_REF:
        myPrintf( output, "addend=%d\n", reloc->u.addend );
        break;
    case JIT_RELOC_HELPER_FUNC:
        myPrintf( output, "helper_func=%s\n",helperTypes[ reloc->u.helper_index] );
        break;
    case JIT_RELOC_RT_FUNC:
        myPrintf( output, "rt_func=%d\n", reloc->u.rt_index );
        break;
    case JIT_RELOC_METHOD_HANDLE:
        myPrintf( output, "method=%d\n", reloc->u.cp_index );
    case JIT_RELOC_CLASS_HANDLE:
    case JIT_RELOC_INTERFACE_HANDLE:
        myPrintf( output, "class=%d\n", reloc->u.cp_index );
        break;
    }
    myPrintf( output, "\t*******************************\n" );
}

static void dumpRelocs( void (*output)( char ), jit_code_str *header )
{
    int                 i;
    int                 count;
    jit_reloc           *curr;

    curr = (jit_reloc *)((char *)header + header->relocs.offset);
    count = header->relocs.size / sizeof( jit_reloc );
    for( i = 0; i < count; i++, curr++ ) {
        dumpOneReloc( output, header, curr );
    }
}

static void dumpEhTable( void (*output)( char ), jit_code_str *header )
{
    int                 i;
    int                 count;
    jit_eh_table       *curr;
    int offset;

    curr = (jit_eh_table *)((char *)header + header->eh_table.offset);
    count = header->eh_table.size / sizeof( jit_eh_table );
    offset = 0;
    myPrintf( output, "\toffset:beg end handler class\n" );
    for( i = 0; i < count; i++, curr++ ) {
        myPrintf( output, "\t  %4.4x:%4.4x %4.4x %4.4x    %4.4x\n", offset,
            curr->beg,curr->end,curr->handler,curr->cp_index );
        offset += sizeof( jit_eh_table );
    }
}

static void dumpPData( void (*output)( char ), jit_code_str *header )
{
    jit_pdata           *pdata;

    pdata = (jit_pdata *)( (char *) header + header->pdata.offset );
    myPrintf( output, "\troutine beg    = %4.4x\n", pdata->rtn_beg );
    myPrintf( output, "\tprolog end     = %4.4x\n", pdata->pro_end );
    myPrintf( output, "\tepilog beg     = %4.4x\n", pdata->epi_beg );
    myPrintf( output, "\troutine end    = %4.4x\n", pdata->rtn_end );
    myPrintf( output, "\tparms          = %4.4x\n", pdata->parms );
    myPrintf( output, "\tlocals         = %4.4x\n", pdata->locals );
}

void DumpJitCodeStr( const char *buffer, unsigned len, void (*output)( char ) )
{
    jit_code_str        *header;

    header = (jit_code_str *)buffer;
    switch( header->arch ) {
    case JIT_ARCH_I86:
    case JIT_ARCH_SPARC:
        myPrintf( output, "arch: %d (%s)\n", header->arch, archTypes[ header->arch ] );
        dumpSection( output, "code", &header->code );
        dumpSection( output, "data", &header->data );
        dumpSection( output, "eh_table", &header->eh_table );
        dumpSection( output, "pdata", &header->pdata );
        dumpSection( output, "relocs", &header->relocs );
        myPrintf( output, "code:\n" );
        dumpCode( output, header );
        myPrintf( output, "data:\n" );
        dumpData( output, header );
        myPrintf( output, "eh_table:\n" );
        dumpEhTable( output, header );
        myPrintf( output, "pdata:\n" );
        dumpPData( output, header );
        myPrintf( output, "relocs:\n" );
        dumpRelocs( output, header );
        break;
    default:
        myPrintf( output, "not a valid code string: arch = %d\n", header->arch );
    }
}

⌨️ 快捷键说明

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