3

デバッグ情報なしでプログラムからのコア ダンプを分析しようとしています (Linux)。分析は C で自動的に行う必要があるため、 GDBはありません。

GDB で見たように、コマンドを使用して、スタック ポインターのトップとスタック ベース ポインター (ESP および EBP) を取得できますinfo registers。また、スタックを上下に移動すると (コマンドupdown)、現在のフレームのレジスタの更新されたバージョンが表示されます。

私の質問は、この情報はコア ダンプのどこにありますか? コア ダンプに、NT_PRSTATUS、NT_PRPSINFO、および NT_AUXV を含む NOTE セクションがあることは知っています。しかし残念なことに、そのノートに関する情報は見つかりませんでした。GDB はどのようにフレームを構築し、どこから情報を取得しますか?

4

2 に答える 2

5

最初に ELF 仕様を読んでから、linux/fs/binfmt_elf.c の関数 elf_core_dump() を読んで、コアダンプ ファイルがどのように構成されているかを知る必要があります。とにかく、次のプログラムを確認できます。

 #include <stdio.h>
 #include <elf.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <sys/procfs.h>

 int main (int argc, char **arg)
 {
Elf32_Ehdr *elfh;
Elf32_Shdr *elfsh;
Elf32_Phdr *elfphdr;
char *p = NULL;
char buf[1000], sbuf[1000];
int ret, fd, i = 0, size;

if (argc < 2) {
    printf("\nUsage: corenotes <core>\n");
    return 0;
}

fd = open(arg[1], O_RDONLY);
if (fd < 0) {
    perror("open");
    return 0;
}

/* Read ELF header*/
ret = read(fd, buf, sizeof(*elfh));
if (!ret) {
    perror("Error Reading the ELF Header");
    goto cl;
}
elfh = (Elf32_Ehdr *) buf;
/* Is it ELF*/
if ((elfh->e_ident[0] != 0x7f) || (elfh->e_ident[1] != 'E') ||
    (elfh->e_ident[2] != 'L') || (elfh->e_ident[3] != 'F')) {
    printf("\nUnrecongised File Format");
    goto cl;
}

/*
 * read program headers and print
 */
size = elfh->e_phnum * elfh->e_phentsize;
p =  malloc(size);

lseek(fd, elfh->e_phoff, SEEK_SET); 
ret = read(fd, p, size);
if (ret != size) {
    printf("\nCannot read Program Header");
    goto cl;
}
elfphdr = (Elf32_Phdr *)p;
for (i = 0; i < elfh->e_phnum; i++) {
    if (elfphdr->p_type == PT_NOTE) {
        unsigned char *pdata;
        struct note {
            unsigned int namesz;
            unsigned int descsz;
            unsigned int type;
        };
        struct note *not;
        int pad;

        pdata = malloc(elfphdr->p_filesz);
        lseek(fd, elfphdr->p_offset, SEEK_SET);
        ret = read(fd, pdata, elfphdr->p_filesz);
        not = (struct note *) pdata;
        printf("\n%s", pdata + sizeof (*not));
        pad  = 4 - (not->namesz % 4); 
        if (not->type == NT_PRSTATUS) {
            struct elf_prstatus *prs;

            prs = (struct elf_prstatus *)(pdata + sizeof(*not) + not->namesz + pad);
            printf("\nProgram Received %d", prs->pr_cursig);
            printf("\nPending Signals %08x", prs->pr_sigpend);
            printf("\nHold Signals %08x", prs->pr_sighold);
            printf("\nPID of the process %d", prs->pr_pid);
            printf("\nPPID of the process %d", prs->pr_ppid);
            printf("\nEBX: %08x", prs->pr_reg[0]);
            printf("\nECX: %08x", prs->pr_reg[1]);
            printf("\nEDX: %08x", prs->pr_reg[2]);
            printf("\nESI: %08x", prs->pr_reg[3]);
            printf("\nEDI: %08x", prs->pr_reg[4]);
            printf("\nEBP: %08x", prs->pr_reg[5]);
            printf("\nEAX: %08x", prs->pr_reg[6]);
            printf("\nXDS: %08x", prs->pr_reg[7]);
            printf("\nXES: %08x", prs->pr_reg[8]);
            printf("\nXFS: %08x", prs->pr_reg[9]);
            printf("\nXGS: %08x", prs->pr_reg[10]);
            printf("\nORG_EAX: %08x", prs->pr_reg[11]);
            printf("\nEIP: %08x", prs->pr_reg[12]);
            printf("\nECS: %08x", prs->pr_reg[13]);
            printf("\nEFLAGS: %08x", prs->pr_reg[14]);
            printf("\nESP: %08x", prs->pr_reg[15]);
            printf("\nXSS: %08x", prs->pr_reg[16]);
            pdata = pdata + sizeof(*not) + not->namesz + pad + sizeof(struct elf_prstatus);
        }
         not = (struct note *)pdata;
         if (not->type == NT_PRPSINFO) {
            struct elf_prpsinfo *prs;
            printf("\n\nNT_PRPSINF\n");
            pad  = 4 - (not->namesz % 4);
            prs = (struct elf_prpsinfo *)(pdata + sizeof(*not) + not->namesz + pad);
            printf("\nName of the Exe %s", prs->pr_fname);
        }
    //  free(pdata);
    }
    elfphdr++;
}
  free(p);      
  printf("\n\n");
  cl:   
  close(fd);
  return 0;
}
于 2012-05-11T16:15:44.277 に答える
0

elf は複雑な形式です。libelf を使用して PT_NOTE を抽出します。他をスキップして、NT_PRSTATUS に必要なものがあります。

他のプログラムを呼び出すことができれば、elfdump のほうがうまくいきます。

ここで NT_PRSTATUS 形式を見つけることができます: http://lxr.free-electrons.com/source/include/linux/elfcore.h#L42 http://lxr.free-electrons.com/source/arch/x86/include/ asm/elf.h#L116

于 2012-05-11T15:26:45.523 に答える