1164190Sjkoshy/*-
2164190Sjkoshy * Copyright (c) 2006 Joseph Koshy
3164190Sjkoshy * All rights reserved.
4164190Sjkoshy *
5164190Sjkoshy * Redistribution and use in source and binary forms, with or without
6164190Sjkoshy * modification, are permitted provided that the following conditions
7164190Sjkoshy * are met:
8164190Sjkoshy * 1. Redistributions of source code must retain the above copyright
9164190Sjkoshy *    notice, this list of conditions and the following disclaimer.
10164190Sjkoshy * 2. Redistributions in binary form must reproduce the above copyright
11164190Sjkoshy *    notice, this list of conditions and the following disclaimer in the
12164190Sjkoshy *    documentation and/or other materials provided with the distribution.
13164190Sjkoshy *
14164190Sjkoshy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15164190Sjkoshy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16164190Sjkoshy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17164190Sjkoshy * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18164190Sjkoshy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19164190Sjkoshy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20164190Sjkoshy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21164190Sjkoshy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22164190Sjkoshy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23164190Sjkoshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24164190Sjkoshy * SUCH DAMAGE.
25164190Sjkoshy */
26164190Sjkoshy
27164190Sjkoshy#include <sys/cdefs.h>
28164190Sjkoshy__FBSDID("$FreeBSD: releng/10.2/lib/libelf/gelf_phdr.c 210325 2010-07-21 08:58:52Z kaiw $");
29164190Sjkoshy
30164190Sjkoshy#include <sys/limits.h>
31164190Sjkoshy
32164190Sjkoshy#include <gelf.h>
33164190Sjkoshy#include <libelf.h>
34164190Sjkoshy
35164190Sjkoshy#include "_libelf.h"
36164190Sjkoshy
37164190SjkoshyElf32_Phdr *
38164190Sjkoshyelf32_getphdr(Elf *e)
39164190Sjkoshy{
40164190Sjkoshy	return (_libelf_getphdr(e, ELFCLASS32));
41164190Sjkoshy}
42164190Sjkoshy
43164190SjkoshyElf64_Phdr *
44164190Sjkoshyelf64_getphdr(Elf *e)
45164190Sjkoshy{
46164190Sjkoshy	return (_libelf_getphdr(e, ELFCLASS64));
47164190Sjkoshy}
48164190Sjkoshy
49164190SjkoshyGElf_Phdr *
50164190Sjkoshygelf_getphdr(Elf *e, int index, GElf_Phdr *d)
51164190Sjkoshy{
52164190Sjkoshy	int ec;
53164190Sjkoshy	Elf32_Ehdr *eh32;
54164190Sjkoshy	Elf64_Ehdr *eh64;
55164190Sjkoshy	Elf32_Phdr *ep32;
56164190Sjkoshy	Elf64_Phdr *ep64;
57164190Sjkoshy
58164190Sjkoshy	if (d == NULL || e == NULL ||
59164190Sjkoshy	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) ||
60164190Sjkoshy	    (e->e_kind != ELF_K_ELF) || index < 0) {
61164190Sjkoshy		LIBELF_SET_ERROR(ARGUMENT, 0);
62164190Sjkoshy		return (NULL);
63164190Sjkoshy	}
64164190Sjkoshy
65164190Sjkoshy	if (ec == ELFCLASS32) {
66164190Sjkoshy		if ((eh32 = _libelf_ehdr(e, ELFCLASS32, 0)) == NULL ||
67164190Sjkoshy		    ((ep32 = _libelf_getphdr(e, ELFCLASS32)) == NULL))
68164190Sjkoshy			return (NULL);
69164190Sjkoshy
70164190Sjkoshy		if (index >= eh32->e_phnum) {
71164190Sjkoshy			LIBELF_SET_ERROR(ARGUMENT, 0);
72164190Sjkoshy			return (NULL);
73164190Sjkoshy		}
74164190Sjkoshy
75164190Sjkoshy		ep32 += index;
76164190Sjkoshy
77164190Sjkoshy		d->p_type   = ep32->p_type;
78164190Sjkoshy		d->p_offset = ep32->p_offset;
79164190Sjkoshy		d->p_vaddr  = (Elf64_Addr) ep32->p_vaddr;
80164190Sjkoshy		d->p_paddr  = (Elf64_Addr) ep32->p_paddr;
81164190Sjkoshy		d->p_filesz = (Elf64_Xword) ep32->p_filesz;
82164190Sjkoshy		d->p_memsz  = (Elf64_Xword) ep32->p_memsz;
83164190Sjkoshy		d->p_flags  = ep32->p_flags;
84164190Sjkoshy		d->p_align  = (Elf64_Xword) ep32->p_align;
85164190Sjkoshy
86164190Sjkoshy	} else {
87164190Sjkoshy		if ((eh64 = _libelf_ehdr(e, ELFCLASS64, 0)) == NULL ||
88164190Sjkoshy		    (ep64 = _libelf_getphdr(e, ELFCLASS64)) == NULL)
89164190Sjkoshy			return (NULL);
90164190Sjkoshy
91164190Sjkoshy		if (index >= eh64->e_phnum) {
92164190Sjkoshy			LIBELF_SET_ERROR(ARGUMENT, 0);
93164190Sjkoshy			return (NULL);
94164190Sjkoshy		}
95164190Sjkoshy
96164190Sjkoshy		ep64 += index;
97164190Sjkoshy
98164190Sjkoshy		*d = *ep64;
99164190Sjkoshy	}
100164190Sjkoshy
101164190Sjkoshy	return (d);
102164190Sjkoshy}
103164190Sjkoshy
104164190SjkoshyElf32_Phdr *
105164190Sjkoshyelf32_newphdr(Elf *e, size_t count)
106164190Sjkoshy{
107164190Sjkoshy	return (_libelf_newphdr(e, ELFCLASS32, count));
108164190Sjkoshy}
109164190Sjkoshy
110164190SjkoshyElf64_Phdr *
111164190Sjkoshyelf64_newphdr(Elf *e, size_t count)
112164190Sjkoshy{
113164190Sjkoshy	return (_libelf_newphdr(e, ELFCLASS64, count));
114164190Sjkoshy}
115164190Sjkoshy
116164190Sjkoshyvoid *
117164190Sjkoshygelf_newphdr(Elf *e, size_t count)
118164190Sjkoshy{
119164190Sjkoshy	if (e == NULL) {
120164190Sjkoshy		LIBELF_SET_ERROR(ARGUMENT, 0);
121164190Sjkoshy		return (NULL);
122164190Sjkoshy	}
123164190Sjkoshy	return (_libelf_newphdr(e, e->e_class, count));
124164190Sjkoshy}
125164190Sjkoshy
126164190Sjkoshyint
127164190Sjkoshygelf_update_phdr(Elf *e, int ndx, GElf_Phdr *s)
128164190Sjkoshy{
129164190Sjkoshy	int ec, phnum;
130164190Sjkoshy	void *ehdr;
131164190Sjkoshy	Elf32_Phdr *ph32;
132164190Sjkoshy	Elf64_Phdr *ph64;
133164190Sjkoshy
134164190Sjkoshy	if (s == NULL || e == NULL || e->e_kind != ELF_K_ELF ||
135164190Sjkoshy	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
136164190Sjkoshy		LIBELF_SET_ERROR(ARGUMENT, 0);
137164190Sjkoshy		return (0);
138164190Sjkoshy	}
139164190Sjkoshy
140164190Sjkoshy	if (e->e_cmd == ELF_C_READ) {
141164190Sjkoshy		LIBELF_SET_ERROR(MODE, 0);
142164190Sjkoshy		return (0);
143164190Sjkoshy	}
144164190Sjkoshy
145164190Sjkoshy	if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
146164190Sjkoshy		return (0);
147164190Sjkoshy
148164190Sjkoshy	if (ec == ELFCLASS32)
149164190Sjkoshy		phnum = ((Elf32_Ehdr *) ehdr)->e_phnum;
150164190Sjkoshy	else
151164190Sjkoshy		phnum = ((Elf64_Ehdr *) ehdr)->e_phnum;
152164190Sjkoshy
153164190Sjkoshy	if (ndx < 0 || ndx > phnum) {
154164190Sjkoshy		LIBELF_SET_ERROR(ARGUMENT, 0);
155164190Sjkoshy		return (0);
156164190Sjkoshy	}
157164190Sjkoshy
158210325Skaiw	(void) elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY);
159210325Skaiw
160164190Sjkoshy	if (ec == ELFCLASS64) {
161164190Sjkoshy		ph64 = e->e_u.e_elf.e_phdr.e_phdr64 + ndx;
162164190Sjkoshy		*ph64 = *s;
163164190Sjkoshy		return (1);
164164190Sjkoshy	}
165164190Sjkoshy
166164190Sjkoshy	ph32 = e->e_u.e_elf.e_phdr.e_phdr32 + ndx;
167164190Sjkoshy
168164190Sjkoshy	ph32->p_type     =  s->p_type;
169164190Sjkoshy	ph32->p_flags    =  s->p_flags;
170164190Sjkoshy	LIBELF_COPY_U32(ph32, s, p_offset);
171164190Sjkoshy	LIBELF_COPY_U32(ph32, s, p_vaddr);
172164190Sjkoshy	LIBELF_COPY_U32(ph32, s, p_paddr);
173164190Sjkoshy	LIBELF_COPY_U32(ph32, s, p_filesz);
174164190Sjkoshy	LIBELF_COPY_U32(ph32, s, p_memsz);
175164190Sjkoshy	LIBELF_COPY_U32(ph32, s, p_align);
176164190Sjkoshy
177164190Sjkoshy	return (1);
178164190Sjkoshy}
179