2010-05-25 1 views
3

Я отлаживаю сбой с использованием GDB и файла ядра. Большая часть пространства памяти вставляется в процесс. Эта часть памяти не сохраняется в основном файле. У меня есть файл, содержащий все данные в этой mmapped памяти.Можно ли загружать файл, полный двоичных данных, в GDB, когда GDB отлаживает основной файл?

Я хотел бы найти способ загрузить данные из этого файла в GDB с определенным смещением, чтобы я мог отображать объекты данных в этом адресном пространстве. Это возможно?

Обратите внимание, что я пробовал команду «restore» в GDB, но он работает только при отладке запущенного процесса.

Возможно, есть инструменты, которые позволяют базовому файлу добавлять к нему дополнительные данные? Я экспериментирую с objcopy, чтобы увидеть, могу ли я увеличить файл ядра с помощью этих двоичных данных, но я еще не успел.

ответ

2

Единственный способ, которым я смог заставить это работать, это изменить сам файл ядра, чтобы иметь дополнительный заголовок/раздел программы, содержащий новые данные.

В теории я считаю, что objcopy должен быть в состоянии сделать это, но после многих испытаний мне не удалось заставить его работать. Вместо этого я приступил к написанию скрипта perl, который изменил основной файл.

Вот сценарий для тех из вас застрял в подобной ситуации (обратите внимание, что это для основных файлов ELF на i386 арку):

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

} 
0

Насколько я знаю, gdb работает либо с файлом ядра, либо с запущенным процессом. То, что вы, кажется, описываете, - это гибрид: запуск основного файла. Я не думаю, что это возможно, и gdb documentation предполагает, что других вариантов нет.

+0

Извините, если я не был ясен: я просто используя файл ядра, но система не была установка, чтобы сохранить mmapped части памяти. Эта память mmapped, потому что это большой кусок физически отображенной непрерывной ОЗУ. После сбоя эта часть ОЗУ была сохранена в файле. Я хочу загрузить этот файл в GDB, чтобы мне не пришлось вручную сопоставлять эти данные с datastructures. objcopy для увеличения основного файла выглядит многообещающим, но я еще не получил его на работу. – efunneko

Смежные вопросы