1a1b5ec25Sjsg /*-
2a1b5ec25Sjsg * Copyright (c) 2006,2008 Joseph Koshy
3a1b5ec25Sjsg * All rights reserved.
4a1b5ec25Sjsg *
5a1b5ec25Sjsg * Redistribution and use in source and binary forms, with or without
6a1b5ec25Sjsg * modification, are permitted provided that the following conditions
7a1b5ec25Sjsg * are met:
8a1b5ec25Sjsg * 1. Redistributions of source code must retain the above copyright
9a1b5ec25Sjsg * notice, this list of conditions and the following disclaimer.
10a1b5ec25Sjsg * 2. Redistributions in binary form must reproduce the above copyright
11a1b5ec25Sjsg * notice, this list of conditions and the following disclaimer in the
12a1b5ec25Sjsg * documentation and/or other materials provided with the distribution.
13a1b5ec25Sjsg *
14a1b5ec25Sjsg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15a1b5ec25Sjsg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16a1b5ec25Sjsg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17a1b5ec25Sjsg * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18a1b5ec25Sjsg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19a1b5ec25Sjsg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20a1b5ec25Sjsg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21a1b5ec25Sjsg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22a1b5ec25Sjsg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23a1b5ec25Sjsg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24a1b5ec25Sjsg * SUCH DAMAGE.
25a1b5ec25Sjsg */
26a1b5ec25Sjsg
27a1b5ec25Sjsg #include <assert.h>
28a1b5ec25Sjsg #include <gelf.h>
29a1b5ec25Sjsg #include <libelf.h>
30a1b5ec25Sjsg #include <stdlib.h>
31a1b5ec25Sjsg
32a1b5ec25Sjsg #include "_libelf.h"
33a1b5ec25Sjsg
34*63b93652Sjsg ELFTC_VCSID("$Id: libelf_phdr.c,v 1.3 2020/05/18 06:46:23 jsg Exp $");
35a1b5ec25Sjsg
36a1b5ec25Sjsg void *
_libelf_getphdr(Elf * e,int ec)37a1b5ec25Sjsg _libelf_getphdr(Elf *e, int ec)
38a1b5ec25Sjsg {
39a1b5ec25Sjsg size_t phnum;
40a1b5ec25Sjsg size_t fsz, msz;
41a1b5ec25Sjsg uint64_t phoff;
42a1b5ec25Sjsg Elf32_Ehdr *eh32;
43a1b5ec25Sjsg Elf64_Ehdr *eh64;
44a1b5ec25Sjsg void *ehdr, *phdr;
45a1b5ec25Sjsg _libelf_translator_function *xlator;
46a1b5ec25Sjsg
47a1b5ec25Sjsg assert(ec == ELFCLASS32 || ec == ELFCLASS64);
48a1b5ec25Sjsg
49a1b5ec25Sjsg if (e == NULL) {
50a1b5ec25Sjsg LIBELF_SET_ERROR(ARGUMENT, 0);
51a1b5ec25Sjsg return (NULL);
52a1b5ec25Sjsg }
53a1b5ec25Sjsg
54a1b5ec25Sjsg if ((phdr = (ec == ELFCLASS32 ?
55a1b5ec25Sjsg (void *) e->e_u.e_elf.e_phdr.e_phdr32 :
56a1b5ec25Sjsg (void *) e->e_u.e_elf.e_phdr.e_phdr64)) != NULL)
57a1b5ec25Sjsg return (phdr);
58a1b5ec25Sjsg
59a1b5ec25Sjsg /*
60a1b5ec25Sjsg * Check the PHDR related fields in the EHDR for sanity.
61a1b5ec25Sjsg */
62a1b5ec25Sjsg
63a1b5ec25Sjsg if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
64a1b5ec25Sjsg return (NULL);
65a1b5ec25Sjsg
66a1b5ec25Sjsg phnum = e->e_u.e_elf.e_nphdr;
67a1b5ec25Sjsg
68a1b5ec25Sjsg if (ec == ELFCLASS32) {
69a1b5ec25Sjsg eh32 = (Elf32_Ehdr *) ehdr;
70a1b5ec25Sjsg phoff = (uint64_t) eh32->e_phoff;
71a1b5ec25Sjsg } else {
72a1b5ec25Sjsg eh64 = (Elf64_Ehdr *) ehdr;
73a1b5ec25Sjsg phoff = (uint64_t) eh64->e_phoff;
74a1b5ec25Sjsg }
75a1b5ec25Sjsg
76a1b5ec25Sjsg fsz = gelf_fsize(e, ELF_T_PHDR, phnum, e->e_version);
77a1b5ec25Sjsg
78a1b5ec25Sjsg assert(fsz > 0);
79a1b5ec25Sjsg
80e219834fSjsg if (phoff + fsz < phoff) { /* Numeric overflow. */
81e219834fSjsg LIBELF_SET_ERROR(HEADER, 0);
82e219834fSjsg return (NULL);
83e219834fSjsg }
84e219834fSjsg
85a1b5ec25Sjsg if ((uint64_t) e->e_rawsize < (phoff + fsz)) {
86a1b5ec25Sjsg LIBELF_SET_ERROR(HEADER, 0);
87a1b5ec25Sjsg return (NULL);
88a1b5ec25Sjsg }
89a1b5ec25Sjsg
90*63b93652Sjsg if ((msz = _libelf_msize(ELF_T_PHDR, ec, EV_CURRENT)) == 0)
91*63b93652Sjsg return (NULL);
92a1b5ec25Sjsg
93a1b5ec25Sjsg if ((phdr = calloc(phnum, msz)) == NULL) {
94a1b5ec25Sjsg LIBELF_SET_ERROR(RESOURCE, 0);
95a1b5ec25Sjsg return (NULL);
96a1b5ec25Sjsg }
97a1b5ec25Sjsg
98a1b5ec25Sjsg if (ec == ELFCLASS32)
99a1b5ec25Sjsg e->e_u.e_elf.e_phdr.e_phdr32 = phdr;
100a1b5ec25Sjsg else
101a1b5ec25Sjsg e->e_u.e_elf.e_phdr.e_phdr64 = phdr;
102a1b5ec25Sjsg
103a1b5ec25Sjsg
104a1b5ec25Sjsg xlator = _libelf_get_translator(ELF_T_PHDR, ELF_TOMEMORY, ec,
105a1b5ec25Sjsg _libelf_elfmachine(e));
106a1b5ec25Sjsg (*xlator)(phdr, phnum * msz, e->e_rawfile + phoff, phnum,
107a1b5ec25Sjsg e->e_byteorder != LIBELF_PRIVATE(byteorder));
108a1b5ec25Sjsg
109a1b5ec25Sjsg return (phdr);
110a1b5ec25Sjsg }
111a1b5ec25Sjsg
112a1b5ec25Sjsg void *
_libelf_newphdr(Elf * e,int ec,size_t count)113a1b5ec25Sjsg _libelf_newphdr(Elf *e, int ec, size_t count)
114a1b5ec25Sjsg {
115a1b5ec25Sjsg void *ehdr, *newphdr, *oldphdr;
116a1b5ec25Sjsg size_t msz;
117a1b5ec25Sjsg
118a1b5ec25Sjsg if (e == NULL) {
119a1b5ec25Sjsg LIBELF_SET_ERROR(ARGUMENT, 0);
120a1b5ec25Sjsg return (NULL);
121a1b5ec25Sjsg }
122a1b5ec25Sjsg
123a1b5ec25Sjsg if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) {
124a1b5ec25Sjsg LIBELF_SET_ERROR(SEQUENCE, 0);
125a1b5ec25Sjsg return (NULL);
126a1b5ec25Sjsg }
127a1b5ec25Sjsg
128a1b5ec25Sjsg assert(e->e_class == ec);
129a1b5ec25Sjsg assert(ec == ELFCLASS32 || ec == ELFCLASS64);
130a1b5ec25Sjsg assert(e->e_version == EV_CURRENT);
131a1b5ec25Sjsg
132*63b93652Sjsg if ((msz = _libelf_msize(ELF_T_PHDR, ec, e->e_version)) == 0)
133*63b93652Sjsg return (NULL);
134a1b5ec25Sjsg
135a1b5ec25Sjsg newphdr = NULL;
136a1b5ec25Sjsg if (count > 0 && (newphdr = calloc(count, msz)) == NULL) {
137a1b5ec25Sjsg LIBELF_SET_ERROR(RESOURCE, 0);
138a1b5ec25Sjsg return (NULL);
139a1b5ec25Sjsg }
140a1b5ec25Sjsg
141a1b5ec25Sjsg if (ec == ELFCLASS32) {
142a1b5ec25Sjsg if ((oldphdr = (void *) e->e_u.e_elf.e_phdr.e_phdr32) != NULL)
143a1b5ec25Sjsg free(oldphdr);
144a1b5ec25Sjsg e->e_u.e_elf.e_phdr.e_phdr32 = (Elf32_Phdr *) newphdr;
145a1b5ec25Sjsg } else {
146a1b5ec25Sjsg if ((oldphdr = (void *) e->e_u.e_elf.e_phdr.e_phdr64) != NULL)
147a1b5ec25Sjsg free(oldphdr);
148a1b5ec25Sjsg e->e_u.e_elf.e_phdr.e_phdr64 = (Elf64_Phdr *) newphdr;
149a1b5ec25Sjsg }
150a1b5ec25Sjsg
151a1b5ec25Sjsg e->e_u.e_elf.e_nphdr = count;
152a1b5ec25Sjsg
153a1b5ec25Sjsg elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY);
154a1b5ec25Sjsg
155a1b5ec25Sjsg return (newphdr);
156a1b5ec25Sjsg }
157