Move ELF functions into elf.c
[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
28 if (eh->e_ehsize < sizeof(Elf_Ehdr) || !IS_ELF(*eh))
29 return 0;
30
31 if (eh->e_ident[EI_CLASS] != ELFCLASS) {
32 warnx("unexpected word size %u", eh->e_ident[EI_CLASS]);
33 return 0;
34 }
35 if (eh->e_ident[EI_VERSION] != ELF_TARG_VER) {
36 warnx("unexpected version %u", eh->e_ident[EI_VERSION]);
37 return 0;
38 }
39 if (eh->e_ident[EI_DATA] >= ELFDATANUM) {
40 warnx("unexpected data format %u", eh->e_ident[EI_DATA]);
41 return 0;
42 }
43 if (eh->e_shoff > filesize) {
44 warnx("bogus section table offset 0x%llx", (off_t)eh->e_shoff);
45 return 0;
46 }
47 if (eh->e_shentsize < sizeof(Elf_Shdr)) {
48 warnx("bogus section header size %u", eh->e_shentsize);
49 return 0;
50 }
51 if (eh->e_shnum > (filesize - eh->e_shoff) / eh->e_shentsize) {
52 warnx("bogus section header count %u", eh->e_shnum);
53 return 0;
54 }
55 if (eh->e_shstrndx >= eh->e_shnum) {
56 warnx("bogus string table index %u", eh->e_shstrndx);
57 return 0;
58 }
59
60 return 1;
61}
62
63int
64elf_getshstrtab(const char *p, size_t filesize, const char **shstrtab,
65 size_t *shstrtabsize)
66{
67 Elf_Ehdr *eh = (Elf_Ehdr *)p;
68 Elf_Shdr *sh;
69
70 sh = (Elf_Shdr *)(p + eh->e_shoff + eh->e_shstrndx * eh->e_shentsize);
71 if (sh->sh_type != SHT_STRTAB) {
72 warnx("unexpected string table type");
73 return 1;
74 }
75 if (sh->sh_offset > filesize) {
76 warnx("bogus string table offset");
77 return 1;
78 }
79 if (sh->sh_size > filesize - sh->sh_offset) {
80 warnx("bogus string table size");
81 return 1;
82 }
83 if (shstrtab != NULL)
84 *shstrtab = p + sh->sh_offset;
85 if (shstrtabsize != NULL)
86 *shstrtabsize = sh->sh_size;
87
88 return 0;
89}
90
91int
92elf_getsymtab(const char *p, const char *shstrtab, size_t shstrtabsize,
93 const Elf_Sym **symtab, size_t *nsymb)
94{
95 Elf_Ehdr *eh = (Elf_Ehdr *)p;
96 Elf_Shdr *sh;
97 size_t i;
98
99 for (i = 0; i < eh->e_shnum; i++) {
100 sh = (Elf_Shdr *)(p + eh->e_shoff + i * eh->e_shentsize);
101
102 if (sh->sh_type != SHT_SYMTAB)
103 continue;
104
105 if ((sh->sh_link >= eh->e_shnum) ||
106 (sh->sh_name >= shstrtabsize))
107 continue;
108
109 if (strncmp(shstrtab + sh->sh_name, ELF_SYMTAB,
110 strlen(ELF_SYMTAB)) == 0) {
111 if (symtab != NULL)
112 *symtab = (Elf_Sym *)(p + sh->sh_offset);
113 if (nsymb != NULL)
114 *nsymb = (sh->sh_size / sh->sh_entsize);
115
116 return 0;
117 }
118 }
119
120 return 1;
121}
122
123int
124elf_getstrtab(const char *p, const char *shstrtab, size_t shstrtabsize,
125 const char **strtab, size_t *strtabsize)
126{
127 Elf_Ehdr *eh = (Elf_Ehdr *)p;
128 Elf_Shdr *sh;
129 size_t i;
130
131 for (i = 0; i < eh->e_shnum; i++) {
132 sh = (Elf_Shdr *)(p + eh->e_shoff + i * eh->e_shentsize);
133
134 if (sh->sh_type != SHT_STRTAB)
135 continue;
136
137 if ((sh->sh_link >= eh->e_shnum) ||
138 (sh->sh_name >= shstrtabsize))
139 continue;
140
141 if (strncmp(shstrtab + sh->sh_name, ELF_STRTAB,
142 strlen(ELF_STRTAB)) == 0) {
143 if (strtab != NULL)
144 *strtab = p + sh->sh_offset;
145 if (strtabsize != NULL)
146 *strtabsize = sh->sh_size;
147
148 return 0;
149 }
150 }
151
152 return 1;
153}