11558Srgrimes/*-
21558Srgrimes * Copyright (c) 2006 Joseph Koshy
31558Srgrimes * All rights reserved.
41558Srgrimes *
51558Srgrimes * Redistribution and use in source and binary forms, with or without
61558Srgrimes * modification, are permitted provided that the following conditions
71558Srgrimes * are met:
81558Srgrimes * 1. Redistributions of source code must retain the above copyright
91558Srgrimes *    notice, this list of conditions and the following disclaimer.
101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111558Srgrimes *    notice, this list of conditions and the following disclaimer in the
121558Srgrimes *    documentation and/or other materials provided with the distribution.
131558Srgrimes *
141558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
151558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
161558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
171558Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
181558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
191558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
201558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
211558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
221558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
231558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
241558Srgrimes * SUCH DAMAGE.
251558Srgrimes */
261558Srgrimes
271558Srgrimes#include <sys/cdefs.h>
281558Srgrimes__FBSDID("$FreeBSD$");
291558Srgrimes
301558Srgrimes#include <sys/limits.h>
3136997Scharnier
321558Srgrimes#include <assert.h>
3336997Scharnier#include <gelf.h>
3436997Scharnier#include <osreldate.h>
3550476Speter
361558Srgrimes#include "_libelf.h"
371558Srgrimes
381558Srgrimes#if	__FreeBSD_version >= 700025
3971787Sphk
401558SrgrimesGElf_Move *
411558Srgrimesgelf_getmove(Elf_Data *d, int ndx, GElf_Move *dst)
421558Srgrimes{
431558Srgrimes	int ec;
441558Srgrimes	Elf *e;
451558Srgrimes	Elf_Scn *scn;
461558Srgrimes	Elf32_Move *move32;
471558Srgrimes	Elf64_Move *move64;
48103949Smike	size_t msz;
491558Srgrimes	uint32_t sh_type;
501558Srgrimes
511558Srgrimes	if (d == NULL || ndx < 0 || dst == NULL ||
5299562Siedowse	    (scn = d->d_scn) == NULL ||
531558Srgrimes	    (e = scn->s_elf) == NULL) {
541558Srgrimes		LIBELF_SET_ERROR(ARGUMENT, 0);
551558Srgrimes		return (NULL);
5671787Sphk	}
5771787Sphk
5871787Sphk	ec = e->e_class;
5971787Sphk	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
6071787Sphk
611558Srgrimes	if (ec == ELFCLASS32)
621558Srgrimes		sh_type = scn->s_shdr.s_shdr32.sh_type;
631558Srgrimes	else
6492837Simp		sh_type = scn->s_shdr.s_shdr64.sh_type;
6592837Simp
6692837Simp	if (_libelf_xlate_shtype(sh_type) != ELF_T_MOVE) {
6792837Simp		LIBELF_SET_ERROR(ARGUMENT, 0);
681558Srgrimes		return (NULL);
691558Srgrimes	}
7092837Simp
711558Srgrimes	msz = _libelf_msize(ELF_T_MOVE, ec, e->e_version);
721558Srgrimes
731558Srgrimes	assert(msz > 0);
741558Srgrimes
751558Srgrimes	if (msz * ndx >= d->d_size) {
7674873Sobrien		LIBELF_SET_ERROR(ARGUMENT, 0);
771558Srgrimes		return (NULL);
7874872Sobrien	}
791558Srgrimes
801558Srgrimes	if (ec == ELFCLASS32) {
811558Srgrimes
821558Srgrimes		move32 = (Elf32_Move *) d->d_buf + ndx;
831558Srgrimes
841558Srgrimes		dst->m_value   = move32->m_value;
8574873Sobrien		dst->m_info    = (Elf64_Xword) move32->m_info;
861558Srgrimes		dst->m_poffset = (Elf64_Xword) move32->m_poffset;
8774872Sobrien		dst->m_repeat  = move32->m_repeat;
881558Srgrimes		dst->m_stride = move32->m_stride;
891558Srgrimes	} else {
901558Srgrimes
911558Srgrimes		move64 = (Elf64_Move *) d->d_buf + ndx;
921558Srgrimes
931558Srgrimes		*dst = *move64;
941558Srgrimes	}
951558Srgrimes
961558Srgrimes	return (dst);
971558Srgrimes}
981558Srgrimes
991558Srgrimesint
1001558Srgrimesgelf_update_move(Elf_Data *d, int ndx, GElf_Move *gm)
1011558Srgrimes{
10292837Simp	int ec;
1031558Srgrimes	Elf *e;
10486473Siedowse	Elf_Scn *scn;
10586473Siedowse	Elf32_Move *move32;
1061558Srgrimes	Elf64_Move *move64;
1071558Srgrimes	size_t msz;
1081558Srgrimes	uint32_t sh_type;
1091558Srgrimes
1101558Srgrimes	if (d == NULL || ndx < 0 || gm == NULL ||
1111558Srgrimes	    (scn = d->d_scn) == NULL ||
11271787Sphk	    (e = scn->s_elf) == NULL) {
1131558Srgrimes		LIBELF_SET_ERROR(ARGUMENT, 0);
1141558Srgrimes		return (0);
1151558Srgrimes	}
1161558Srgrimes
1171558Srgrimes	ec = e->e_class;
1181558Srgrimes	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
1191558Srgrimes
1201558Srgrimes	if (ec == ELFCLASS32)
12171787Sphk		sh_type = scn->s_shdr.s_shdr32.sh_type;
12271787Sphk	else
1231558Srgrimes		sh_type = scn->s_shdr.s_shdr64.sh_type;
1241558Srgrimes
1251558Srgrimes	if (_libelf_xlate_shtype(sh_type) != ELF_T_MOVE) {
1261558Srgrimes		LIBELF_SET_ERROR(ARGUMENT, 0);
12792837Simp		return (0);
1281558Srgrimes	}
12986473Siedowse
13086473Siedowse	msz = _libelf_msize(ELF_T_MOVE, ec, e->e_version);
1311558Srgrimes	assert(msz > 0);
1321558Srgrimes
1331558Srgrimes	if (msz * ndx >= d->d_size) {
1341558Srgrimes		LIBELF_SET_ERROR(ARGUMENT, 0);
135179275Smckusick		return (0);
1361558Srgrimes	}
1371558Srgrimes
1381558Srgrimes	if (ec == ELFCLASS32) {
139179275Smckusick		move32 = (Elf32_Move *) d->d_buf + ndx;
1401558Srgrimes
1411558Srgrimes		move32->m_value  = gm->m_value;
1421558Srgrimes		LIBELF_COPY_U32(move32, gm, m_info);
1431558Srgrimes		LIBELF_COPY_U32(move32, gm, m_poffset);
1441558Srgrimes		move32->m_repeat  = gm->m_repeat;
1451558Srgrimes		move32->m_stride = gm->m_stride;
1461558Srgrimes
1471558Srgrimes	} else {
1481558Srgrimes		move64 = (Elf64_Move *) d->d_buf + ndx;
1491558Srgrimes
1501558Srgrimes		*move64 = *gm;
15198542Smckusick	}
1521558Srgrimes
15398542Smckusick	return (1);
1541558Srgrimes}
1551558Srgrimes
1561558Srgrimes#endif	/* __FreeBSD_version >= 700025 */
1571558Srgrimes