GDB 用内容初始化数组

问题描述 投票:0回答:1

我没有找到我要找的东西,所以我会提出我自己的问题。

考虑下面的 C 程序

char heap[<some-static-size>];

void main() {
  <this-code-reads-and-writes-to-heap>
}

我想在初始化

gdb
之后在
heap
中执行这个程序。一种可能性是我将数组的内容放入一个文件中,并以某种方式将其提供给 gdb。我怎样才能最简单地做到这一点?一旦
main
完成,我想读取
heap
的内容并将其写入其他文件。

arrays c memory initialization gdb
1个回答
0
投票

您可以创建一个共享库来执行以下操作:

  1. 在构造函数中,基于环境变量
    HEAPFILE
    ,执行
    mmap
    ,因此
    heap
    被 R/W 映射到
    HEAPFILE
    (注意:涉及欺骗,请参阅下面的代码)
  2. 目标程序将具有
    heap
    设置[神奇地;-)]。
  3. 当目标程序完成时,共享库析构函数会将[可能修改的]
    heap
    的内容复制到文件
    HEAPOUT

这是共享库代码。请注意,虽然它有一些错误检查,并且它有效,但它可以清理一下。

// libtst.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/mman.h>

#if DEBUG
#define dbgprt(_fmt...) \
    printf(_fmt)
#else
#define dbgprt(_fmt...) \
    do { } while (0)
#endif

// exported to target program
char *heap;                             // pointer to heap
size_t heapsize;                        // bytes in heap

// private
static char *heap_file;                 // input file
static char *heap_ofile;                // output file
static int heap_fd;                     // open file descriptor for heap_file
static struct stat heap_st;             // result of stat for heap_file

void __attribute__((constructor))
fakeinit(void)
{

    do {
        // get input file name
        heap_file = getenv("HEAPFILE");
        if (heap_file == NULL)
            break;

        // get output file name
        heap_ofile = getenv("HEAPOUT");
        if (heap_ofile == NULL)
            break;

        // open input file
        heap_fd = open(heap_file,O_RDONLY);
        if (heap_fd < 0)
            break;

        // get input file size (and export this for target program)
        if (fstat(heap_fd,&heap_st) < 0)
            break;
        heapsize = heap_st.st_size;

        // map this for the target program
        // NOTE: by using PROT_READ/PROT_WRITE target program will think this
        // is an ordinary array, but MAP_PRIVATE will prevent original file
        // from being altered
        heap = mmap(NULL,heapsize,
            PROT_READ | PROT_WRITE,
            MAP_PRIVATE,
            heap_fd,0);

        if (heap == MAP_FAILED) {
            dbgprt("fakeinit: FAILED\n");
            heap = NULL;
            break;
        }
    } while (0);
}

void __attribute__((destructor))
fakefini(void)
{

    do {
        // open the output file
        int fdout = open(heap_ofile,O_RDWR | O_CREAT,0644);
        if (fdout < 0)
            break;

        // enlarge output file to correct size
        dbgprt("fakefini: heapsize=%zu\n",heapsize);
        ftruncate(fdout,heapsize);

        // map the output file R/W
        char *outbuf = mmap(NULL,heapsize,
            PROT_READ | PROT_WRITE,
            MAP_SHARED,
            fdout,0);
        if (outbuf == MAP_FAILED) {
            dbgprt("fakefini: FAILED\n");
            break;
        }

        // put data into output file
        memcpy(outbuf,heap,heapsize);

        // unmap/close output file
        munmap(outbuf,heapsize);
        close(fdout);

        // unmap/close input file
        munmap(heap,heapsize);
        close(heap_fd);
    } while (0);
}

这是要测试运行的示例程序:

// test.c -- sample program to be run under test
#include <stddef.h>

// set by shared library
extern char *heap;
extern size_t heapsize;

int
main(void)
{

    heap[0] += 1;
    heap[1] += 1;
    heap[2] += 1;

    return 0;
}

这是一个构建/运行脚本:

#!/bin/bash

cc -o libtst.so -shared -fpic libtst.c -g -DDEBUG=1
cc -o test test.c ./libtst.so -g

echo "abc" > old
rm -f new

env HEAPFILE=old HEAPOUT=new ./test

head -1000 old new

这是

sh -x ./build
的输出:

+ cc -o libtst.so -shared -fpic libtst.c -g -DDEBUG=1
+ cc -o test test.c ./libtst.so -g
+ echo abc
+ rm -f new
+ env HEAPFILE=old HEAPOUT=new ./test
fakefini: heapsize=4
+ head -1000 old new
==> old <==
abc

==> new <==
bcd
© www.soinside.com 2019 - 2024. All rights reserved.