Search code examples
linuxgdbcpu-registerscoredump

How to extract EBP and ESP from Core Dump?


I'm trying to analyze a core dump from a program without debug infos (Linux). The analyzing should be done automatically in C, so no GDB.

As I've seen in GDB, it is possible to get the top of stack pointer and the stack base pointer (ESP and EBP) via the command info registers. And when I go up or down the stack (command up and down) I see the updated version of the registers for the current frame.

My question is, where do I find this information in the core dump? I know there is a NOTE section in the core dump that contains NT_PRSTATUS, NT_PRPSINFO and NT_AUXV. But sadly, I can't find any information about that notes. How does GDB build of the frames, where does it take the informations from?


Solution

  • First you need to read the ELF specification and then read the function elf_core_dump() in the linux/fs/binfmt_elf.c to get to know how the coredump file is organised. But anyway, you can check the following program.

     #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;
    }