当GDB正在调试一个核心文件时,是否可以将一个包含二进制数据的文件加载到GDB中? [英] Is it possible to load a file full of binary data into GDB when GDB is debugging a core file?

查看:164
本文介绍了当GDB正在调试一个核心文件时,是否可以将一个包含二进制数据的文件加载到GDB中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用GDB和核心文件调试崩溃。大部分内存空间被划分到该进程中。存储器的该部分不会保存到核心文件中。我有一个包含该内存中所有数据的文件。



我想找到一种方法,以某种偏移方式将数据从该文件加载到GDB中,以便我可以在该地址空间内显示数据结构。这可能吗?注意,我已经在GDB中尝试了' restore '命令,但它只能在调试运行的进程时起作用。



也许有些工具允许核心文件附加附加数据?我正在试验objcopy,看看是否可以用这个二进制数据来扩充核心文件,但是我还没有成功。

解决方案

我能够让这个工作的唯一方法是修改核心文件本身以增加一个程序头/部分包含新的数据。



理论上,我相信objcopy应该能够做到这一点,但经过很多测试,我无法得到它工作。相反,我诉诸于编写一个修改核心文件的perl脚本。



这是您处于类似情况的脚本(请注意,这适用于ELF在i386拱顶上的核心文件):

#!/ 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;

main();


sub main {

我的@stat = stat($ core);
我的$ coreSize = $ stat [7];

@stat = stat($ dataFile);
我的$ dfSize = $ stat [7];

我的($ in,$ out,$ df);
open($ in,,$ outFile)|| die(无法打开$ outFile:$!);

我$ buf;
my $ bytes = sysread($ in,$ buf,52);

我的$ hdr = unpackStruct(\ @ elfHeader,$ buf);

#修复elf标头有一个额外的程序头
我的$ phNum = $ hdr - > {e_phnum};
$ hdr - > {e_phnum} ++;

#修复标题以指向程序头的新位置(在文件末尾)
my $ phOff = $ hdr - > {e_phoff};
$ hdr - > {e_phoff} = $ coreSize;

#阅读完整的程序头表
我的$ phTable;
sysseek($ in,$ phOff,0);
我的$ readSize = $ hdr - > {e_phentsize} * $ phNum;
$ bytes = sysread($ in,$ phTable,$ readSize);

#在ph表的末尾添加一个附加条目
my $ entry = packStruct(\ @ progHeader,{ptype => 1,
poffset => $ coreSize + $ hdr - > {e_phentsize} * $ hdr - > {e_phnum},
pvaddr => 0x80f95000,
ppaddr => 0,
pfilesz => $ dfSize,
pmemsz => $ dfSize,
pflags => 7,
palign => 4096});

$ phTable。= $ entry;

#形成新的elf标头
我的$ elf = packStruct(\ @ elfHeader,$ hdr);

#输出新标题
syswrite($ out,$ elf,length($ elf));

#复制标题后的完整核心文件
sysseek($ in,52,0);
copyData($ in,$ out,$ coreSize - 52);

#输出新的程序表
syswrite($ out,$ phTable,length($ phTable));

#添加结尾的数据
copyData($ df,$ out,$ dfSize);

}


sub copyData {
我的($ in,$ out,$ numBytes)= @_;

我的$ buf;

while($ numBytes> 0){
我的$ readBytes = sysread($ in,$ buf,8192);
syswrite($ out,$ buf,$ readBytes);
$ numBytes - = $ readBytes;
}

}


sub unpackStruct {
我的($ fields,$ data)= @_;

我的$ unpack;
map {$ unpack。= $ _-> [1]} @ {$ fields};

我的@vals = unpack($ unpack,$ data);

我的%res;
foreach我的$字段(@ {$ fields}){
$ res {$ field - > [0]} = shift(@vals);
}

return \%res;

}


sub packStruct {
我的($ fields,$ data)= @_;

我的$ pack;
map {$ pack。= $ _-> [1]} @ {$ fields};

我的@vals;
foreach我的$字段(@ {$ fields}){
push(@vals,$ data - > {$ field - > [0]})
}

my $ res = pack($ pack,@vals);

return $ res;

}


