1179337Syongari/*	$NetBSD: gelf_move.c,v 1.5 2024/03/03 17:37:34 christos Exp $	*/
2179337Syongari
3179337Syongari/*-
4179337Syongari * Copyright (c) 2006,2008 Joseph Koshy
5179337Syongari * All rights reserved.
6179337Syongari *
7179337Syongari * Redistribution and use in source and binary forms, with or without
8179337Syongari * modification, are permitted provided that the following conditions
9179337Syongari * are met:
10179337Syongari * 1. Redistributions of source code must retain the above copyright
11179337Syongari *    notice, this list of conditions and the following disclaimer.
12179337Syongari * 2. Redistributions in binary form must reproduce the above copyright
13179337Syongari *    notice, this list of conditions and the following disclaimer in the
14179337Syongari *    documentation and/or other materials provided with the distribution.
15179337Syongari *
16179337Syongari * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17179337Syongari * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18179337Syongari * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19179337Syongari * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20179337Syongari * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21179337Syongari * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22179337Syongari * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23179337Syongari * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24179337Syongari * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25179337Syongari * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26179337Syongari * SUCH DAMAGE.
27179337Syongari */
28179337Syongari
29179337Syongari#if HAVE_NBTOOL_CONFIG_H
30179337Syongari# include "nbtool_config.h"
31179337Syongari#endif
32179337Syongari
33179337Syongari#include <sys/cdefs.h>
34179337Syongari
35179337Syongari#include <assert.h>
36179337Syongari#include <gelf.h>
37179337Syongari#include <limits.h>
38179337Syongari#include <stdint.h>
39179337Syongari
40179337Syongari#include "_libelf.h"
41179337Syongari
42182888Syongari__RCSID("$NetBSD: gelf_move.c,v 1.5 2024/03/03 17:37:34 christos Exp $");
43182888SyongariELFTC_VCSID("Id: gelf_move.c 3977 2022-05-01 06:45:34Z jkoshy");
44179337Syongari
45179337SyongariGElf_Move *
46179337Syongarigelf_getmove(Elf_Data *ed, int ndx, GElf_Move *dst)
47179337Syongari{
48179337Syongari	int ec;
49182888Syongari	Elf *e;
50179337Syongari	size_t msz;
51183814Syongari	Elf_Scn *scn;
52183814Syongari	uint32_t sh_type;
53179337Syongari	Elf32_Move *move32;
54179337Syongari	Elf64_Move *move64;
55179337Syongari	struct _Libelf_Data *d;
56179337Syongari
57179337Syongari	d = (struct _Libelf_Data *) ed;
58179337Syongari
59179337Syongari	if (d == NULL || ndx < 0 || dst == NULL ||
60179337Syongari	    (scn = d->d_scn) == NULL ||
61179337Syongari	    (e = scn->s_elf) == NULL) {
62179337Syongari		LIBELF_SET_ERROR(ARGUMENT, 0);
63179337Syongari		return (NULL);
64179337Syongari	}
65179337Syongari
66179337Syongari	ec = e->e_class;
67179337Syongari	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
68179337Syongari
69179337Syongari	if (ec == ELFCLASS32)
70179337Syongari		sh_type = scn->s_shdr.s_shdr32.sh_type;
71179337Syongari	else
72179337Syongari		sh_type = scn->s_shdr.s_shdr64.sh_type;
73179337Syongari
74179337Syongari	if (_libelf_xlate_shtype(sh_type) != ELF_T_MOVE) {
75179337Syongari		LIBELF_SET_ERROR(ARGUMENT, 0);
76179337Syongari		return (NULL);
77179337Syongari	}
78179337Syongari
79179337Syongari	if ((msz = _libelf_msize(ELF_T_MOVE, ec, e->e_version)) == 0)
80179337Syongari		return (NULL);
81179337Syongari
82179337Syongari	assert(ndx >= 0);
83179337Syongari
84179337Syongari	if (msz * (size_t) ndx >= d->d_data.d_size) {
85179337Syongari		LIBELF_SET_ERROR(ARGUMENT, 0);
86179337Syongari		return (NULL);
87179337Syongari	}
88179337Syongari
89179337Syongari	if (ec == ELFCLASS32) {
90179337Syongari
91179337Syongari		move32 = (Elf32_Move *) d->d_data.d_buf + ndx;
92179337Syongari
93179337Syongari		dst->m_value   = move32->m_value;
94179337Syongari		dst->m_info    = (Elf64_Xword) move32->m_info;
95179337Syongari		dst->m_poffset = (Elf64_Xword) move32->m_poffset;
96179337Syongari		dst->m_repeat  = move32->m_repeat;
97179337Syongari		dst->m_stride = move32->m_stride;
98179337Syongari	} else {
99179337Syongari
100179337Syongari		move64 = (Elf64_Move *) d->d_data.d_buf + ndx;
101179337Syongari
102179337Syongari		*dst = *move64;
103179337Syongari	}
104179337Syongari
105179337Syongari	return (dst);
106179337Syongari}
107179337Syongari
108179337Syongariint
109179337Syongarigelf_update_move(Elf_Data *ed, int ndx, GElf_Move *gm)
110179337Syongari{
111179337Syongari	int ec;
112179337Syongari	Elf *e;
113179337Syongari	size_t msz;
114179337Syongari	Elf_Scn *scn;
115179337Syongari	uint32_t sh_type;
116179337Syongari	Elf32_Move *move32;
117179337Syongari	Elf64_Move *move64;
118179337Syongari	struct _Libelf_Data *d;
119179337Syongari
120179337Syongari	d = (struct _Libelf_Data *) ed;
121179337Syongari
122179337Syongari	if (d == NULL || ndx < 0 || gm == NULL ||
123179337Syongari	    (scn = d->d_scn) == NULL ||
124179337Syongari	    (e = scn->s_elf) == NULL) {
125179337Syongari		LIBELF_SET_ERROR(ARGUMENT, 0);
126179337Syongari		return (0);
127179337Syongari	}
128179337Syongari
129179337Syongari	ec = e->e_class;
130179337Syongari	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
131179337Syongari
132179337Syongari	if (ec == ELFCLASS32)
133179337Syongari		sh_type = scn->s_shdr.s_shdr32.sh_type;
134179337Syongari	else
135179337Syongari		sh_type = scn->s_shdr.s_shdr64.sh_type;
136179337Syongari
137179337Syongari	if (_libelf_xlate_shtype(sh_type) != ELF_T_MOVE) {
138179337Syongari		LIBELF_SET_ERROR(ARGUMENT, 0);
139179337Syongari		return (0);
140179337Syongari	}
141179337Syongari
142179337Syongari	if ((msz = _libelf_msize(ELF_T_MOVE, ec, e->e_version)) == 0)
143179337Syongari		return (0);
144179337Syongari
145179337Syongari	assert(ndx >= 0);
146179337Syongari
147179337Syongari	if (msz * (size_t) ndx >= d->d_data.d_size) {
148179337Syongari		LIBELF_SET_ERROR(ARGUMENT, 0);
149179337Syongari		return (0);
150179337Syongari	}
151179337Syongari
152179337Syongari	if (ec == ELFCLASS32) {
153179337Syongari		move32 = (Elf32_Move *) d->d_data.d_buf + ndx;
154179337Syongari
155179337Syongari		move32->m_value  = gm->m_value;
156179337Syongari		LIBELF_COPY_U32(move32, gm, m_info);
157179337Syongari		LIBELF_COPY_U32(move32, gm, m_poffset);
158179337Syongari		move32->m_repeat  = gm->m_repeat;
159179337Syongari		move32->m_stride = gm->m_stride;
160179337Syongari
161179337Syongari	} else {
162179337Syongari		move64 = (Elf64_Move *) d->d_data.d_buf + ndx;
163179337Syongari
164179337Syongari		*move64 = *gm;
165179337Syongari	}
166179337Syongari
167179337Syongari	return (1);
168179337Syongari}
169179337Syongari