【问题标题】:Is it possible to load a file full of binary data into GDB when GDB is debugging a core file?当 GDB 调试核心文件时,是否可以将充满二进制数据的文件加载到 GDB 中?
【发布时间】:2010-05-27 18:02:28
【问题描述】:

我正在使用 GDB 和核心文件调试崩溃。很大一部分内存空间被映射到进程中。那部分内存没有保存到核心文件中。我有一个文件,其中包含该映射内存中的所有数据。

我想找到一种方法将该文件中的数据以某个偏移量加载到 GDB 中,以便我可以在该地址空间内显示数据结构。这可能吗?

请注意,我已在 GDB 中尝试过“restore”命令,但它仅在调试正在运行的进程时才有效。

也许有一些工具可以让核心文件附加额外的数据?我正在尝试使用 objcopy 来查看是否可以使用此二进制数据扩充核心文件,但我还没有成功。

【问题讨论】:

    标签: c++ debugging gdb


    【解决方案1】:

    我能够让它工作的唯一方法是修改核心文件本身,使其具有包含新数据的附加程序头/节。

    理论上,我相信 objcopy 应该可以做到这一点,但是经过大量测试后我无法让它工作。相反,我求助于编写修改核心文件的 perl 脚本。

    这是为那些陷入类似情况的人准备的脚本(请注意,这是针对 i386 架构上的 ELF 核心文件):

    #!/usr/bin/perl
    
    我的@elfHeader = (
      [ident => 'A16'],
      [e_type => 'v'],
      [e_machine => 'v'],
      [e_version => 'V'],
      [e_entry => 'V'],
      [e_phoff => 'V'],
      [e_shoff => 'V'],
      [e_flags => 'V'],
      [e_ehsize => 'v'],
      [e_phentsize => 'v'],
      [e_phnum => 'v'],
      [e_shentsize => 'v'],
      [e_shnum => 'v'],
      [e_shstrndx => 'v']
    );
    
    我的@progHeader = (
      [ptype => 'V'],
      [poffset => 'V'],
      [pvaddr => 'V'],
      [ppaddr => 'V'],
      [pfilesz => 'V'],
      [pmemsz => 'V'],
      [pflags => 'V'],
      [palign => 'V'],
    );
    
    
    我的 ($core, $dataFile, $outFile) = @ARGV;
    
    主要的();
    
    
    子主{
    
      我的@stat = stat($core);
      我的 $coreSize = $stat[7];
    
      @stat = stat($dataFile);
      我的 $dfSize = $stat[7];
    
      我的 ($in, $out, $df);
      打开($in, "", $outFile) || die("无法打开 $outFile: $!");
    
      我的 $buf;
      我的 $bytes = sysread($in, $buf, 52);
    
      我的 $hdr = unpackStruct(\@elfHeader, $buf);
    
      # 修复 elf 头文件有一个额外的程序头文件
      我的 $phNum = $hdr->{e_phnum};
      $hdr->{e_phnum}++;
    
      # 修复头文件以指向程序头文件的新位置(在文件末尾)
      我的 $phOff = $hdr->{e_phoff};
      $hdr->{e_phoff} = $coreSize;
    
      # 读入完整的程序头表
      我的 $phTable;
      sysseek($in, $phOff, 0);
      我的 $readSize = $hdr->{e_phentsize} * $phNum;
      $bytes = sysread($in, $phTable, $readSize);
    
      # 在 ph 表的末尾添加一个额外的条目
      我的 $entry = packStruct(\@progHeader, {ptype => 1,
                                            poffset => $coreSize + $hdr->{e_phentsize} * $hdr->{e_phnum},
                                            pvaddr => 0x80f95000,
                                            ppaddr => 0,
                                            pfilesz => $dfSize,
                                            pmemsz => $dfSize,
                                            pflags => 7,
                                            对齐 => 4096});
    
      $phTable .= $entry;
    
      # 形成新的精灵头
      我的 $elf = packStruct(\@elfHeader, $hdr);
    
      # 输出新的头文件
      系统写入($out,$elf,长度($elf));
    
      # 将完整的核心文件复制到文件头之后
      sysseek($in, 52, 0);
      复制数据($in,$out,$coreSize - 52);
    
      # 输出新的节目表
      syswrite($out, $phTable, 长度($phTable));
    
      # 在末尾添加数据
      复制数据($df,$out,$dfSize);
    
    }
    
    
    子副本数据 {
      我的 ($in, $out, $numBytes) = @_;
    
      我的 $buf;
    
      而($numBytes > 0){
        我的 $readBytes = sysread($in, $buf, 8192);
        syswrite($out, $buf, $readBytes);
        $numBytes -= $readBytes;
      }
    
    }
    
    
    子解包结构{
      我的 ($fields, $data) = @_;
    
      我的 $unpack;
      地图 {$unpack .= $_->[1]} @{$fields};
    
      我的@vals = unpack($unpack, $data);
    
      我的%res;
      foreach 我的 $field (@{$fields}) {
        $res{$field->[0]} = shift(@vals);
      }
    
      返回 \%res;
    
    }
    
    
    子包结构{
      我的 ($fields, $data) = @_;
    
      我的 $pack;
      地图 {$pack .= $_->[1]} @{$fields};
    
      我的@vals;
      foreach 我的 $field (@{$fields}) {
        推(@vals,$data->{$field->[0]})
      }
    
      我的 $res = pack($pack, @vals);
    
      返回 $res;
    
    }
    

    【讨论】:

      【解决方案2】:
      【解决方案3】:

      据我所知,gdb 可以在核心文件或正在运行的进程上工作。您似乎在描述的是混合:运行核心文件。我认为这是不可能的,gdb documentation 表明没有其他选择。

      【讨论】:

      • 对不起,如果我不清楚:我只是使用一个核心文件,但系统没有设置来保存内存的映射部分。该内存被映射,因为它是物理映射的一大块连续 RAM。崩溃发生后,那部分 RAM 被保存到一个文件中。我想将该文件加载到 GDB 中,这样我就不必手动将该数据映射到数据结构。 objcopy 来扩充核心文件看起来很有希望,但我还没有让它工作。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-20
      • 2012-08-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多