I am debugging a crash using GDB and a core file. A large portion of the memory space is mmapped into the process. That portion of the memory is not saved into the core file. I have a file that contains all the data in that mmapped memory.

I would like to find a way to load the data from that file into GDB at a certain offset so that I can display datastructures within that address space. Is this possible?

Note that I have tried the 'restore' command in GDB but it only works when debugging a running process.

Perhaps there are tools that allow a core file to have additional data appended to it? I am experimenting with objcopy to see if I can augment the core file with this binary data, but I have not been successful yet.

解决方案

The only way that I was able to get this to work was to modify the core file itself to have an additional program header/section that contained the new data.

In theory, I believe that objcopy should be able to do this, but after a lot of testing I was unable to get it to work. Instead, I resorted to writing a perl script that modified the core file.

Here is the script for those of you stuck in a similar situation (note that this is for ELF core files on an i386 arch):

#!/usr/bin/perl

my @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']
);

my @progHeader = (
  [ptype => 'V'],
  [poffset => 'V'],
  [pvaddr => 'V'],
  [ppaddr => 'V'],
  [pfilesz => 'V'],
  [pmemsz => 'V'],
  [pflags => 'V'],
  [palign => 'V'],
);


my ($core, $dataFile, $outFile) = @ARGV;

main();


sub main {

  my @stat = stat($core);
  my $coreSize = $stat[7];

  @stat = stat($dataFile);
  my $dfSize = $stat[7];

  my ($in, $out, $df);
  open($in, "", $outFile) || die("Couldn't open $outFile: $!");

  my $buf;
  my $bytes = sysread($in, $buf, 52);

  my $hdr = unpackStruct(\@elfHeader, $buf);

  # Fix the elf header to have an additional program header
  my $phNum = $hdr->{e_phnum};
  $hdr->{e_phnum}++;

  # Fix the header to point to a new location for the program headers (at the end of the file)
  my $phOff = $hdr->{e_phoff};
  $hdr->{e_phoff} = $coreSize;

  # Read in the full program header table
  my $phTable;
  sysseek($in, $phOff, 0);
  my $readSize = $hdr->{e_phentsize} * $phNum;
  $bytes = sysread($in, $phTable, $readSize);

  # Add an additional entry to the end of the ph table
  my $entry = packStruct(\@progHeader, {ptype => 1, 
                                        poffset => $coreSize + $hdr->{e_phentsize} * $hdr->{e_phnum},
                                        pvaddr => 0x80f95000,
                                        ppaddr => 0,
                                        pfilesz => $dfSize,
                                        pmemsz => $dfSize,
                                        pflags => 7,
                                        palign => 4096});

  $phTable .= $entry;

  # Form the new elf header
  my $elf = packStruct(\@elfHeader, $hdr);

  # Output the new header
  syswrite($out, $elf, length($elf));

  # Copy the full core file after the header
  sysseek($in, 52, 0);
  copyData($in, $out, $coreSize - 52);

  # Output the new program table
  syswrite($out, $phTable, length($phTable));

  # Add the data on the end
  copyData($df, $out, $dfSize);

}


sub copyData {
  my ($in, $out, $numBytes) = @_;

  my $buf;

  while ($numBytes > 0) {
    my $readBytes = sysread($in, $buf, 8192);
    syswrite($out, $buf, $readBytes);
    $numBytes -= $readBytes;
  }

}


sub unpackStruct {
  my ($fields, $data) = @_;

  my $unpack;
  map {$unpack .= $_->[1]} @{$fields};

  my @vals = unpack($unpack, $data);

  my %res;
  foreach my $field (@{$fields}) {
    $res{$field->[0]} = shift(@vals);
  }

  return \%res;

}


sub packStruct {
  my ($fields, $data) = @_;

  my $pack;
  map {$pack .= $_->[1]} @{$fields};

  my @vals;
  foreach my $field (@{$fields}) {
    push(@vals, $data->{$field->[0]})
  }

  my $res = pack($pack, @vals);

  return $res;

}

这篇关于当GDB正在调试一个核心文件时,是否可以将一个包含二进制数据的文件加载到GDB中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