Add const and unsigned when it make sense and use size_t. Also use -Wall
[elfdbg/.git] / elf.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2015 Sofian Brabez <sbz@FreeBSD.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer
12  *    in this position and unchanged.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 #include <err.h>
30 #include <fcntl.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/mman.h>
35 #include <unistd.h>
36
37 #include "elf.h"
38
39 Elf_Obj *
40 elf_init(const char *filename)
41 {
42         int fd;
43         struct stat sb;
44         Elf_Obj *e = NULL;
45
46         if ((fd = open(filename, O_RDONLY)) == -1)
47                 errx(1, "open");
48
49         e = malloc(sizeof(Elf_Obj));
50         if (e == NULL)
51                 errx(1, "malloc");
52
53         e->fd = fd;
54
55         if (fstat(fd, &sb) == -1)
56                 errx(1, "fstat");
57
58         e->sb = sb;
59
60         e->mm = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
61         if (e->mm == MAP_FAILED)
62                 errx(1, "mmap");
63
64         e->ehdr = (Elf_Ehdr *)e->mm;
65         e->ehdr_size = e->ehdr->e_ehsize;
66
67         if (e->sb.st_size < sizeof(Elf_Ehdr))
68                 errx(1, "not a ELF object %s:%d", __func__, __LINE__);
69
70         if (memcmp(e->ehdr->e_ident, ELFMAG, sizeof(ELFMAG) - 1) != 0)
71                 errx(1, "not a ELF object %s:%d", __func__, __LINE__);
72
73         e->shdr = (Elf_Shdr *)(e->mm + e->ehdr->e_shoff);
74         e->shdr_size = e->ehdr->e_shnum;
75
76         e->strtab = NULL;
77         e->strtab_size = 0;
78
79         return (e);
80 }
81
82 Elf_Shdr *
83 elf_strtab(Elf_Obj *e)
84 {
85         Elf_Shdr *ptr;
86
87         ptr = &e->shdr[e->ehdr->e_shstrndx];
88         e->strtab = malloc(ptr->sh_size);
89         if (e->strtab == NULL)
90                 errx(1, "malloc %s:%d", __func__, __LINE__);
91
92         e->strtab_size = ptr->sh_size;
93
94         memcpy(e->strtab, (e->mm + ptr->sh_offset), ptr->sh_size);
95
96         return (ptr);
97 }
98
99 int
100 elf_destroy(Elf_Obj *e)
101 {
102         if (e == NULL)
103                 return (1);
104
105         if (e->mm != NULL)
106                 if (munmap(e->mm, e->sb.st_size) == -1)
107                         return (1);
108
109         close(e->fd);
110
111         if (e->strtab != NULL)
112                 free(e->strtab);
113
114         free(e);
115
116         return (0);
117 }
118
119 char *
120 elf_str_get(Elf_Obj *e, size_t index)
121 {
122         if (e == NULL || index > e->strtab_size)
123                 return (NULL);
124
125         return (&e->strtab[e->shdr[index].sh_name]);
126 }
127
128 unsigned int
129 elf_debug_count(Elf_Obj *e)
130 {
131         unsigned int has_debug = 0;
132         const char debug_prefix[] = ".debug_";
133         char *section_name = NULL;
134
135         for (size_t i = 0; i < e->shdr_size; i++) {
136                 section_name = elf_str_get(e, i);
137         if (strnstr(section_name, debug_prefix,
138                     strlen(debug_prefix))) {
139                         has_debug++;
140                 }
141         }
142
143         return (has_debug);
144 }
145
146 void
147 elf_debug_print(Elf_Obj *e)
148 {
149         const char debug_prefix[] = ".debug_";
150         char *section_name = NULL;
151
152         printf("%u ELF debug sections:\n", elf_debug_count(e));
153
154         for (size_t i = 0; i < e->shdr_size; i++) {
155                 if (e->shdr[i].sh_type != SHT_PROGBITS)
156                         continue;
157
158                 section_name = elf_str_get(e, i);
159                 if (strnstr(section_name, debug_prefix,
160                     strlen(debug_prefix))) {
161                         printf("%s\n", section_name);
162                 }
163         }
164 }