2 * a simple elf core file backtrace viewer
4 * Copyright (C) 2010-2013 Ali Gholami Rudi
6 * This program is released under the Modified BSD license.
17 /* simplified elf struct and macro names */
19 # define Elf_Phdr Elf64_Phdr
20 # define Elf_Ehdr Elf64_Ehdr
22 # define Elf_Phdr Elf32_Phdr
23 # define Elf_Ehdr Elf32_Ehdr
26 #define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
27 #define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
29 static long readlong(char *mem
, unsigned long addr
)
31 Elf_Ehdr
*ehdr
= (void *) mem
;
32 Elf_Phdr
*phdr
= (void *) (mem
+ ehdr
->e_phoff
);
34 for (i
= 0; i
< ehdr
->e_phnum
; i
++) {
35 unsigned long beg
= phdr
[i
].p_vaddr
;
36 if (addr
>= beg
&& addr
< beg
+ phdr
[i
].p_filesz
) {
37 unsigned long diff
= addr
- beg
;
38 return *(long *) (mem
+ phdr
[i
].p_offset
+ diff
);
44 static void dump_prstatus(char *mem
, struct elf_prstatus
*prs
)
46 struct user_regs_struct
*regs
= (void *) &prs
->pr_reg
;
47 unsigned long bp
= regs
->bp
;
48 printf("ip=%lx, sp=%lx, bp=%lx\n\n", regs
->ip
, regs
->sp
, regs
->bp
);
49 printf("\t%lx: %lx\n", regs
->ip
, regs
->bp
);
51 printf("\t%lx: %lx\n",
52 readlong(mem
, bp
+ sizeof(long)), readlong(mem
, bp
));
53 bp
= readlong(mem
, bp
);
64 static void dumpnote(char *mem
, char *note
, int len
)
66 struct elfnote
*elfnote
;
67 char *end
= note
+ len
;
69 elfnote
= (void *) note
;
70 note
+= sizeof(*elfnote
);
71 note
+= ALIGN(elfnote
->namesz
, 4);
72 if (elfnote
->type
== NT_PRSTATUS
)
73 dump_prstatus(mem
, (void *) note
);
74 note
+= ALIGN(elfnote
->descsz
, 4);
78 static void dumpelf(char *mem
)
80 Elf_Ehdr
*ehdr
= (void *) mem
;
81 Elf_Phdr
*phdr
= (void *) (mem
+ ehdr
->e_phoff
);
82 if (ehdr
->e_type
== ET_CORE
&& phdr
[0].p_type
== PT_NOTE
)
83 dumpnote(mem
, mem
+ phdr
[0].p_offset
, phdr
[0].p_filesz
);
86 static void die(char *msg
)
92 static long filesize(int fd
)
99 int main(int argc
, char **argv
)
105 printf("Usage: %s path\n", argv
[0]);
108 fd
= open(argv
[1], O_RDONLY
);
112 mem
= mmap(NULL
, size
, PROT_READ
, MAP_SHARED
, fd
, 0);