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

📄 linuxmap.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:  Routines to keep track of loaded modules and address maps.
*
****************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include "trpimp.h"
#include "mad.h"
#include "exeelf.h"
#include "linuxcomm.h"

typedef struct lli {
    addr_off    offset;
    addr_off    dbg_dyn_sect;
    addr_off    code_size;
    char        newly_unloaded : 1;
    char        newly_loaded : 1;
    char        filename[257]; // TODO: These should really be dynamic!
} lib_load_info;

static lib_load_info    *moduleInfo;
static int              ModuleTop;

/*
 * FindLib - find a shared lib entry in the list
 */
lib_load_info *FindLib( addr_off dynsection )
{
    unsigned    i;

    for( i = 0; i < ModuleTop; ++i ) {
        if( moduleInfo[i].dbg_dyn_sect == dynsection )
            return( &moduleInfo[i] );
    }
    return( NULL );
}

struct link_map *FindLibInLinkMap( struct link_map *first_lmap, addr_off dyn_base )
{
    struct link_map     lmap;
    struct link_map     *dbg_lmap;

    dbg_lmap = first_lmap;
    while( dbg_lmap != NULL ) {
        if( !GetLinkMap( pid, dbg_lmap, &lmap ) ) break;
        if( (addr_off)lmap.l_ld == dyn_base )
            return( dbg_lmap );
        dbg_lmap = lmap.l_next;
    }
    return( NULL );
}

/*
 * AddProcess - a new process has been created
 */
void AddProcess( void )
{
    lib_load_info       *lli;

    moduleInfo = malloc( sizeof( lib_load_info ) );
    memset( moduleInfo, 0, sizeof( lib_load_info ) );
    ModuleTop = 1;

    lli = &moduleInfo[0];

    lli->offset = 0;    /* Assume that main executable was not relocated */
    lli->filename[0] = '\0';
}

/*
 * AddLib - a new library has loaded
 */
void AddLib( struct link_map *lmap )
{
    lib_load_info       *lli;

    /* This code is not terribly efficient */
    ModuleTop++;
    lli = malloc( ModuleTop * sizeof( lib_load_info ) );
    memset( lli, 0, ModuleTop * sizeof( lib_load_info ) );
    memcpy( lli, moduleInfo, (ModuleTop - 1) * sizeof( lib_load_info ) );
    free( moduleInfo );
    moduleInfo = lli;
    lli = &moduleInfo[ModuleTop - 1];

    lli->offset = lmap->l_addr;
    lli->dbg_dyn_sect = (addr_off)lmap->l_ld;
    dbg_strcpy( pid, lli->filename, lmap->l_name );
    lli->newly_loaded = TRUE;
    lli->newly_unloaded = FALSE;
    lli->offset = lmap->l_addr;

    Out( "Added library: ofs/dyn = " );
    OutNum( lmap->l_addr );
    Out( "/" );
    OutNum( (addr_off)lmap->l_ld );
    Out( " " );
    Out( lli->filename );
    Out( "\n" );
}

void DelLib( addr_off dynsection )
{
    unsigned    i;

    for( i = 0; i < ModuleTop; ++i ) {
        if( moduleInfo[i].dbg_dyn_sect == dynsection ) {
            Out( "Deleting library " );
            Out( moduleInfo[i].filename );
            Out( "\n" );
            moduleInfo[i].newly_unloaded = TRUE;
            moduleInfo[i].offset = 0;
            moduleInfo[i].dbg_dyn_sect = 0;
            moduleInfo[i].code_size = 0;
            break;
        }
    }
}

void DelProcess( void )
{
    unsigned    i;

    for( i = 0; i < ModuleTop; ++i ) {
        moduleInfo[i].offset = 0;
        moduleInfo[i].dbg_dyn_sect = 0;
        moduleInfo[i].code_size = 0;
    }
}


/*
 * AddInitialLibs - called the first time we can get information
 * about loaded shared libs.
 */
int AddInitialLibs( struct link_map *first_lmap )
{
    struct link_map     lmap;
    struct link_map     *dbg_lmap;
    int                 count = 0;

    dbg_lmap = first_lmap;
    while( dbg_lmap != NULL ) {
        if( !GetLinkMap( pid, dbg_lmap, &lmap ) ) break;
        AddLib( &lmap );
        ++count;
        dbg_lmap = lmap.l_next;
    }
    return( count );
}

/*
 * AddOneLib - called when dynamic linker is adding a library. Unfortunately
 * we don't get told which library, so we just have to zip through the list
 * until we find one we don't know about yet.
 */
int AddOneLib( struct link_map *first_lmap )
{
    struct link_map     lmap;
    struct link_map     *dbg_lmap;
    int                 count = 0;
    lib_load_info       *lli;

    dbg_lmap = first_lmap;
    while( dbg_lmap != NULL ) {
        if( !GetLinkMap( pid, dbg_lmap, &lmap ) ) break;
        lli = FindLib( (addr_off)lmap.l_ld );
        if( lli == NULL ) {
            AddLib( &lmap );
            ++count;
        }
        dbg_lmap = lmap.l_next;
    }
    return( count );
}

