⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ntoutl.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
字号:
/****************************************************************************
*
*                            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:  QNX Neutrino debugger utility functions.
*
****************************************************************************/


#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "mad.h"
#include "bool.h"
#include "ntocomm.h"


#ifndef ELF_SIGNATURE
    #define ELF_SIGNATURE   "\177ELF"
#endif

#ifdef DEBUG_OUT
void Out( const char *str )
{
    write( 1, (char *)str, strlen( str ) );
}

void OutNum( unsigned long i )
{
    char    numbuff[16];
    char    *ptr;

    ptr = numbuff+10;
    *--ptr = '\0';
    do {
        *--ptr = ( i % 16 ) + '0';
        if( *ptr > '9' )
            *ptr += 'A' - '9' - 1;
        i /= 16;
    } while( i != 0 );
    Out( ptr );
}
#endif

/* Read a block memory in debuggee's address space */
unsigned ReadMem( pid_handle procfs_fd, void *ptr, addr_off offv, unsigned size )
{
    int     length = 0;
    
    if( lseek( procfs_fd, (off_t)offv, SEEK_SET ) == (off_t)offv ) {
        length = read( procfs_fd, ptr, size );
        if( length < 0 ) {
            dbg_print(( "ReadMem failed\n" ));
            length = 0;
        }
    }
    return( length );
}

/* Write a block of memory in debuggee's address space */
unsigned WriteMem( pid_handle procfs_fd, void *ptr, addr_off offv, unsigned size )
{
    int     length = 0;

    if( lseek( procfs_fd, (off_t)offv, SEEK_SET ) == (off_t)offv ) {
        length = write( procfs_fd, ptr, size );
        if( length < 0 ) {
            dbg_print(( "WriteMem failed\n" ));
            length = 0;
        }
    }
    return( length );
}


/* Obtain address of the dynamic section from the program
 * header. If anything unexpected happens, give up. Note that the
 * address is unrelocated, but usually it will match the actual VA.
 */
addr_off GetDynSection( const char *exe_name )
{
    addr_off    result = 0;
    Elf32_Ehdr  ehdr;
    Elf32_Phdr  phdr;
    int         fd;
    size_t      i;

    fd = open( exe_name, O_RDONLY );
    if( fd < 0 ) {
        return( result );
    }
    if( read( fd, &ehdr, sizeof( ehdr ) ) >= sizeof( ehdr ) &&
        memcmp( ehdr.e_ident, ELF_SIGNATURE, 4 ) == 0 &&
        ehdr.e_phoff != 0 &&
        ehdr.e_phentsize >= sizeof( phdr ) &&
        lseek( fd, ehdr.e_phoff, SEEK_SET ) == ehdr.e_phoff ) {
        for( i = 0; i < ehdr.e_phnum; i++ ) {
            if( read( fd, &phdr, sizeof phdr ) < sizeof( phdr ) )
                break;
            if( phdr.p_type == PT_DYNAMIC ) {
                result = phdr.p_vaddr;
                break;
            }
            if( lseek( fd, ehdr.e_phentsize - sizeof( phdr ), SEEK_CUR ) < 0 )
                break;
        }
    }
    close( fd );
    dbg_print(( "DynSection at: %08x\n", (unsigned)result ));
    return( result );
}

/* Read dynamic linker rendezvous structure from debuggee's address space
 * and return its offset, as well as offset of the dynamic linker breakpoint.
 * Note that it is perfectly valid for this function to fail - that will 
 * happen if the debuggee is statically linked.
 */
