1 /* $NetBSD: libelf_xlate.c,v 1.2 2014/03/09 16:58:04 christos Exp $ */
4 * Copyright (c) 2006,2008 Joseph Koshy
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #if HAVE_NBTOOL_CONFIG_H
30 # include "nbtool_config.h"
33 #include <sys/cdefs.h>
40 __RCSID("$NetBSD: libelf_xlate.c,v 1.2 2014/03/09 16:58:04 christos Exp $");
41 ELFTC_VCSID("Id: libelf_xlate.c 2225 2011-11-26 18:55:54Z jkoshy ");
44 * Translate to/from the file representation of ELF objects.
46 * Translation could potentially involve the following
49 * - an endianness conversion,
50 * - a change of layout, as the file representation of ELF objects
51 * can differ from their in-memory representation.
52 * - a change in representation due to a layout version change.
56 _libelf_xlate(Elf_Data
*dst
, const Elf_Data
*src
, unsigned int encoding
,
57 int elfclass
, int direction
)
60 size_t cnt
, dsz
, fsz
, msz
;
61 uintptr_t sb
, se
, db
, de
;
63 if (encoding
== ELFDATANONE
)
64 encoding
= _libelf_host_byteorder();
66 if ((encoding
!= ELFDATA2LSB
&& encoding
!= ELFDATA2MSB
) ||
67 dst
== NULL
|| src
== NULL
|| dst
== src
) {
68 LIBELF_SET_ERROR(ARGUMENT
, 0);
72 assert(elfclass
== ELFCLASS32
|| elfclass
== ELFCLASS64
);
73 assert(direction
== ELF_TOFILE
|| direction
== ELF_TOMEMORY
);
75 if (dst
->d_version
!= src
->d_version
) {
76 LIBELF_SET_ERROR(UNIMPL
, 0);
80 if (src
->d_buf
== NULL
|| dst
->d_buf
== NULL
) {
81 LIBELF_SET_ERROR(DATA
, 0);
85 if ((int) src
->d_type
< 0 || src
->d_type
>= ELF_T_NUM
) {
86 LIBELF_SET_ERROR(DATA
, 0);
90 if ((fsz
= (elfclass
== ELFCLASS32
? elf32_fsize
: elf64_fsize
)
91 (src
->d_type
, (size_t) 1, src
->d_version
)) == 0)
94 msz
= _libelf_msize(src
->d_type
, elfclass
, src
->d_version
);
98 if (src
->d_size
% (direction
== ELF_TOMEMORY
? fsz
: msz
)) {
99 LIBELF_SET_ERROR(DATA
, 0);
104 * Determine the number of objects that need to be converted, and
105 * the space required for the converted objects in the destination
108 if (direction
== ELF_TOMEMORY
) {
109 cnt
= src
->d_size
/ fsz
;
112 cnt
= src
->d_size
/ msz
;
116 if (dst
->d_size
< dsz
) {
117 LIBELF_SET_ERROR(DATA
, 0);
121 sb
= (uintptr_t) src
->d_buf
;
122 se
= sb
+ src
->d_size
;
123 db
= (uintptr_t) dst
->d_buf
;
124 de
= db
+ dst
->d_size
;
127 * Check for overlapping buffers. Note that db == sb is
130 if (db
!= sb
&& de
> sb
&& se
> db
) {
131 LIBELF_SET_ERROR(DATA
, 0);
135 if ((direction
== ELF_TOMEMORY
? db
: sb
) %
136 _libelf_malign(src
->d_type
, elfclass
)) {
137 LIBELF_SET_ERROR(DATA
, 0);
141 dst
->d_type
= src
->d_type
;
144 byteswap
= encoding
!= _libelf_host_byteorder();
146 if (src
->d_size
== 0 ||
147 (db
== sb
&& !byteswap
&& fsz
== msz
))
148 return (dst
); /* nothing more to do */
150 if (!(_libelf_get_translator(src
->d_type
, direction
, elfclass
))
151 (dst
->d_buf
, dsz
, src
->d_buf
, cnt
, byteswap
)) {
152 LIBELF_SET_ERROR(DATA
, 0);