Fix an unsigned cast madness.
[ctfdump/.git] / elf.c
CommitLineData
c36bfc0c
MP
1/*
2 * Copyright (c) 2016 Martin Pieuchot <mpi@openbsd.org>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <sys/param.h>
18#include <sys/exec_elf.h>
19
20#include <err.h>
21#include <string.h>
22
23int
24iself(const char *p, size_t filesize)
25{
26 Elf_Ehdr *eh = (Elf_Ehdr *)p;
27
87354304
MP
28 if (filesize < sizeof(Elf_Ehdr))
29 return 0;
30
c36bfc0c
MP
31 if (eh->e_ehsize < sizeof(Elf_Ehdr) || !IS_ELF(*eh))
32 return 0;
33
34 if (eh->e_ident[EI_CLASS] != ELFCLASS) {
35 warnx("unexpected word size %u", eh->e_ident[EI_CLASS]);
36 return 0;
37 }
38 if (eh->e_ident[EI_VERSION] != ELF_TARG_VER) {
39 warnx("unexpected version %u", eh->e_ident[EI_VERSION]);
40 return 0;
41 }
42 if (eh->e_ident[EI_DATA] >= ELFDATANUM) {
43 warnx("unexpected data format %u", eh->e_ident[EI_DATA]);
44 return 0;
45 }
46 if (eh->e_shoff > filesize) {
47 warnx("bogus section table offset 0x%llx", (off_t)eh->e_shoff);
48 return 0;
49 }
50 if (eh->e_shentsize < sizeof(Elf_Shdr)) {
51 warnx("bogus section header size %u", eh->e_shentsize);
52 return 0;
53 }
54 if (eh->e_shnum > (filesize - eh->e_shoff) / eh->e_shentsize) {
55 warnx("bogus section header count %u", eh->e_shnum);
56 return 0;
57 }
58 if (eh->e_shstrndx >= eh->e_shnum) {
59 warnx("bogus string table index %u", eh->e_shstrndx);
60 return 0;
61 }
62
63 return 1;
64}
65
66int
67elf_getshstrtab(const char *p, size_t filesize, const char **shstrtab,
68 size_t *shstrtabsize)
69{
70 Elf_Ehdr *eh = (Elf_Ehdr *)p;
71 Elf_Shdr *sh;
72
73 sh = (Elf_Shdr *)(p + eh->e_shoff + eh->e_shstrndx * eh->e_shentsize);
74 if (sh->sh_type != SHT_STRTAB) {
75 warnx("unexpected string table type");
76 return 1;
77 }
78 if (sh->sh_offset > filesize) {
79 warnx("bogus string table offset");
80 return 1;
81 }
82 if (sh->sh_size > filesize - sh->sh_offset) {
83 warnx("bogus string table size");
84 return 1;
85 }
86 if (shstrtab != NULL)
87 *shstrtab = p + sh->sh_offset;
88 if (shstrtabsize != NULL)
89 *shstrtabsize = sh->sh_size;
90
91 return 0;
92}
93
94int
95elf_getsymtab(const char *p, const char *shstrtab, size_t shstrtabsize,
96 const Elf_Sym **symtab, size_t *nsymb)
97{
98 Elf_Ehdr *eh = (Elf_Ehdr *)p;
99 Elf_Shdr *sh;
100 size_t i;
101
102 for (i = 0; i < eh->e_shnum; i++) {
103 sh = (Elf_Shdr *)(p + eh->e_shoff + i * eh->e_shentsize);
104
105 if (sh->sh_type != SHT_SYMTAB)
106 continue;
107
108 if ((sh->sh_link >= eh->e_shnum) ||
109 (sh->sh_name >= shstrtabsize))
110 continue;
111
112 if (strncmp(shstrtab + sh->sh_name, ELF_SYMTAB,
113 strlen(ELF_SYMTAB)) == 0) {
114 if (symtab != NULL)
115 *symtab = (Elf_Sym *)(p + sh->sh_offset);
116 if (nsymb != NULL)
117 *nsymb = (sh->sh_size / sh->sh_entsize);
118
119 return 0;
120 }
121 }
122
123 return 1;
124}
125
126int
2ef38d60
MP
127elf_getsection(const char *p, const char *sname, const char *shstrtab,
128 size_t shstrtabsize, const char **sdata, size_t *ssize)
c36bfc0c
MP
129{
130 Elf_Ehdr *eh = (Elf_Ehdr *)p;
131 Elf_Shdr *sh;
132 size_t i;
133
134 for (i = 0; i < eh->e_shnum; i++) {
135 sh = (Elf_Shdr *)(p + eh->e_shoff + i * eh->e_shentsize);
136
c36bfc0c
MP
137 if ((sh->sh_link >= eh->e_shnum) ||
138 (sh->sh_name >= shstrtabsize))
139 continue;
140
2ef38d60
MP
141 if (strncmp(shstrtab + sh->sh_name, sname,
142 strlen(sname)) == 0) {
143 if (sdata != NULL)
144 *sdata = p + sh->sh_offset;
145 if (ssize != NULL)
146 *ssize = sh->sh_size;
c36bfc0c
MP
147
148 return 0;
149 }
150 }
151
152 return 1;
153}