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 <libelf.h> 29260684Skaiw 30260684Skaiw#include "_libelf.h" 31260684Skaiw 32367466SdimELFTC_VCSID("$Id: libelf_xlate.c 3732 2019-04-22 11:08:38Z jkoshy $"); 33260684Skaiw 34260684Skaiw/* 35260684Skaiw * Translate to/from the file representation of ELF objects. 36260684Skaiw * 37260684Skaiw * Translation could potentially involve the following 38260684Skaiw * transformations: 39260684Skaiw * 40260684Skaiw * - an endianness conversion, 41260684Skaiw * - a change of layout, as the file representation of ELF objects 42260684Skaiw * can differ from their in-memory representation. 43260684Skaiw * - a change in representation due to a layout version change. 44260684Skaiw */ 45260684Skaiw 46260684SkaiwElf_Data * 47260684Skaiw_libelf_xlate(Elf_Data *dst, const Elf_Data *src, unsigned int encoding, 48367466Sdim int elfclass, int elfmachine, int direction) 49260684Skaiw{ 50260684Skaiw int byteswap; 51260684Skaiw size_t cnt, dsz, fsz, msz; 52260684Skaiw uintptr_t sb, se, db, de; 53367466Sdim _libelf_translator_function *xlator; 54260684Skaiw 55260684Skaiw if (encoding == ELFDATANONE) 56260684Skaiw encoding = LIBELF_PRIVATE(byteorder); 57260684Skaiw 58260684Skaiw if ((encoding != ELFDATA2LSB && encoding != ELFDATA2MSB) || 59260684Skaiw dst == NULL || src == NULL || dst == src) { 60260684Skaiw LIBELF_SET_ERROR(ARGUMENT, 0); 61260684Skaiw return (NULL); 62260684Skaiw } 63260684Skaiw 64260684Skaiw assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); 65260684Skaiw assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY); 66260684Skaiw 67260684Skaiw if (dst->d_version != src->d_version) { 68260684Skaiw LIBELF_SET_ERROR(UNIMPL, 0); 69260684Skaiw return (NULL); 70260684Skaiw } 71260684Skaiw 72260684Skaiw if (src->d_buf == NULL || dst->d_buf == NULL) { 73260684Skaiw LIBELF_SET_ERROR(DATA, 0); 74260684Skaiw return (NULL); 75260684Skaiw } 76260684Skaiw 77260684Skaiw if ((int) src->d_type < 0 || src->d_type >= ELF_T_NUM) { 78260684Skaiw LIBELF_SET_ERROR(DATA, 0); 79260684Skaiw return (NULL); 80260684Skaiw } 81260684Skaiw 82260684Skaiw if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize) 83260684Skaiw (src->d_type, (size_t) 1, src->d_version)) == 0) 84260684Skaiw return (NULL); 85260684Skaiw 86367466Sdim if ((msz = _libelf_msize(src->d_type, elfclass, src->d_version)) == 0) 87367466Sdim return (NULL); 88260684Skaiw 89260684Skaiw if (src->d_size % (direction == ELF_TOMEMORY ? fsz : msz)) { 90260684Skaiw LIBELF_SET_ERROR(DATA, 0); 91260684Skaiw return (NULL); 92260684Skaiw } 93260684Skaiw 94260684Skaiw /* 95260684Skaiw * Determine the number of objects that need to be converted, and 96260684Skaiw * the space required for the converted objects in the destination 97260684Skaiw * buffer. 98260684Skaiw */ 99260684Skaiw if (direction == ELF_TOMEMORY) { 100276371Semaste cnt = (size_t) src->d_size / fsz; 101260684Skaiw dsz = cnt * msz; 102260684Skaiw } else { 103276371Semaste cnt = (size_t) src->d_size / msz; 104260684Skaiw dsz = cnt * fsz; 105260684Skaiw } 106260684Skaiw 107260684Skaiw if (dst->d_size < dsz) { 108260684Skaiw LIBELF_SET_ERROR(DATA, 0); 109260684Skaiw return (NULL); 110260684Skaiw } 111260684Skaiw 112260684Skaiw sb = (uintptr_t) src->d_buf; 113276371Semaste se = sb + (size_t) src->d_size; 114260684Skaiw db = (uintptr_t) dst->d_buf; 115276371Semaste de = db + (size_t) dst->d_size; 116260684Skaiw 117260684Skaiw /* 118260684Skaiw * Check for overlapping buffers. Note that db == sb is 119260684Skaiw * allowed. 120260684Skaiw */ 121260684Skaiw if (db != sb && de > sb && se > db) { 122260684Skaiw LIBELF_SET_ERROR(DATA, 0); 123260684Skaiw return (NULL); 124260684Skaiw } 125260684Skaiw 126260684Skaiw if ((direction == ELF_TOMEMORY ? db : sb) % 127260684Skaiw _libelf_malign(src->d_type, elfclass)) { 128260684Skaiw LIBELF_SET_ERROR(DATA, 0); 129260684Skaiw return (NULL); 130260684Skaiw } 131260684Skaiw 132260684Skaiw dst->d_type = src->d_type; 133260684Skaiw dst->d_size = dsz; 134260684Skaiw 135260684Skaiw byteswap = encoding != LIBELF_PRIVATE(byteorder); 136260684Skaiw 137260684Skaiw if (src->d_size == 0 || 138260684Skaiw (db == sb && !byteswap && fsz == msz)) 139260684Skaiw return (dst); /* nothing more to do */ 140260684Skaiw 141367466Sdim xlator = _libelf_get_translator(src->d_type, direction, elfclass, 142367466Sdim elfmachine); 143367466Sdim if (!xlator(dst->d_buf, dsz, src->d_buf, cnt, byteswap)) { 144260684Skaiw LIBELF_SET_ERROR(DATA, 0); 145260684Skaiw return (NULL); 146260684Skaiw } 147260684Skaiw 148260684Skaiw return (dst); 149260684Skaiw} 150