1165535Sjkoshy/*-
2165535Sjkoshy * Copyright (c) 2006 Joseph Koshy
3165535Sjkoshy * All rights reserved.
4165535Sjkoshy *
5165535Sjkoshy * Redistribution and use in source and binary forms, with or without
6165535Sjkoshy * modification, are permitted provided that the following conditions
7165535Sjkoshy * are met:
8165535Sjkoshy * 1. Redistributions of source code must retain the above copyright
9165535Sjkoshy *    notice, this list of conditions and the following disclaimer.
10165535Sjkoshy * 2. Redistributions in binary form must reproduce the above copyright
11165535Sjkoshy *    notice, this list of conditions and the following disclaimer in the
12165535Sjkoshy *    documentation and/or other materials provided with the distribution.
13165535Sjkoshy *
14165535Sjkoshy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15165535Sjkoshy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16165535Sjkoshy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17165535Sjkoshy * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18165535Sjkoshy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19165535Sjkoshy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20165535Sjkoshy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21165535Sjkoshy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22165535Sjkoshy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23165535Sjkoshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24165535Sjkoshy * SUCH DAMAGE.
25165535Sjkoshy */
26165535Sjkoshy
27165535Sjkoshy#include <sys/cdefs.h>
28165535Sjkoshy__FBSDID("$FreeBSD$");
29165535Sjkoshy
30165535Sjkoshy#include <assert.h>
31165535Sjkoshy#include <libelf.h>
32165535Sjkoshy
33165535Sjkoshy#include "_libelf.h"
34165535Sjkoshy
35165535Sjkoshy/*
36165535Sjkoshy * Retrieve section #0, allocating a new section if needed.
37165535Sjkoshy */
38165535Sjkoshystatic Elf_Scn *
39165535Sjkoshy_libelf_getscn0(Elf *e)
40165535Sjkoshy{
41165535Sjkoshy	Elf_Scn *s;
42165535Sjkoshy
43165535Sjkoshy	if ((s = STAILQ_FIRST(&e->e_u.e_elf.e_scn)) != NULL)
44165535Sjkoshy		return (s);
45165535Sjkoshy
46165535Sjkoshy	return (_libelf_allocate_scn(e, (size_t) SHN_UNDEF));
47165535Sjkoshy}
48165535Sjkoshy
49165535Sjkoshyint
50165535Sjkoshy_libelf_setshnum(Elf *e, void *eh, int ec, size_t shnum)
51165535Sjkoshy{
52165535Sjkoshy	Elf_Scn *scn;
53165535Sjkoshy
54165535Sjkoshy	if (shnum >= SHN_LORESERVE) {
55165535Sjkoshy		if ((scn = _libelf_getscn0(e)) == NULL)
56165535Sjkoshy			return (0);
57165535Sjkoshy
58165535Sjkoshy		assert(scn->s_ndx == SHN_UNDEF);
59165535Sjkoshy
60165535Sjkoshy		if (ec == ELFCLASS32)
61165535Sjkoshy			scn->s_shdr.s_shdr32.sh_size = shnum;
62165535Sjkoshy		else
63165535Sjkoshy			scn->s_shdr.s_shdr64.sh_size = shnum;
64165535Sjkoshy
65165535Sjkoshy		(void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);
66165535Sjkoshy
67165535Sjkoshy		shnum = 0;
68165535Sjkoshy	}
69165535Sjkoshy
70165535Sjkoshy	if (ec == ELFCLASS32)
71165535Sjkoshy		((Elf32_Ehdr *) eh)->e_shnum = shnum;
72165535Sjkoshy	else
73165535Sjkoshy		((Elf64_Ehdr *) eh)->e_shnum = shnum;
74165535Sjkoshy
75165535Sjkoshy
76165535Sjkoshy	return (1);
77165535Sjkoshy}
78165535Sjkoshy
79165535Sjkoshyint
80165535Sjkoshy_libelf_setshstrndx(Elf *e, void *eh, int ec, size_t shstrndx)
81165535Sjkoshy{
82165535Sjkoshy	Elf_Scn *scn;
83165535Sjkoshy
84165535Sjkoshy	if (shstrndx >= SHN_LORESERVE) {
85165535Sjkoshy		if ((scn = _libelf_getscn0(e)) == NULL)
86165535Sjkoshy			return (0);
87165535Sjkoshy
88165535Sjkoshy		assert(scn->s_ndx == SHN_UNDEF);
89165535Sjkoshy
90165535Sjkoshy		if (ec == ELFCLASS32)
91165535Sjkoshy			scn->s_shdr.s_shdr32.sh_link = shstrndx;
92165535Sjkoshy		else
93165535Sjkoshy			scn->s_shdr.s_shdr64.sh_link = shstrndx;
94165535Sjkoshy
95165535Sjkoshy		(void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);
96165535Sjkoshy
97165535Sjkoshy		shstrndx = SHN_XINDEX;
98165535Sjkoshy	}
99165535Sjkoshy
100165535Sjkoshy	if (ec == ELFCLASS32)
101165535Sjkoshy		((Elf32_Ehdr *) eh)->e_shstrndx = shstrndx;
102165535Sjkoshy	else
103165535Sjkoshy		((Elf64_Ehdr *) eh)->e_shstrndx = shstrndx;
104165535Sjkoshy
105165535Sjkoshy	return (1);
106165535Sjkoshy}
107165535Sjkoshy
108165535Sjkoshyint
109165535Sjkoshy_libelf_setphnum(Elf *e, void *eh, int ec, size_t phnum)
110165535Sjkoshy{
111165535Sjkoshy	Elf_Scn *scn;
112165535Sjkoshy
113165535Sjkoshy	if (phnum >= PN_XNUM) {
114165535Sjkoshy		if ((scn = _libelf_getscn0(e)) == NULL)
115165535Sjkoshy			return (0);
116165535Sjkoshy
117165535Sjkoshy		assert(scn->s_ndx == SHN_UNDEF);
118165535Sjkoshy
119165535Sjkoshy		if (ec == ELFCLASS32)
120165535Sjkoshy			scn->s_shdr.s_shdr32.sh_info = phnum;
121165535Sjkoshy		else
122165535Sjkoshy			scn->s_shdr.s_shdr64.sh_info = phnum;
123165535Sjkoshy
124165535Sjkoshy		(void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);
125165535Sjkoshy
126165535Sjkoshy		phnum = PN_XNUM;
127165535Sjkoshy	}
128165535Sjkoshy
129165535Sjkoshy	if (ec == ELFCLASS32)
130165535Sjkoshy		((Elf32_Ehdr *) eh)->e_phnum = phnum;
131165535Sjkoshy	else
132165535Sjkoshy		((Elf64_Ehdr *) eh)->e_phnum = phnum;
133165535Sjkoshy
134165535Sjkoshy	return (1);
135165535Sjkoshy}
136165535Sjkoshy
137