libelf_xlate.c revision 4484
13804SN/A/*- 212776Snikos.nikoleris@arm.com * Copyright (c) 2006 Joseph Koshy 39235Sandreas.hansson@arm.com * All rights reserved. 49235Sandreas.hansson@arm.com * 59235Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 69235Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions 79235Sandreas.hansson@arm.com * are met: 89235Sandreas.hansson@arm.com * 1. Redistributions of source code must retain the above copyright 99235Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer. 109235Sandreas.hansson@arm.com * 2. Redistributions in binary form must reproduce the above copyright 119235Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 129235Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution. 139235Sandreas.hansson@arm.com * 143804SN/A * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 153804SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 163804SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 173804SN/A * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 183804SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 193804SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 203804SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 213804SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 223804SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 233804SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 243804SN/A * SUCH DAMAGE. 253804SN/A */ 263804SN/A 273804SN/A#include <assert.h> 283804SN/A 293804SN/A#include "libelf.h" 303804SN/A#include "_libelf.h" 313804SN/A 323804SN/A/* 333804SN/A * Translate to/from the file representation of ELF objects. 343804SN/A * 353804SN/A * Translation could potentially involve the following 363804SN/A * transformations: 373804SN/A * 383804SN/A * - an endianness conversion, 393804SN/A * - a change of layout, as the file representation of ELF objects 403804SN/A * can differ from their in-memory representation. 419235Sandreas.hansson@arm.com * - a change in representation due to a layout version change. 423804SN/A */ 433804SN/A 449235Sandreas.hansson@arm.comElf_Data * 459235Sandreas.hansson@arm.com_libelf_xlate(Elf_Data *dst, const Elf_Data *src, unsigned int encoding, 463804SN/A int elfclass, int direction) 478229SN/A{ 488902SN/A size_t cnt, dsz, fsz, msz; 498229SN/A uintptr_t sb, se, db, de; 509235Sandreas.hansson@arm.com 513804SN/A if (encoding == ELFDATANONE) 528918SN/A encoding = LIBELF_PRIVATE(byteorder); 539235Sandreas.hansson@arm.com 549235Sandreas.hansson@arm.com if ((encoding != ELFDATA2LSB && encoding != ELFDATA2MSB) || 559235Sandreas.hansson@arm.com dst == NULL || src == NULL || dst == src) { 568918SN/A LIBELF_SET_ERROR(ARGUMENT, 0); 5712777Sgabeblack@google.com return (NULL); 589235Sandreas.hansson@arm.com } 593804SN/A 603804SN/A assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); 619235Sandreas.hansson@arm.com assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY); 623804SN/A 633804SN/A if (dst->d_version != src->d_version) { 643804SN/A LIBELF_SET_ERROR(UNIMPL, 0); 658918SN/A return (NULL); 663804SN/A } 6712776Snikos.nikoleris@arm.com 6812776Snikos.nikoleris@arm.com if (src->d_buf == NULL || dst->d_buf == NULL || 6912776Snikos.nikoleris@arm.com src->d_size == 0) { 7012776Snikos.nikoleris@arm.com LIBELF_SET_ERROR(DATA, 0); 7112776Snikos.nikoleris@arm.com return (NULL); 7212776Snikos.nikoleris@arm.com } 7312776Snikos.nikoleris@arm.com 7412776Snikos.nikoleris@arm.com if ((int) src->d_type < 0 || src->d_type >= ELF_T_NUM) { 7512776Snikos.nikoleris@arm.com LIBELF_SET_ERROR(DATA, 0); 7612776Snikos.nikoleris@arm.com return (NULL); 778918SN/A } 7812776Snikos.nikoleris@arm.com 798918SN/A if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize)(src->d_type, 8012776Snikos.nikoleris@arm.com (size_t) 1, src->d_version)) == 0) 813804SN/A return (NULL); 823804SN/A 8312776Snikos.nikoleris@arm.com msz = _libelf_msize(src->d_type, elfclass, src->d_version); 8412776Snikos.nikoleris@arm.com 8512776Snikos.nikoleris@arm.com assert(msz > 0); 8612776Snikos.nikoleris@arm.com 8712776Snikos.nikoleris@arm.com if (src->d_size % (direction == ELF_TOMEMORY ? fsz : msz)) { 8812776Snikos.nikoleris@arm.com LIBELF_SET_ERROR(DATA, 0); 8912776Snikos.nikoleris@arm.com return (NULL); 9012776Snikos.nikoleris@arm.com } 9112776Snikos.nikoleris@arm.com 9212776Snikos.nikoleris@arm.com /* 938918SN/A * Determine the number of objects that need to be converted, and 9412776Snikos.nikoleris@arm.com * the space required for the converted objects in the destination 958918SN/A * buffer. 9612776Snikos.nikoleris@arm.com */ 978918SN/A if (direction == ELF_TOMEMORY) { 988918SN/A cnt = src->d_size / fsz; 9912776Snikos.nikoleris@arm.com dsz = cnt * msz; 10012776Snikos.nikoleris@arm.com } else { 10112776Snikos.nikoleris@arm.com cnt = src->d_size / msz; 10212776Snikos.nikoleris@arm.com dsz = cnt * fsz; 10312776Snikos.nikoleris@arm.com } 10412776Snikos.nikoleris@arm.com 10512776Snikos.nikoleris@arm.com if (dst->d_size < dsz) { 10612776Snikos.nikoleris@arm.com LIBELF_SET_ERROR(DATA, 0); 10712776Snikos.nikoleris@arm.com return (NULL); 10812776Snikos.nikoleris@arm.com } 10912776Snikos.nikoleris@arm.com 11012776Snikos.nikoleris@arm.com sb = (uintptr_t) src->d_buf; 1115609SN/A se = sb + src->d_size; 11212776Snikos.nikoleris@arm.com db = (uintptr_t) dst->d_buf; 1135609SN/A de = db + dst->d_size; 1145609SN/A 1159409Sandreas.hansson@arm.com /* 1169235Sandreas.hansson@arm.com * Check for overlapping buffers. Note that db == sb is 1173804SN/A * allowed. 11812776Snikos.nikoleris@arm.com */ 1193804SN/A if (db != sb && de > sb && se > db) { 1203804SN/A LIBELF_SET_ERROR(DATA, 0); 1218902SN/A return (NULL); 1223804SN/A } 1233804SN/A 1245608SN/A if ((direction == ELF_TOMEMORY ? db : sb) % 1255608SN/A _libelf_malign(src->d_type, elfclass)) { 1263804SN/A LIBELF_SET_ERROR(DATA, 0); 12712777Sgabeblack@google.com return (NULL); 1283804SN/A } 1293804SN/A 1303804SN/A dst->d_type = src->d_type; 1315608SN/A dst->d_size = dsz; 1325608SN/A 1333804SN/A if (db == sb && encoding == LIBELF_PRIVATE(byteorder) && 13412777Sgabeblack@google.com fsz == msz) 13512777Sgabeblack@google.com return (dst); /* nothing more to do */ 13612777Sgabeblack@google.com 1373804SN/A (_libelf_get_translator(src->d_type, direction, elfclass))(dst->d_buf, 1383804SN/A src->d_buf, cnt, encoding != LIBELF_PRIVATE(byteorder)); 1393804SN/A 1405608SN/A return (dst); 1415608SN/A} 1423804SN/A