/*
 * DelOneLib - called when dynamic linker is deleting a library. Unfortunately
 * we don't get told which library, so we just have to zip through our list
 * until we find out which one is suddenly missing.
 */
int DelOneLib( struct link_map *first_lmap )
{
    int                 count = 0;
    int                 i;
    addr_off            dyn_base;

    for( i = 0; i < ModuleTop; ++i ) {
        dyn_base = moduleInfo[i].dbg_dyn_sect;
        if( dyn_base != 0 ) {
            if( FindLibInLinkMap( first_lmap, dyn_base ) == NULL ) {
                DelLib( dyn_base );
            }
        }
    }
    return( count );
}

/*
 * AccMapAddr - map address in image from link-time virtual address to
 * actual linear address as loaded in memory. For executables, this will
 * in effect return the address unchanged (image base 0x08048100 equals
 * linear 0x08048100), for shared libs this will typically add the offset
 * from zero (link time VA) to actual load base.
 */
unsigned ReqMap_addr( void )
{
    map_addr_req    *acc;
    map_addr_ret    *ret;
    unsigned long   val;
    lib_load_info   *lli;

    // Note: Info about the process address space is stored in the user register
    //       for GDB, so we can use that to find out what we need to convert these
    //       values in here...
    acc = GetInPtr( 0 );
    CONV_LE_32( acc->in_addr.offset );
    CONV_LE_16( acc->in_addr.segment );
    CONV_LE_32( acc->handle );
    ret = GetOutPtr( 0 );
    ret->lo_bound = 0;
    ret->hi_bound = ~(addr_off)0;
    errno = 0;
    if( (val = ptrace( PTRACE_PEEKUSER, pid, (void *)(offsetof( user_struct, start_code )), 0 )) == -1 ) {
        if( errno ) {
            Out( "ReqMap_addr: first PTRACE_PEEKUSER failed!\n" );
            val = 0;
        }
    }
#ifdef __MIPS__
    // Hack for MIPS - the above call seems to be failing but isn't returning
    // an error; it's possible that the call just isn't valid.
    val = 0;
#endif
    ret->out_addr.offset = acc->in_addr.offset + val;

    if( acc->handle > ModuleTop ) {
        Out( "ReqMap_addr: Invalid handle passed!\n" );
        return( sizeof( *ret ) );
    } else {
        lli = &moduleInfo[acc->handle];
    }

    Out( "ReqMap_addr: addr " );
    OutNum( acc->in_addr.segment );
    Out( ":" );
    OutNum( acc->in_addr.offset );
    Out( " in module " );
    OutNum( acc->handle );
    if( acc->in_addr.segment == MAP_FLAT_DATA_SELECTOR ||
        acc->in_addr.segment == flatDS ) {
        if( (val = ptrace( PTRACE_PEEKUSER, pid, (void *)offsetof( user_struct, u_tsize ), 0 )) == -1 ) {
            if( errno ) {
                Out( "ReqMap_addr: second PTRACE_PEEKUSER failed!\n" );
                val = 0;
            }
        }
        ret->out_addr.offset += val;
        ret->out_addr.segment = flatDS;
    } else {
        ret->out_addr.segment = flatCS;
    }
    ret->out_addr.offset += lli->offset;
    Out( " to " );
    OutNum( ret->out_addr.offset );
    Out( "\n" );
    CONV_LE_32( ret->out_addr.offset );
    CONV_LE_16( ret->out_addr.segment );
    CONV_LE_32( ret->lo_bound );
    CONV_LE_32( ret->hi_bound );
    return( sizeof( *ret ) );
}

/*
 * AccGetLibName - get lib name of current module
 */
unsigned ReqGet_lib_name( void )
{
    get_lib_name_req    *acc;
    get_lib_name_ret    *ret;
    char                *name;
    unsigned            i;
    unsigned            ret_len = sizeof( *ret );

    acc = GetInPtr( 0 );
    CONV_LE_32( acc->handle );
    ret = GetOutPtr( 0 );
    name = GetOutPtr( sizeof( *ret ) );

    ret->handle = 0;
    name[0] = '\0';

    for( i = 0; i < ModuleTop; ++i ) {
        if( moduleInfo[i].newly_unloaded ) {
            Out( "(newly unloaded) " );
            ret->handle = i;
            name[0] = '\0';
            moduleInfo[i].newly_unloaded = FALSE;
            ret_len = sizeof( *ret );
            break;
        } else if( moduleInfo[i].newly_loaded ) {
            Out( "(newly loaded) " );
            ret->handle = i;
            strcpy( name, moduleInfo[i].filename );
            moduleInfo[i].newly_loaded = FALSE;
            ret_len = sizeof( *ret ) + strlen( name ) + 1;
            break;
        }
    }
    Out( "ReqGet_lib_name: in handle " );
    OutNum( acc->handle );
    Out( " out handle " );
    OutNum( ret->handle );
    Out( "\n" );
    CONV_LE_32( ret->handle );
    return( ret_len );
}

⌨️ 快捷键说明

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