int GetLdInfo( pid_handle pid, addr_off dynsec_off, addr_off *rdebug_off, addr_off *ld_bp_off )
{
    Elf32_Dyn       loc_dyn;
    struct r_debug  rdebug;
    addr_off        rdebug_ptr = 0;
    unsigned        read_len;

    if( dynsec_off == 0 ) {
        dbg_print(( "GetLdInfo: dynamic section not available\n" ));
        return( FALSE );
    }
    read_len = sizeof( loc_dyn );
    if( ReadMem( pid, &loc_dyn, dynsec_off, read_len ) != read_len ) {
        dbg_print(( "GetLdInfo: failed to copy first dynamic entry\n" ));
        return( FALSE );
    }
    while( loc_dyn.d_tag != DT_NULL ) {
        if( loc_dyn.d_tag == DT_DEBUG ) {
            rdebug_ptr = loc_dyn.d_un.d_ptr;
            dbg_print(( "GetLdInfo: DT_DEBUG entry found (%08lx)\n", rdebug_ptr ));
            break;
        }
        dynsec_off += sizeof( Elf32_Dyn );
        if( ReadMem( pid, &loc_dyn, dynsec_off, read_len ) != read_len ) {
            dbg_print(( "GetLdInfo: failed to copy dynamic entry\n" ));
            return( FALSE );
        }
    }
    if( rdebug_ptr == 0 ) {
        dbg_print(( "GetLdInfo: DT_DEBUG entry not found or not set\n" ));
        return( FALSE );
    }
    read_len = sizeof( rdebug );
    if( ReadMem( pid, &rdebug, rdebug_ptr, read_len ) != read_len ) {
        dbg_print(( "GetLdInfo: failed to copy r_debug struct\n" ));
        return( FALSE );
    }
    *rdebug_off = rdebug_ptr;
    *ld_bp_off  = rdebug.r_brk;
    dbg_print(( "GetLdInfo: dynamic linker rendezvous structure found\n" ));
    return( TRUE );
}

/* Like strcpy() but source string is in debuggee's address space. Not
 * very efficient, use sparingly!
 */
char *dbg_strcpy( pid_handle pid, char *s1, const char *s2 )
{
    char    *dst = s1;
    char    c;

    do {
        if( ReadMem( pid, &c, (addr48_off)s2, 1 ) != 1 ) {
            dbg_print(( "dbg_strcpy: failed at %08x\n", (unsigned)s2 ));
            return( NULL );
        }
        *dst++ = c;
        ++s2;
    } while( c );

    return( s1 );
}

/* Copy a link map struct from debuggee address space to memory
 * provided by caller.
 */
int GetLinkMap( pid_handle pid, addr_off dbg_lmap_off, struct link_map *local_lmap )
{
    unsigned    read_len;

    read_len = sizeof( *local_lmap );
    if( ReadMem( pid, local_lmap, dbg_lmap_off, read_len ) != read_len ) {
        dbg_print(( "GetLinkMap: failed to copy link_map struct at %08x\n", (unsigned)dbg_lmap_off ));
        return( FALSE );
    }
    return( TRUE );
}


/* Map an address to a link-time VA (map offset) in the module that
 * it belongs to. Preferably used on a base address of a module.
 */
int MapAddrToLinkVA( pid_handle pid, addr_off addr, addr_off *map_addr )
{
    procfs_debuginfo    dbg_info;

    dbg_info.vaddr = addr;
    if( devctl( pid, DCMD_PROC_MAPDEBUG, &dbg_info, sizeof( dbg_info ), 0 ) != EOK ) {
        dbg_print(( "MapAddrToLinkVA: failed to map address\n" ));
        return( FALSE );
    }
    *map_addr = dbg_info.vaddr;
    return( TRUE );
}


/* Break up program arguments passed in as a single string into
 * individual components. Useful for passing argv style array to
 * exec().
 */
int SplitParms( char *p, char *args[], unsigned len )
{
    int     i;
    char    endc;

    i = 0;
    if( len == 1 ) goto done;
    for( ;; ) {
        for( ;; ) {
            if( len == 0 ) goto done;
            if( *p != ' ' && *p != '\t' ) break;
            ++p;
            --len;
        }
        if( len == 0 ) goto done;
        if( *p == '"' ) {
            --len;
            ++p;
            endc = '"';
        } else {
            endc = ' ';
        }
        if( args != NULL ) {
            args[i] = p;
        }
        ++i;
        for( ;; ) {
            if( len == 0 ) goto done;
            if( *p == endc || *p == '\0' || (endc == ' ' && *p == '\t') ) {
                if( args != NULL ) {
                    *p = '\0';  //NYI: not a good idea, should make a copy
                }
                ++p;
                --len;
                if( len == 0 ) goto done;
                break;
            }
            ++p;
            --len;
        }
    }
done:
    return( i );
}

⌨️ 快捷键说明

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