Re: magic file entry to understand core dumps

Jeremy Fitzhardinge (jeremy@zip.com.au)
Sun, 21 Jul 1996 21:08:15 +1000


This is a multi-part message in MIME format.

--------------4A6501B25EBBC8F7EDB6F7D
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Darrin R. Smith wrote:
> No -- `file` used to give the name of the prog. that dumped
> the core file. Since the switchover to elf, it's output was changed
> to the garbage^h^h^h^h^h^h^h useless info line you see above. This has
> been irritating me for a long time -- I would *love* to see the old
> functionality put back in.

Here's a program to do more than you want. It should be easy enough to
hack or hack into 'file'.

Sorry it's a MIME attachment; its the best I can do now.

J

--------------4A6501B25EBBC8F7EDB6F7D
Content-Type: text/plain; charset=us-ascii; name="dcore.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="dcore.c"

/*
* Show goo about ELF core files
* Jeremy Fitzhardinge <jeremy@zip.com.au> 1996
*/
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <linux/elf.h>
#include <linux/elfcore.h>

static void fperror(const char *str)
{
perror(str);
exit(1);
}

static size_t myread(int fd, void *buf, size_t sz)
{
size_t ret;

if ((ret = read(fd, buf, sz)) != sz)
fperror("read failed");
return ret;
}

static void print_prstatus(const prstatus_t *pr)
{
unsigned i;
static const char *regs[] = { "ebx", "ecx", "edx", "esi", "edi", "ebp",
"eax", "ds", "es", "fs", "gs",
"orig_eax", "eip", "cs",
"efl", "uesp", "ss"};

printf(" pid=%d ppid=%d pgrp=%d sid=%d\n",
pr->pr_pid, pr->pr_ppid, pr->pr_pgrp, pr->pr_sid);
for(i = 0; i < NGREG; i++)
{
unsigned long val = pr->pr_reg[i];
printf(" %-2u %-5s=%08lx %lu\n", i, regs[i], val, val);
}
}

static void print_prpsinfo(const prpsinfo_t *ps)
{
printf(" uid=%d gid=%d\n", ps->pr_uid, ps->pr_gid);
printf(" comm=%s\n", ps->pr_fname);
printf(" psargs=%s\n", ps->pr_psargs);
}

#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))

static void do_note(int fd, Elf32_Phdr *phdr)
{
off_t here = lseek(fd, 0, SEEK_CUR);
int size = phdr->p_filesz;
char *raw = alloca(size), *end;
end = raw+size;

lseek(fd, phdr->p_offset, SEEK_SET);
myread(fd, raw, size);

while(raw < end)
{
Elf32_Nhdr *note = (Elf32_Nhdr *)raw;
const char *str;
const char *name, *desc;

raw += sizeof(*note);
name = raw;
raw += roundup(note->n_namesz, sizeof(long));
desc = raw;
raw += roundup(note->n_descsz, sizeof(long));

printf(" name=%.*s", (int)note->n_namesz, name);

if(strncmp(name, "CORE", note->n_namesz) != 0)
{
printf("\n");
continue;
}

switch(note->n_type)
{
#define X(x) case x: str = #x; break;
X(NT_PRSTATUS);
X(NT_PRFPREG);
X(NT_PRPSINFO);
X(NT_TASKSTRUCT);
#undef X
default:
str = "???";
}
printf(" n_type=%s n_descsz=%ld\n",
str, note->n_descsz);
switch(note->n_type)
{
case NT_PRSTATUS:
print_prstatus((prstatus_t *)desc);
break;
case NT_PRPSINFO:
print_prpsinfo((prpsinfo_t *)desc);
break;
}
}
lseek(fd, here, SEEK_SET);
}

int main(int argc, char *argv[])
{
int fd;
Elf32_Ehdr elf;
int i;

if (argc != 2)
{
fprintf(stderr, "Usage: %s corefile\n", argv[0]);
exit(1);
}

if ((fd = open(argv[1], O_RDONLY)) == -1)
fperror("open of core");

myread(fd, &elf, sizeof(elf));

if (memcmp(ELFMAG, elf.e_ident, SELFMAG) != 0)
printf("bad magic\n");

if (elf.e_ident[EI_CLASS] != ELFCLASS32)
printf("wrong class\n");

if (elf.e_ident[EI_DATA] != ELFDATA2LSB)
printf("wrong endianess\n");

if (elf.e_ident[EI_VERSION] != EV_CURRENT)
printf("wrong version\n");

{
const char *str;
switch(elf.e_type)
{
#define C(x) case ET_##x: str = #x; break;
C(NONE);
C(REL);
C(EXEC);
C(DYN);
C(CORE);
#undef C
default: str = "???"; break;
}
printf("elf file type ET_%s\n", str);
}

if (elf.e_machine != EM_386 && elf.e_machine != EM_486)
printf("not i386 or i486\n");

if (elf.e_ehsize != sizeof(elf))
printf("wrong header size\n");

if (elf.e_phentsize != sizeof(Elf32_Phdr))
printf("wrong phdr size\n");

if (lseek(fd, elf.e_phoff, SEEK_SET) != (off_t)elf.e_phoff)
fperror("lseek to phdr failed\n");

for(i = 0; i < elf.e_phnum; i++)
{
Elf32_Phdr phdr;
const char *str;

myread(fd, &phdr, sizeof(phdr));
switch(phdr.p_type)
{
#define C(x) case PT_##x: str = #x; break;
C(NULL);
C(LOAD);
C(DYNAMIC);
C(INTERP);
C(NOTE);
C(SHLIB);
C(PHDR);
#undef C
default:
str = "???"; break;
}
printf("type PT_%s off=%ld vaddr=%lx filesz=%ld flags=%lx\n",
str, phdr.p_offset, phdr.p_vaddr, phdr.p_filesz,
(unsigned long)phdr.p_flags);
if (phdr.p_type == PT_NOTE)
do_note(fd, &phdr);
}
exit(0);
}

--------------4A6501B25EBBC8F7EDB6F7D--