Add support for Linux
[elfdbg/.git] / elf.c
CommitLineData
d0dd0df1 1#include <err.h>
1960d10e
SB
2#include <fcntl.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6#include <sys/mman.h>
7#include <unistd.h>
8
9#include "elf.h"
10
11
12Elf_Obj *
13elf_init(const char *filename)
14{
15 int fd;
16 struct stat sb;
d0dd0df1
SB
17 Elf_Obj *e = NULL;
18
19 if ((fd = open(filename, O_RDONLY)) == -1)
20 errx(1, "open");
1960d10e 21
1960d10e 22 e = (Elf_Obj *)malloc(sizeof(Elf_Obj));
d0dd0df1
SB
23 if (e == NULL)
24 errx(1, "malloc");
25
1960d10e 26 e->fd = fd;
d0dd0df1
SB
27
28 if (fstat(fd, &sb) == -1)
29 errx(1, "fstat");
30
1960d10e
SB
31 e->sb = sb;
32
33 e->mm = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
d0dd0df1
SB
34 if (e->mm == MAP_FAILED)
35 errx(1, "mmap");
36
1960d10e
SB
37 e->ehdr = (Elf_Ehdr *) e->mm;
38 e->ehdr_size = e->ehdr->e_ehsize;
39
d0dd0df1
SB
40 if (e->sb.st_size < sizeof(Elf_Ehdr))
41 errx(1, "not a ELF object");
42
43 if (memcmp(e->ehdr->e_ident, ELFMAG, sizeof(ELFMAG) -1) != 0)
44 errx(1, "not a ELF object");
45
1960d10e
SB
46 e->shdr = (Elf_Shdr *) (e->mm + e->ehdr->e_shoff);
47 e->shdr_size = e->ehdr->e_shnum;
48
49 e->strtab = NULL;
50 e->strtab_size = 0;
51
d0dd0df1 52 return (e);
1960d10e
SB
53}
54
55Elf_Shdr *
56elf_strtab(Elf_Obj *e)
57{
58 Elf_Shdr *ptr;
59
60 ptr = &e->shdr[e->ehdr->e_shstrndx];
61 e->strtab = malloc(ptr->sh_size);
d0dd0df1
SB
62 if (e->strtab == NULL)
63 errx(1, "malloc %s:%d", __func__, __LINE__);
64
1960d10e
SB
65 e->strtab_size = ptr->sh_size;
66
67 memcpy(e->strtab, (e->mm + ptr->sh_offset), ptr->sh_size);
68
d0dd0df1 69 return (ptr);
1960d10e
SB
70}
71
72int
73elf_destroy(Elf_Obj *e)
74{
75 if (e == NULL)
d0dd0df1
SB
76 return (1);
77
78 if (e->mm != NULL)
79 if (munmap(e->mm, e->sb.st_size) == -1)
80 return (1);
1960d10e 81
1960d10e 82 close(e->fd);
d0dd0df1 83
1960d10e
SB
84 if (e->strtab != NULL)
85 free(e->strtab);
d0dd0df1 86
1960d10e
SB
87 free(e);
88
d0dd0df1
SB
89 return (0);
90}
91
92char *
93elf_str_get(Elf_Obj *e, int index) {
94 if (e == NULL || index > e->strtab_size)
95 return (NULL);
96
97 return (&e->strtab[e->shdr[index].sh_name]);
1960d10e
SB
98}
99
100int
101elf_debug(Elf_Obj *e)
102{
103 int i, has_debug = 0;
104 char *debug_prefix = ".debug_";
105 char *section_name = NULL;
106
107 for (i=0; i < e->shdr_size; i++) {
d0dd0df1 108 section_name = elf_str_get(e, i);
1960d10e 109 if (strnstr(section_name, debug_prefix, strlen(debug_prefix))) {
1960d10e
SB
110 has_debug++;
111 }
1960d10e
SB
112 }
113
d0dd0df1
SB
114 return (has_debug);
115}
363fc57e
SB
116
117void
118elf_debug_print(Elf_Obj *e)
119{
120 int i;
121 char *debug_prefix = ".debug_";
122 char *section_name = NULL;
123
124 printf("%d ELF debug sections:\n", elf_debug(e));
125
126 for (i=0; i < e->shdr_size; i++) {
015997ab
SB
127 if (e->shdr[i].sh_type != SHT_PROGBITS)
128 continue;
129
363fc57e
SB
130 section_name = elf_str_get(e, i);
131 if (strnstr(section_name, debug_prefix, strlen(debug_prefix))) {
132 printf("%s\n", section_name);
133 }
134 }
1960d10e 135}