1*2de3b87aSKai Wang /*- 2*2de3b87aSKai Wang * Copyright (c) 2006,2008 Joseph Koshy 3*2de3b87aSKai Wang * All rights reserved. 4*2de3b87aSKai Wang * 5*2de3b87aSKai Wang * Redistribution and use in source and binary forms, with or without 6*2de3b87aSKai Wang * modification, are permitted provided that the following conditions 7*2de3b87aSKai Wang * are met: 8*2de3b87aSKai Wang * 1. Redistributions of source code must retain the above copyright 9*2de3b87aSKai Wang * notice, this list of conditions and the following disclaimer. 10*2de3b87aSKai Wang * 2. Redistributions in binary form must reproduce the above copyright 11*2de3b87aSKai Wang * notice, this list of conditions and the following disclaimer in the 12*2de3b87aSKai Wang * documentation and/or other materials provided with the distribution. 13*2de3b87aSKai Wang * 14*2de3b87aSKai Wang * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*2de3b87aSKai Wang * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*2de3b87aSKai Wang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*2de3b87aSKai Wang * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*2de3b87aSKai Wang * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*2de3b87aSKai Wang * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*2de3b87aSKai Wang * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*2de3b87aSKai Wang * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*2de3b87aSKai Wang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*2de3b87aSKai Wang * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*2de3b87aSKai Wang * SUCH DAMAGE. 25*2de3b87aSKai Wang */ 26*2de3b87aSKai Wang 27*2de3b87aSKai Wang #include <sys/cdefs.h> 28*2de3b87aSKai Wang 29*2de3b87aSKai Wang #include <assert.h> 30*2de3b87aSKai Wang #include <libelf.h> 31*2de3b87aSKai Wang 32*2de3b87aSKai Wang #include "_libelf.h" 33*2de3b87aSKai Wang 34*2de3b87aSKai Wang ELFTC_VCSID("$Id: libelf_xlate.c 2225 2011-11-26 18:55:54Z jkoshy $"); 35*2de3b87aSKai Wang 36*2de3b87aSKai Wang /* 37*2de3b87aSKai Wang * Translate to/from the file representation of ELF objects. 38*2de3b87aSKai Wang * 39*2de3b87aSKai Wang * Translation could potentially involve the following 40*2de3b87aSKai Wang * transformations: 41*2de3b87aSKai Wang * 42*2de3b87aSKai Wang * - an endianness conversion, 43*2de3b87aSKai Wang * - a change of layout, as the file representation of ELF objects 44*2de3b87aSKai Wang * can differ from their in-memory representation. 45*2de3b87aSKai Wang * - a change in representation due to a layout version change. 46*2de3b87aSKai Wang */ 47*2de3b87aSKai Wang 48*2de3b87aSKai Wang Elf_Data * 49*2de3b87aSKai Wang _libelf_xlate(Elf_Data *dst, const Elf_Data *src, unsigned int encoding, 50*2de3b87aSKai Wang int elfclass, int direction) 51*2de3b87aSKai Wang { 52*2de3b87aSKai Wang int byteswap; 53*2de3b87aSKai Wang size_t cnt, dsz, fsz, msz; 54*2de3b87aSKai Wang uintptr_t sb, se, db, de; 55*2de3b87aSKai Wang 56*2de3b87aSKai Wang if (encoding == ELFDATANONE) 57*2de3b87aSKai Wang encoding = LIBELF_PRIVATE(byteorder); 58*2de3b87aSKai Wang 59*2de3b87aSKai Wang if ((encoding != ELFDATA2LSB && encoding != ELFDATA2MSB) || 60*2de3b87aSKai Wang dst == NULL || src == NULL || dst == src) { 61*2de3b87aSKai Wang LIBELF_SET_ERROR(ARGUMENT, 0); 62*2de3b87aSKai Wang return (NULL); 63*2de3b87aSKai Wang } 64*2de3b87aSKai Wang 65*2de3b87aSKai Wang assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); 66*2de3b87aSKai Wang assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY); 67*2de3b87aSKai Wang 68*2de3b87aSKai Wang if (dst->d_version != src->d_version) { 69*2de3b87aSKai Wang LIBELF_SET_ERROR(UNIMPL, 0); 70*2de3b87aSKai Wang return (NULL); 71*2de3b87aSKai Wang } 72*2de3b87aSKai Wang 73*2de3b87aSKai Wang if (src->d_buf == NULL || dst->d_buf == NULL) { 74*2de3b87aSKai Wang LIBELF_SET_ERROR(DATA, 0); 75*2de3b87aSKai Wang return (NULL); 76*2de3b87aSKai Wang } 77*2de3b87aSKai Wang 78*2de3b87aSKai Wang if ((int) src->d_type < 0 || src->d_type >= ELF_T_NUM) { 79*2de3b87aSKai Wang LIBELF_SET_ERROR(DATA, 0); 80*2de3b87aSKai Wang return (NULL); 81*2de3b87aSKai Wang } 82*2de3b87aSKai Wang 83*2de3b87aSKai Wang if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize) 84*2de3b87aSKai Wang (src->d_type, (size_t) 1, src->d_version)) == 0) 85*2de3b87aSKai Wang return (NULL); 86*2de3b87aSKai Wang 87*2de3b87aSKai Wang msz = _libelf_msize(src->d_type, elfclass, src->d_version); 88*2de3b87aSKai Wang 89*2de3b87aSKai Wang assert(msz > 0); 90*2de3b87aSKai Wang 91*2de3b87aSKai Wang if (src->d_size % (direction == ELF_TOMEMORY ? fsz : msz)) { 92*2de3b87aSKai Wang LIBELF_SET_ERROR(DATA, 0); 93*2de3b87aSKai Wang return (NULL); 94*2de3b87aSKai Wang } 95*2de3b87aSKai Wang 96*2de3b87aSKai Wang /* 97*2de3b87aSKai Wang * Determine the number of objects that need to be converted, and 98*2de3b87aSKai Wang * the space required for the converted objects in the destination 99*2de3b87aSKai Wang * buffer. 100*2de3b87aSKai Wang */ 101*2de3b87aSKai Wang if (direction == ELF_TOMEMORY) { 102*2de3b87aSKai Wang cnt = src->d_size / fsz; 103*2de3b87aSKai Wang dsz = cnt * msz; 104*2de3b87aSKai Wang } else { 105*2de3b87aSKai Wang cnt = src->d_size / msz; 106*2de3b87aSKai Wang dsz = cnt * fsz; 107*2de3b87aSKai Wang } 108*2de3b87aSKai Wang 109*2de3b87aSKai Wang if (dst->d_size < dsz) { 110*2de3b87aSKai Wang LIBELF_SET_ERROR(DATA, 0); 111*2de3b87aSKai Wang return (NULL); 112*2de3b87aSKai Wang } 113*2de3b87aSKai Wang 114*2de3b87aSKai Wang sb = (uintptr_t) src->d_buf; 115*2de3b87aSKai Wang se = sb + src->d_size; 116*2de3b87aSKai Wang db = (uintptr_t) dst->d_buf; 117*2de3b87aSKai Wang de = db + dst->d_size; 118*2de3b87aSKai Wang 119*2de3b87aSKai Wang /* 120*2de3b87aSKai Wang * Check for overlapping buffers. Note that db == sb is 121*2de3b87aSKai Wang * allowed. 122*2de3b87aSKai Wang */ 123*2de3b87aSKai Wang if (db != sb && de > sb && se > db) { 124*2de3b87aSKai Wang LIBELF_SET_ERROR(DATA, 0); 125*2de3b87aSKai Wang return (NULL); 126*2de3b87aSKai Wang } 127*2de3b87aSKai Wang 128*2de3b87aSKai Wang if ((direction == ELF_TOMEMORY ? db : sb) % 129*2de3b87aSKai Wang _libelf_malign(src->d_type, elfclass)) { 130*2de3b87aSKai Wang LIBELF_SET_ERROR(DATA, 0); 131*2de3b87aSKai Wang return (NULL); 132*2de3b87aSKai Wang } 133*2de3b87aSKai Wang 134*2de3b87aSKai Wang dst->d_type = src->d_type; 135*2de3b87aSKai Wang dst->d_size = dsz; 136*2de3b87aSKai Wang 137*2de3b87aSKai Wang byteswap = encoding != LIBELF_PRIVATE(byteorder); 138*2de3b87aSKai Wang 139*2de3b87aSKai Wang if (src->d_size == 0 || 140*2de3b87aSKai Wang (db == sb && !byteswap && fsz == msz)) 141*2de3b87aSKai Wang return (dst); /* nothing more to do */ 142*2de3b87aSKai Wang 143*2de3b87aSKai Wang if (!(_libelf_get_translator(src->d_type, direction, elfclass)) 144*2de3b87aSKai Wang (dst->d_buf, dsz, src->d_buf, cnt, byteswap)) { 145*2de3b87aSKai Wang LIBELF_SET_ERROR(DATA, 0); 146*2de3b87aSKai Wang return (NULL); 147*2de3b87aSKai Wang } 148*2de3b87aSKai Wang 149*2de3b87aSKai Wang return (dst); 150*2de3b87aSKai Wang } 151