1260684Skaiw/*-
2260684Skaiw * Copyright (c) 2006,2008 Joseph Koshy
3260684Skaiw * All rights reserved.
4260684Skaiw *
5260684Skaiw * Redistribution and use in source and binary forms, with or without
6260684Skaiw * modification, are permitted provided that the following conditions
7260684Skaiw * are met:
8260684Skaiw * 1. Redistributions of source code must retain the above copyright
9260684Skaiw *    notice, this list of conditions and the following disclaimer.
10260684Skaiw * 2. Redistributions in binary form must reproduce the above copyright
11260684Skaiw *    notice, this list of conditions and the following disclaimer in the
12260684Skaiw *    documentation and/or other materials provided with the distribution.
13260684Skaiw *
14260684Skaiw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15260684Skaiw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16260684Skaiw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17260684Skaiw * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18260684Skaiw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19260684Skaiw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20260684Skaiw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21260684Skaiw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22260684Skaiw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23260684Skaiw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24260684Skaiw * SUCH DAMAGE.
25260684Skaiw */
26260684Skaiw
27260684Skaiw#include <assert.h>
28260684Skaiw#include <gelf.h>
29260684Skaiw
30260684Skaiw#include "_libelf.h"
31260684Skaiw
32367466SdimELFTC_VCSID("$Id: gelf_syminfo.c 3732 2019-04-22 11:08:38Z jkoshy $");
33260684Skaiw
34260684SkaiwGElf_Syminfo *
35260684Skaiwgelf_getsyminfo(Elf_Data *ed, int ndx, GElf_Syminfo *dst)
36260684Skaiw{
37260684Skaiw	int ec;
38260684Skaiw	Elf *e;
39260684Skaiw	size_t msz;
40260684Skaiw	Elf_Scn *scn;
41260684Skaiw	uint32_t sh_type;
42260684Skaiw	struct _Libelf_Data *d;
43260684Skaiw	Elf32_Syminfo *syminfo32;
44260684Skaiw	Elf64_Syminfo *syminfo64;
45260684Skaiw
46260684Skaiw	d = (struct _Libelf_Data *) ed;
47260684Skaiw
48260684Skaiw	if (d == NULL || ndx < 0 || dst == NULL ||
49260684Skaiw	    (scn = d->d_scn) == NULL ||
50260684Skaiw	    (e = scn->s_elf) == NULL) {
51260684Skaiw		LIBELF_SET_ERROR(ARGUMENT, 0);
52260684Skaiw		return (NULL);
53260684Skaiw	}
54260684Skaiw
55260684Skaiw	ec = e->e_class;
56260684Skaiw	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
57260684Skaiw
58260684Skaiw	if (ec == ELFCLASS32)
59260684Skaiw		sh_type = scn->s_shdr.s_shdr32.sh_type;
60260684Skaiw	else
61260684Skaiw		sh_type = scn->s_shdr.s_shdr64.sh_type;
62260684Skaiw
63260684Skaiw	if (_libelf_xlate_shtype(sh_type) != ELF_T_SYMINFO) {
64260684Skaiw		LIBELF_SET_ERROR(ARGUMENT, 0);
65260684Skaiw		return (NULL);
66260684Skaiw	}
67260684Skaiw
68367466Sdim	if ((msz = _libelf_msize(ELF_T_SYMINFO, ec, e->e_version)) == 0)
69367466Sdim		return (NULL);
70260684Skaiw
71276371Semaste	assert(ndx >= 0);
72260684Skaiw
73276371Semaste	if (msz * (size_t) ndx >= d->d_data.d_size) {
74260684Skaiw		LIBELF_SET_ERROR(ARGUMENT, 0);
75260684Skaiw		return (NULL);
76260684Skaiw	}
77260684Skaiw
78260684Skaiw	if (ec == ELFCLASS32) {
79260684Skaiw
80260684Skaiw		syminfo32 = (Elf32_Syminfo *) d->d_data.d_buf + ndx;
81260684Skaiw
82260684Skaiw		dst->si_boundto = syminfo32->si_boundto;
83260684Skaiw		dst->si_flags   = syminfo32->si_flags;
84260684Skaiw
85260684Skaiw	} else {
86260684Skaiw
87260684Skaiw		syminfo64 = (Elf64_Syminfo *) d->d_data.d_buf + ndx;
88260684Skaiw
89260684Skaiw		*dst = *syminfo64;
90260684Skaiw	}
91260684Skaiw
92260684Skaiw	return (dst);
93260684Skaiw}
94260684Skaiw
95260684Skaiwint
96260684Skaiwgelf_update_syminfo(Elf_Data *ed, int ndx, GElf_Syminfo *gs)
97260684Skaiw{
98260684Skaiw	int ec;
99260684Skaiw	Elf *e;
100260684Skaiw	size_t msz;
101260684Skaiw	Elf_Scn *scn;
102260684Skaiw	uint32_t sh_type;
103260684Skaiw	struct _Libelf_Data *d;
104260684Skaiw	Elf32_Syminfo *syminfo32;
105260684Skaiw	Elf64_Syminfo *syminfo64;
106260684Skaiw
107260684Skaiw	d = (struct _Libelf_Data *) ed;
108260684Skaiw
109260684Skaiw	if (d == NULL || ndx < 0 || gs == NULL ||
110260684Skaiw	    (scn = d->d_scn) == NULL ||
111260684Skaiw	    (e = scn->s_elf) == NULL) {
112260684Skaiw		LIBELF_SET_ERROR(ARGUMENT, 0);
113260684Skaiw		return (0);
114260684Skaiw	}
115260684Skaiw
116260684Skaiw	ec = e->e_class;
117260684Skaiw	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
118260684Skaiw
119260684Skaiw	if (ec == ELFCLASS32)
120260684Skaiw		sh_type = scn->s_shdr.s_shdr32.sh_type;
121260684Skaiw	else
122260684Skaiw		sh_type = scn->s_shdr.s_shdr64.sh_type;
123260684Skaiw
124260684Skaiw	if (_libelf_xlate_shtype(sh_type) != ELF_T_SYMINFO) {
125260684Skaiw		LIBELF_SET_ERROR(ARGUMENT, 0);
126260684Skaiw		return (0);
127260684Skaiw	}
128260684Skaiw
129367466Sdim	if ((msz = _libelf_msize(ELF_T_SYMINFO, ec, e->e_version)) == 0)
130367466Sdim		return (0);
131276371Semaste
132276371Semaste	assert(ndx >= 0);
133260684Skaiw
134276371Semaste	if (msz * (size_t) ndx >= d->d_data.d_size) {
135260684Skaiw		LIBELF_SET_ERROR(ARGUMENT, 0);
136260684Skaiw		return (0);
137260684Skaiw	}
138260684Skaiw
139260684Skaiw	if (ec == ELFCLASS32) {
140260684Skaiw		syminfo32 = (Elf32_Syminfo *) d->d_data.d_buf + ndx;
141260684Skaiw
142260684Skaiw		syminfo32->si_boundto  = gs->si_boundto;
143260684Skaiw		syminfo32->si_flags  = gs->si_flags;
144260684Skaiw
145260684Skaiw	} else {
146260684Skaiw		syminfo64 = (Elf64_Syminfo *) d->d_data.d_buf + ndx;
147260684Skaiw
148260684Skaiw		*syminfo64 = *gs;
149260684Skaiw	}
150260684Skaiw
151260684Skaiw	return (1);
152260684Skaiw}
153