1/*-
2 * Copyright (c) 2006,2008 Joseph Koshy
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <assert.h>
28#include <gelf.h>
29#include <libelf.h>
30#include <limits.h>
31#include <stdint.h>
32#include <string.h>
33
34#include "_libelf.h"
35
36ELFTC_VCSID("$Id: gelf_ehdr.c 3177 2015-03-30 18:19:41Z emaste $");
37
38Elf32_Ehdr *
39elf32_getehdr(Elf *e)
40{
41	return (_libelf_ehdr(e, ELFCLASS32, 0));
42}
43
44Elf64_Ehdr *
45elf64_getehdr(Elf *e)
46{
47	return (_libelf_ehdr(e, ELFCLASS64, 0));
48}
49
50GElf_Ehdr *
51gelf_getehdr(Elf *e, GElf_Ehdr *d)
52{
53	int ec;
54	Elf32_Ehdr *eh32;
55	Elf64_Ehdr *eh64;
56
57	if (d == NULL || e == NULL ||
58	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
59		LIBELF_SET_ERROR(ARGUMENT, 0);
60		return (NULL);
61	}
62
63	if (ec == ELFCLASS32) {
64		if ((eh32 = _libelf_ehdr(e, ELFCLASS32, 0)) == NULL)
65			return (NULL);
66
67		(void) memcpy(d->e_ident, eh32->e_ident,
68		    sizeof(eh32->e_ident));
69		d->e_type		= eh32->e_type;
70		d->e_machine		= eh32->e_machine;
71		d->e_version		= eh32->e_version;
72		d->e_entry		= eh32->e_entry;
73		d->e_phoff		= eh32->e_phoff;
74		d->e_shoff		= eh32->e_shoff;
75		d->e_flags		= eh32->e_flags;
76		d->e_ehsize		= eh32->e_ehsize;
77		d->e_phentsize		= eh32->e_phentsize;
78		d->e_phnum		= eh32->e_phnum;
79		d->e_shentsize		= eh32->e_shentsize;
80		d->e_shnum		= eh32->e_shnum;
81		d->e_shstrndx		= eh32->e_shstrndx;
82
83		return (d);
84	}
85
86	assert(ec == ELFCLASS64);
87
88	if ((eh64 = _libelf_ehdr(e, ELFCLASS64, 0)) == NULL)
89		return (NULL);
90	*d = *eh64;
91
92	return (d);
93}
94
95Elf32_Ehdr *
96elf32_newehdr(Elf *e)
97{
98	return (_libelf_ehdr(e, ELFCLASS32, 1));
99}
100
101Elf64_Ehdr *
102elf64_newehdr(Elf *e)
103{
104	return (_libelf_ehdr(e, ELFCLASS64, 1));
105}
106
107void *
108gelf_newehdr(Elf *e, int ec)
109{
110	if (e != NULL &&
111	    (ec == ELFCLASS32 || ec == ELFCLASS64))
112		return (_libelf_ehdr(e, ec, 1));
113
114	LIBELF_SET_ERROR(ARGUMENT, 0);
115	return (NULL);
116}
117
118int
119gelf_update_ehdr(Elf *e, GElf_Ehdr *s)
120{
121	int ec;
122	void *ehdr;
123	Elf32_Ehdr *eh32;
124	Elf64_Ehdr *eh64;
125
126	if (s== NULL || e == NULL || e->e_kind != ELF_K_ELF ||
127	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
128		LIBELF_SET_ERROR(ARGUMENT, 0);
129		return (0);
130	}
131
132	if (e->e_cmd == ELF_C_READ) {
133		LIBELF_SET_ERROR(MODE, 0);
134		return (0);
135	}
136
137	if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
138		return (0);
139
140	(void) elf_flagehdr(e, ELF_C_SET, ELF_F_DIRTY);
141
142	if (ec == ELFCLASS64) {
143		eh64 = (Elf64_Ehdr *) ehdr;
144		*eh64 = *s;
145		return (1);
146	}
147
148	eh32 = (Elf32_Ehdr *) ehdr;
149
150	(void) memcpy(eh32->e_ident, s->e_ident, sizeof(eh32->e_ident));
151
152	eh32->e_type      = s->e_type;
153	eh32->e_machine   = s->e_machine;
154	eh32->e_version   = s->e_version;
155	LIBELF_COPY_U32(eh32, s, e_entry);
156	LIBELF_COPY_U32(eh32, s, e_phoff);
157	LIBELF_COPY_U32(eh32, s, e_shoff);
158	eh32->e_flags     = s->e_flags;
159	eh32->e_ehsize    = s->e_ehsize;
160	eh32->e_phentsize = s->e_phentsize;
161	eh32->e_phnum     = s->e_phnum;
162	eh32->e_shentsize = s->e_shentsize;
163	eh32->e_shnum     = s->e_shnum;
164	eh32->e_shstrndx  = s->e_shstrndx;
165
166	return (1);
167}
168