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