12de3b87aSKai Wang/*- 22de3b87aSKai Wang * Copyright (c) 2006-2011 Joseph Koshy 32de3b87aSKai Wang * All rights reserved. 42de3b87aSKai Wang * 52de3b87aSKai Wang * Redistribution and use in source and binary forms, with or without 62de3b87aSKai Wang * modification, are permitted provided that the following conditions 72de3b87aSKai Wang * are met: 82de3b87aSKai Wang * 1. Redistributions of source code must retain the above copyright 92de3b87aSKai Wang * notice, this list of conditions and the following disclaimer. 102de3b87aSKai Wang * 2. Redistributions in binary form must reproduce the above copyright 112de3b87aSKai Wang * notice, this list of conditions and the following disclaimer in the 122de3b87aSKai Wang * documentation and/or other materials provided with the distribution. 132de3b87aSKai Wang * 142de3b87aSKai Wang * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 152de3b87aSKai Wang * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 162de3b87aSKai Wang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 172de3b87aSKai Wang * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 182de3b87aSKai Wang * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 192de3b87aSKai Wang * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 202de3b87aSKai Wang * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 212de3b87aSKai Wang * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 222de3b87aSKai Wang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 232de3b87aSKai Wang * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 242de3b87aSKai Wang * SUCH DAMAGE. 252de3b87aSKai Wang */ 262de3b87aSKai Wang 272de3b87aSKai Wang#include <assert.h> 282de3b87aSKai Wang#include <libelf.h> 292de3b87aSKai Wang#include <string.h> 302de3b87aSKai Wang 312de3b87aSKai Wang#include "_libelf.h" 322de3b87aSKai Wang 33d003e0d7SEd MasteELFTC_VCSID("$Id: libelf_convert.m4 3712 2019-03-16 22:23:34Z jkoshy $"); 342de3b87aSKai Wang 352de3b87aSKai Wang/* WARNING: GENERATED FROM __file__. */ 362de3b87aSKai Wang 372de3b87aSKai Wangdivert(-1) 382de3b87aSKai Wang 392de3b87aSKai Wang# Generate conversion routines for converting between in-memory and 402de3b87aSKai Wang# file representations of Elf data structures. 412de3b87aSKai Wang# 422de3b87aSKai Wang# These conversions use the type information defined in `elf_types.m4'. 432de3b87aSKai Wang 442de3b87aSKai Wanginclude(SRCDIR`/elf_types.m4') 452de3b87aSKai Wang 462de3b87aSKai Wang# For the purposes of generating conversion code, ELF types may be 472de3b87aSKai Wang# classified according to the following characteristics: 482de3b87aSKai Wang# 492de3b87aSKai Wang# 1. Whether the ELF type can be directly mapped to an integral C 502de3b87aSKai Wang# language type. For example, the ELF_T_WORD type maps directly to 512de3b87aSKai Wang# a 'uint32_t', but ELF_T_GNUHASH lacks a matching C type. 522de3b87aSKai Wang# 532de3b87aSKai Wang# 2. Whether the type has word size dependent variants. For example, 542de3b87aSKai Wang# ELT_T_EHDR is represented using C types Elf32_Ehdr and El64_Ehdr, 552de3b87aSKai Wang# and the ELF_T_ADDR and ELF_T_OFF types have integral C types that 562de3b87aSKai Wang# can be 32- or 64- bit wide. 572de3b87aSKai Wang# 582de3b87aSKai Wang# 3. Whether the ELF types has a fixed representation or not. For 592de3b87aSKai Wang# example, the ELF_T_SYM type has a fixed size file representation, 602de3b87aSKai Wang# some types like ELF_T_NOTE and ELF_T_GNUHASH use a variable size 612de3b87aSKai Wang# representation. 622de3b87aSKai Wang# 632de3b87aSKai Wang# We use m4 macros to generate conversion code for ELF types that have 642de3b87aSKai Wang# a fixed size representation. Conversion functions for the remaining 652de3b87aSKai Wang# types are coded by hand. 662de3b87aSKai Wang# 672de3b87aSKai Wang#* Handling File and Memory Representations 682de3b87aSKai Wang# 692de3b87aSKai Wang# `In-memory' representations of an Elf data structure use natural 702de3b87aSKai Wang# alignments and native byte ordering. This allows pointer arithmetic 712de3b87aSKai Wang# and casting to work as expected. On the other hand, the `file' 722de3b87aSKai Wang# representation of an ELF data structure could possibly be packed 732de3b87aSKai Wang# tighter than its `in-memory' representation, and could be of a 742de3b87aSKai Wang# differing byte order. Reading ELF objects that are members of `ar' 752de3b87aSKai Wang# archives present an additional complication: `ar' pads file data to 762de3b87aSKai Wang# even addresses, so file data structures in an archive member 772de3b87aSKai Wang# residing inside an `ar' archive could be at misaligned memory 782de3b87aSKai Wang# addresses when brought into memory. 792de3b87aSKai Wang# 802de3b87aSKai Wang# In summary, casting the `char *' pointers that point to memory 812de3b87aSKai Wang# representations (i.e., source pointers for the *_tof() functions and 822de3b87aSKai Wang# the destination pointers for the *_tom() functions), is safe, as 832de3b87aSKai Wang# these pointers should be correctly aligned for the memory type 842de3b87aSKai Wang# already. However, pointers to file representations have to be 852de3b87aSKai Wang# treated as being potentially unaligned and no casting can be done. 862de3b87aSKai Wang 872de3b87aSKai Wang# NOCVT(TYPE) -- Do not generate the cvt[] structure entry for TYPE 882de3b87aSKai Wangdefine(`NOCVT',`define(`NOCVT_'$1,1)') 892de3b87aSKai Wang 902de3b87aSKai Wang# NOFUNC(TYPE) -- Do not generate a conversion function for TYPE 912de3b87aSKai Wangdefine(`NOFUNC',`define(`NOFUNC_'$1,1)') 922de3b87aSKai Wang 932de3b87aSKai Wang# IGNORE(TYPE) -- Completely ignore the type. 942de3b87aSKai Wangdefine(`IGNORE',`NOCVT($1)NOFUNC($1)') 952de3b87aSKai Wang 962de3b87aSKai Wang# Mark ELF types that should not be processed by the M4 macros below. 972de3b87aSKai Wang 982de3b87aSKai Wang# Types for which we use functions with non-standard names. 992de3b87aSKai WangIGNORE(`BYTE') # Uses a wrapper around memcpy(). 1002de3b87aSKai WangIGNORE(`NOTE') # Not a fixed size type. 1012de3b87aSKai Wang 1022de3b87aSKai Wang# Types for which we supply hand-coded functions. 1032de3b87aSKai WangNOFUNC(`GNUHASH') # A type with complex internal structure. 1042de3b87aSKai WangNOFUNC(`VDEF') # See MAKE_VERSION_CONVERTERS below. 1052de3b87aSKai WangNOFUNC(`VNEED') # .. 1062de3b87aSKai Wang 1072de3b87aSKai Wang# Unimplemented types. 1082de3b87aSKai WangIGNORE(`MOVEP') 1092de3b87aSKai Wang 1102de3b87aSKai Wang# ELF types that don't exist in a 32-bit world. 1112de3b87aSKai WangNOFUNC(`XWORD32') 1122de3b87aSKai WangNOFUNC(`SXWORD32') 1132de3b87aSKai Wang 1142de3b87aSKai Wang# `Primitive' ELF types are those that are an alias for an integral 1152de3b87aSKai Wang# type. As they have no internal structure, they can be copied using 1162de3b87aSKai Wang# a `memcpy()', and byteswapped in straightforward way. 1172de3b87aSKai Wang# 1182de3b87aSKai Wang# Mark all ELF types that directly map to integral C types. 1192de3b87aSKai Wangdefine(`PRIM_ADDR', 1) 1202de3b87aSKai Wangdefine(`PRIM_BYTE', 1) 1212de3b87aSKai Wangdefine(`PRIM_HALF', 1) 1222de3b87aSKai Wangdefine(`PRIM_LWORD', 1) 1232de3b87aSKai Wangdefine(`PRIM_OFF', 1) 1242de3b87aSKai Wangdefine(`PRIM_SWORD', 1) 1252de3b87aSKai Wangdefine(`PRIM_SXWORD', 1) 1262de3b87aSKai Wangdefine(`PRIM_WORD', 1) 1272de3b87aSKai Wangdefine(`PRIM_XWORD', 1) 1282de3b87aSKai Wang 1292de3b87aSKai Wang# Note the primitive types that are size-dependent. 1302de3b87aSKai Wangdefine(`SIZEDEP_ADDR', 1) 1312de3b87aSKai Wangdefine(`SIZEDEP_OFF', 1) 1322de3b87aSKai Wang 1332de3b87aSKai Wang# Generate conversion functions for primitive types. 1342de3b87aSKai Wang# 1352de3b87aSKai Wang# Macro use: MAKEPRIMFUNCS(ELFTYPE,CTYPE,TYPESIZE,SYMSIZE) 1362de3b87aSKai Wang# `$1': Name of the ELF type. 1372de3b87aSKai Wang# `$2': C structure name suffix. 1382de3b87aSKai Wang# `$3': ELF class specifier for types, one of [`32', `64']. 1392de3b87aSKai Wang# `$4': Additional ELF class specifier, one of [`', `32', `64']. 1402de3b87aSKai Wang# 1412de3b87aSKai Wang# Generates a pair of conversion functions. 1422de3b87aSKai Wangdefine(`MAKEPRIMFUNCS',` 1432de3b87aSKai Wangstatic int 144cf781b2eSEd Maste_libelf_cvt_$1$4_tof(unsigned char *dst, size_t dsz, unsigned char *src, 145cf781b2eSEd Maste size_t count, int byteswap) 1462de3b87aSKai Wang{ 1472de3b87aSKai Wang Elf$3_$2 t, *s = (Elf$3_$2 *) (uintptr_t) src; 1482de3b87aSKai Wang size_t c; 1492de3b87aSKai Wang 1502de3b87aSKai Wang (void) dsz; 1512de3b87aSKai Wang 1522de3b87aSKai Wang if (!byteswap) { 1532de3b87aSKai Wang (void) memcpy(dst, src, count * sizeof(*s)); 1542de3b87aSKai Wang return (1); 1552de3b87aSKai Wang } 1562de3b87aSKai Wang 1572de3b87aSKai Wang for (c = 0; c < count; c++) { 1582de3b87aSKai Wang t = *s++; 1592de3b87aSKai Wang SWAP_$1$4(t); 1602de3b87aSKai Wang WRITE_$1$4(dst,t); 1612de3b87aSKai Wang } 1622de3b87aSKai Wang 1632de3b87aSKai Wang return (1); 1642de3b87aSKai Wang} 1652de3b87aSKai Wang 1662de3b87aSKai Wangstatic int 167cf781b2eSEd Maste_libelf_cvt_$1$4_tom(unsigned char *dst, size_t dsz, unsigned char *src, 168cf781b2eSEd Maste size_t count, int byteswap) 1692de3b87aSKai Wang{ 1702de3b87aSKai Wang Elf$3_$2 t, *d = (Elf$3_$2 *) (uintptr_t) dst; 1712de3b87aSKai Wang size_t c; 1722de3b87aSKai Wang 1732de3b87aSKai Wang if (dsz < count * sizeof(Elf$3_$2)) 1742de3b87aSKai Wang return (0); 1752de3b87aSKai Wang 1762de3b87aSKai Wang if (!byteswap) { 1772de3b87aSKai Wang (void) memcpy(dst, src, count * sizeof(*d)); 1782de3b87aSKai Wang return (1); 1792de3b87aSKai Wang } 1802de3b87aSKai Wang 1812de3b87aSKai Wang for (c = 0; c < count; c++) { 1822de3b87aSKai Wang READ_$1$4(src,t); 1832de3b87aSKai Wang SWAP_$1$4(t); 1842de3b87aSKai Wang *d++ = t; 1852de3b87aSKai Wang } 1862de3b87aSKai Wang 1872de3b87aSKai Wang return (1); 1882de3b87aSKai Wang} 1892de3b87aSKai Wang') 1902de3b87aSKai Wang 1912de3b87aSKai Wang# 1922de3b87aSKai Wang# Handling composite ELF types 1932de3b87aSKai Wang# 1942de3b87aSKai Wang 1952de3b87aSKai Wang# SWAP_FIELD(FIELDNAME,ELFTYPE) -- Generate code to swap one field. 1962de3b87aSKai Wangdefine(`SWAP_FIELD', 1972de3b87aSKai Wang `ifdef(`SIZEDEP_'$2, 1982de3b87aSKai Wang `SWAP_$2'SZ()`(t.$1); 1992de3b87aSKai Wang ', 2002de3b87aSKai Wang `SWAP_$2(t.$1); 2012de3b87aSKai Wang ')') 2022de3b87aSKai Wang 2032de3b87aSKai Wang# SWAP_MEMBERS(STRUCT) -- Iterate over a structure definition. 2042de3b87aSKai Wangdefine(`SWAP_MEMBERS', 2052de3b87aSKai Wang `ifelse($#,1,`/**/', 2062de3b87aSKai Wang `SWAP_FIELD($1)SWAP_MEMBERS(shift($@))')') 2072de3b87aSKai Wang 2082de3b87aSKai Wang# SWAP_STRUCT(CTYPE,SIZE) -- Generate code to swap an ELF structure. 2092de3b87aSKai Wangdefine(`SWAP_STRUCT', 2102de3b87aSKai Wang `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */ 2112de3b87aSKai Wang SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') 2122de3b87aSKai Wang 2132de3b87aSKai Wang# WRITE_FIELD(ELFTYPE,FIELDNAME) -- Generate code to write one field. 2142de3b87aSKai Wangdefine(`WRITE_FIELD', 2152de3b87aSKai Wang `ifdef(`SIZEDEP_'$2, 2162de3b87aSKai Wang `WRITE_$2'SZ()`(dst,t.$1); 2172de3b87aSKai Wang ', 2182de3b87aSKai Wang `WRITE_$2(dst,t.$1); 2192de3b87aSKai Wang ')') 2202de3b87aSKai Wang 2212de3b87aSKai Wang# WRITE_MEMBERS(ELFTYPELIST) -- Iterate over a structure definition. 2222de3b87aSKai Wangdefine(`WRITE_MEMBERS', 2232de3b87aSKai Wang `ifelse($#,1,`/**/', 2242de3b87aSKai Wang `WRITE_FIELD($1)WRITE_MEMBERS(shift($@))')') 2252de3b87aSKai Wang 2262de3b87aSKai Wang# WRITE_STRUCT(CTYPE,SIZE) -- Generate code to write out an ELF structure. 2272de3b87aSKai Wangdefine(`WRITE_STRUCT', 2282de3b87aSKai Wang `pushdef(`SZ',$2)/* Write an Elf$2_$1 */ 2292de3b87aSKai Wang WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') 2302de3b87aSKai Wang 2312de3b87aSKai Wang# READ_FIELD(ELFTYPE,CTYPE) -- Generate code to read one field. 2322de3b87aSKai Wangdefine(`READ_FIELD', 2332de3b87aSKai Wang `ifdef(`SIZEDEP_'$2, 2342de3b87aSKai Wang `READ_$2'SZ()`(s,t.$1); 2352de3b87aSKai Wang ', 2362de3b87aSKai Wang `READ_$2(s,t.$1); 2372de3b87aSKai Wang ')') 2382de3b87aSKai Wang 2392de3b87aSKai Wang# READ_MEMBERS(ELFTYPELIST) -- Iterate over a structure definition. 2402de3b87aSKai Wangdefine(`READ_MEMBERS', 2412de3b87aSKai Wang `ifelse($#,1,`/**/', 2422de3b87aSKai Wang `READ_FIELD($1)READ_MEMBERS(shift($@))')') 2432de3b87aSKai Wang 2442de3b87aSKai Wang# READ_STRUCT(CTYPE,SIZE) -- Generate code to read an ELF structure. 2452de3b87aSKai Wangdefine(`READ_STRUCT', 2462de3b87aSKai Wang `pushdef(`SZ',$2)/* Read an Elf$2_$1 */ 2472de3b87aSKai Wang READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') 2482de3b87aSKai Wang 2492de3b87aSKai Wang 2502de3b87aSKai Wang# MAKECOMPFUNCS -- Generate converters for composite ELF structures. 2512de3b87aSKai Wang# 2522de3b87aSKai Wang# When converting data to file representation, the source pointer will 2532de3b87aSKai Wang# be naturally aligned for a data structure's in-memory 2542de3b87aSKai Wang# representation. When converting data to memory, the destination 2552de3b87aSKai Wang# pointer will be similarly aligned. 2562de3b87aSKai Wang# 2572de3b87aSKai Wang# For in-place conversions, when converting to file representations, 2582de3b87aSKai Wang# the source buffer is large enough to hold `file' data. When 2592de3b87aSKai Wang# converting from file to memory, we need to be careful to work 2602de3b87aSKai Wang# `backwards', to avoid overwriting unconverted data. 2612de3b87aSKai Wang# 2622de3b87aSKai Wang# Macro use: 2632de3b87aSKai Wang# `$1': Name of the ELF type. 2642de3b87aSKai Wang# `$2': C structure name suffix. 2652de3b87aSKai Wang# `$3': ELF class specifier, one of [`', `32', `64'] 2662de3b87aSKai Wangdefine(`MAKECOMPFUNCS', `ifdef(`NOFUNC_'$1$3,`',` 2672de3b87aSKai Wangstatic int 268cf781b2eSEd Maste_libelf_cvt_$1$3_tof(unsigned char *dst, size_t dsz, unsigned char *src, 269cf781b2eSEd Maste size_t count, int byteswap) 2702de3b87aSKai Wang{ 2712de3b87aSKai Wang Elf$3_$2 t, *s; 2722de3b87aSKai Wang size_t c; 2732de3b87aSKai Wang 2742de3b87aSKai Wang (void) dsz; 2752de3b87aSKai Wang 2762de3b87aSKai Wang s = (Elf$3_$2 *) (uintptr_t) src; 2772de3b87aSKai Wang for (c = 0; c < count; c++) { 2782de3b87aSKai Wang t = *s++; 2792de3b87aSKai Wang if (byteswap) { 2802de3b87aSKai Wang SWAP_STRUCT($2,$3) 2812de3b87aSKai Wang } 2822de3b87aSKai Wang WRITE_STRUCT($2,$3) 2832de3b87aSKai Wang } 2842de3b87aSKai Wang 2852de3b87aSKai Wang return (1); 2862de3b87aSKai Wang} 2872de3b87aSKai Wang 2882de3b87aSKai Wangstatic int 289cf781b2eSEd Maste_libelf_cvt_$1$3_tom(unsigned char *dst, size_t dsz, unsigned char *src, 290cf781b2eSEd Maste size_t count, int byteswap) 2912de3b87aSKai Wang{ 2922de3b87aSKai Wang Elf$3_$2 t, *d; 293cf781b2eSEd Maste unsigned char *s,*s0; 2942de3b87aSKai Wang size_t fsz; 2952de3b87aSKai Wang 2962de3b87aSKai Wang fsz = elf$3_fsize(ELF_T_$1, (size_t) 1, EV_CURRENT); 2972de3b87aSKai Wang d = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1); 298cf781b2eSEd Maste s0 = src + (count - 1) * fsz; 2992de3b87aSKai Wang 3002de3b87aSKai Wang if (dsz < count * sizeof(Elf$3_$2)) 3012de3b87aSKai Wang return (0); 3022de3b87aSKai Wang 3032de3b87aSKai Wang while (count--) { 3042de3b87aSKai Wang s = s0; 3052de3b87aSKai Wang READ_STRUCT($2,$3) 3062de3b87aSKai Wang if (byteswap) { 3072de3b87aSKai Wang SWAP_STRUCT($2,$3) 3082de3b87aSKai Wang } 3092de3b87aSKai Wang *d-- = t; s0 -= fsz; 3102de3b87aSKai Wang } 3112de3b87aSKai Wang 3122de3b87aSKai Wang return (1); 3132de3b87aSKai Wang} 3142de3b87aSKai Wang')') 3152de3b87aSKai Wang 3162de3b87aSKai Wang# MAKE_TYPE_CONVERTER(ELFTYPE,CTYPE) 3172de3b87aSKai Wang# 3182de3b87aSKai Wang# Make type convertor functions from the type definition 3192de3b87aSKai Wang# of the ELF type: 3202de3b87aSKai Wang# - Skip convertors marked as `NOFUNC'. 3212de3b87aSKai Wang# - Invoke `MAKEPRIMFUNCS' or `MAKECOMPFUNCS' as appropriate. 3222de3b87aSKai Wangdefine(`MAKE_TYPE_CONVERTER', 3232de3b87aSKai Wang `ifdef(`NOFUNC_'$1,`', 3242de3b87aSKai Wang `ifdef(`PRIM_'$1, 3252de3b87aSKai Wang `ifdef(`SIZEDEP_'$1, 3262de3b87aSKai Wang `MAKEPRIMFUNCS($1,$2,32,32)dnl 3272de3b87aSKai Wang MAKEPRIMFUNCS($1,$2,64,64)', 3282de3b87aSKai Wang `MAKEPRIMFUNCS($1,$2,64)')', 3292de3b87aSKai Wang `MAKECOMPFUNCS($1,$2,32)dnl 3302de3b87aSKai Wang MAKECOMPFUNCS($1,$2,64)')')') 3312de3b87aSKai Wang 3322de3b87aSKai Wang# MAKE_TYPE_CONVERTERS(ELFTYPELIST) -- Generate conversion functions. 3332de3b87aSKai Wangdefine(`MAKE_TYPE_CONVERTERS', 3342de3b87aSKai Wang `ifelse($#,1,`', 3352de3b87aSKai Wang `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')') 3362de3b87aSKai Wang 3372de3b87aSKai Wang 3382de3b87aSKai Wang# 3392de3b87aSKai Wang# Macros to generate entries for the table of convertors. 3402de3b87aSKai Wang# 3412de3b87aSKai Wang 3422de3b87aSKai Wang# CONV(ELFTYPE,SIZE,DIRECTION) 3432de3b87aSKai Wang# 3442de3b87aSKai Wang# Generate the name of a convertor function. 3452de3b87aSKai Wangdefine(`CONV', 3462de3b87aSKai Wang `ifdef(`NOFUNC_'$1$2, 3472de3b87aSKai Wang `.$3$2 = NULL', 3482de3b87aSKai Wang `ifdef(`PRIM_'$1, 3492de3b87aSKai Wang `ifdef(`SIZEDEP_'$1, 3502de3b87aSKai Wang `.$3$2 = _libelf_cvt_$1$2_$3', 3512de3b87aSKai Wang `.$3$2 = _libelf_cvt_$1_$3')', 3522de3b87aSKai Wang `.$3$2 = _libelf_cvt_$1$2_$3')')') 3532de3b87aSKai Wang 3542de3b87aSKai Wang# CONVERTER_NAME(ELFTYPE) 3552de3b87aSKai Wang# 3562de3b87aSKai Wang# Generate the contents of one `struct cvt' instance. 3572de3b87aSKai Wangdefine(`CONVERTER_NAME', 3582de3b87aSKai Wang `ifdef(`NOCVT_'$1,`', 3592de3b87aSKai Wang ` [ELF_T_$1] = { 3602de3b87aSKai Wang CONV($1,32,tof), 3612de3b87aSKai Wang CONV($1,32,tom), 3622de3b87aSKai Wang CONV($1,64,tof), 3632de3b87aSKai Wang CONV($1,64,tom) 3642de3b87aSKai Wang }, 3652de3b87aSKai Wang 3662de3b87aSKai Wang')') 3672de3b87aSKai Wang 3682de3b87aSKai Wang# CONVERTER_NAMES(ELFTYPELIST) 3692de3b87aSKai Wang# 3702de3b87aSKai Wang# Generate the `struct cvt[]' array. 3712de3b87aSKai Wangdefine(`CONVERTER_NAMES', 3722de3b87aSKai Wang `ifelse($#,1,`', 3732de3b87aSKai Wang `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')') 3742de3b87aSKai Wang 3752de3b87aSKai Wang# 3762de3b87aSKai Wang# Handling ELF version sections. 3772de3b87aSKai Wang# 3782de3b87aSKai Wang 3792de3b87aSKai Wang# _FSZ(FIELD,BASETYPE) - return the file size for a field. 3802de3b87aSKai Wangdefine(`_FSZ', 3812de3b87aSKai Wang `ifelse($2,`HALF',2, 3822de3b87aSKai Wang $2,`WORD',4)') 3832de3b87aSKai Wang 3842de3b87aSKai Wang# FSZ(STRUCT) - determine the file size of a structure. 3852de3b87aSKai Wangdefine(`FSZ', 3862de3b87aSKai Wang `ifelse($#,1,0, 3872de3b87aSKai Wang `eval(_FSZ($1) + FSZ(shift($@)))')') 3882de3b87aSKai Wang 3892de3b87aSKai Wang# MAKE_VERSION_CONVERTERS(TYPE,BASE,AUX,PFX) -- Generate conversion 3902de3b87aSKai Wang# functions for versioning structures. 3912de3b87aSKai Wangdefine(`MAKE_VERSION_CONVERTERS', 3922de3b87aSKai Wang `MAKE_VERSION_CONVERTER($1,$2,$3,$4,32) 3932de3b87aSKai Wang MAKE_VERSION_CONVERTER($1,$2,$3,$4,64)') 3942de3b87aSKai Wang 3952de3b87aSKai Wang# MAKE_VERSION_CONVERTOR(TYPE,CBASE,CAUX,PFX,SIZE) -- Generate a 3962de3b87aSKai Wang# conversion function. 3972de3b87aSKai Wangdefine(`MAKE_VERSION_CONVERTER',` 3982de3b87aSKai Wangstatic int 399cf781b2eSEd Maste_libelf_cvt_$1$5_tof(unsigned char *dst, size_t dsz, unsigned char *src, 400cf781b2eSEd Maste size_t count, int byteswap) 4012de3b87aSKai Wang{ 4022de3b87aSKai Wang Elf$5_$2 t; 4032de3b87aSKai Wang Elf$5_$3 a; 4042de3b87aSKai Wang const size_t verfsz = FSZ(Elf$5_$2_DEF); 4052de3b87aSKai Wang const size_t auxfsz = FSZ(Elf$5_$3_DEF); 4062de3b87aSKai Wang const size_t vermsz = sizeof(Elf$5_$2); 4072de3b87aSKai Wang const size_t auxmsz = sizeof(Elf$5_$3); 408cf781b2eSEd Maste unsigned char * const dstend = dst + dsz; 409cf781b2eSEd Maste unsigned char * const srcend = src + count; 410cf781b2eSEd Maste unsigned char *dtmp, *dstaux, *srcaux; 4112de3b87aSKai Wang Elf$5_Word aux, anext, cnt, vnext; 4122de3b87aSKai Wang 413cf781b2eSEd Maste for (dtmp = dst, vnext = ~0U; 4142de3b87aSKai Wang vnext != 0 && dtmp + verfsz <= dstend && src + vermsz <= srcend; 4152de3b87aSKai Wang dtmp += vnext, src += vnext) { 4162de3b87aSKai Wang 4172de3b87aSKai Wang /* Read in an Elf$5_$2 structure. */ 4182de3b87aSKai Wang t = *((Elf$5_$2 *) (uintptr_t) src); 4192de3b87aSKai Wang 4202de3b87aSKai Wang aux = t.$4_aux; 4212de3b87aSKai Wang cnt = t.$4_cnt; 4222de3b87aSKai Wang vnext = t.$4_next; 4232de3b87aSKai Wang 4242de3b87aSKai Wang if (byteswap) { 4252de3b87aSKai Wang SWAP_STRUCT($2, $5) 4262de3b87aSKai Wang } 4272de3b87aSKai Wang 4282de3b87aSKai Wang dst = dtmp; 4292de3b87aSKai Wang WRITE_STRUCT($2, $5) 4302de3b87aSKai Wang 4312de3b87aSKai Wang if (aux < verfsz) 4322de3b87aSKai Wang return (0); 4332de3b87aSKai Wang 4342de3b87aSKai Wang /* Process AUX entries. */ 435cf781b2eSEd Maste for (anext = ~0U, dstaux = dtmp + aux, srcaux = src + aux; 4362de3b87aSKai Wang cnt != 0 && anext != 0 && dstaux + auxfsz <= dstend && 4372de3b87aSKai Wang srcaux + auxmsz <= srcend; 4382de3b87aSKai Wang dstaux += anext, srcaux += anext, cnt--) { 4392de3b87aSKai Wang 4402de3b87aSKai Wang /* Read in an Elf$5_$3 structure. */ 4412de3b87aSKai Wang a = *((Elf$5_$3 *) (uintptr_t) srcaux); 4422de3b87aSKai Wang anext = a.$4a_next; 4432de3b87aSKai Wang 4442de3b87aSKai Wang if (byteswap) { 4452de3b87aSKai Wang pushdef(`t',`a')SWAP_STRUCT($3, $5)popdef(`t') 4462de3b87aSKai Wang } 4472de3b87aSKai Wang 4482de3b87aSKai Wang dst = dstaux; 4492de3b87aSKai Wang pushdef(`t',`a')WRITE_STRUCT($3, $5)popdef(`t') 4502de3b87aSKai Wang } 4512de3b87aSKai Wang 4522de3b87aSKai Wang if (anext || cnt) 4532de3b87aSKai Wang return (0); 4542de3b87aSKai Wang } 4552de3b87aSKai Wang 4562de3b87aSKai Wang if (vnext) 4572de3b87aSKai Wang return (0); 4582de3b87aSKai Wang 4592de3b87aSKai Wang return (1); 4602de3b87aSKai Wang} 4612de3b87aSKai Wang 4622de3b87aSKai Wangstatic int 463cf781b2eSEd Maste_libelf_cvt_$1$5_tom(unsigned char *dst, size_t dsz, unsigned char *src, 464cf781b2eSEd Maste size_t count, int byteswap) 4652de3b87aSKai Wang{ 4662de3b87aSKai Wang Elf$5_$2 t, *dp; 4672de3b87aSKai Wang Elf$5_$3 a, *ap; 4682de3b87aSKai Wang const size_t verfsz = FSZ(Elf$5_$2_DEF); 4692de3b87aSKai Wang const size_t auxfsz = FSZ(Elf$5_$3_DEF); 4702de3b87aSKai Wang const size_t vermsz = sizeof(Elf$5_$2); 4712de3b87aSKai Wang const size_t auxmsz = sizeof(Elf$5_$3); 472cf781b2eSEd Maste unsigned char * const dstend = dst + dsz; 473cf781b2eSEd Maste unsigned char * const srcend = src + count; 474cf781b2eSEd Maste unsigned char *dstaux, *s, *srcaux, *stmp; 4752de3b87aSKai Wang Elf$5_Word aux, anext, cnt, vnext; 4762de3b87aSKai Wang 477cf781b2eSEd Maste for (stmp = src, vnext = ~0U; 4782de3b87aSKai Wang vnext != 0 && stmp + verfsz <= srcend && dst + vermsz <= dstend; 4792de3b87aSKai Wang stmp += vnext, dst += vnext) { 4802de3b87aSKai Wang 4812de3b87aSKai Wang /* Read in a $1 structure. */ 4822de3b87aSKai Wang s = stmp; 4832de3b87aSKai Wang READ_STRUCT($2, $5) 4842de3b87aSKai Wang if (byteswap) { 4852de3b87aSKai Wang SWAP_STRUCT($2, $5) 4862de3b87aSKai Wang } 4872de3b87aSKai Wang 4882de3b87aSKai Wang dp = (Elf$5_$2 *) (uintptr_t) dst; 4892de3b87aSKai Wang *dp = t; 4902de3b87aSKai Wang 4912de3b87aSKai Wang aux = t.$4_aux; 4922de3b87aSKai Wang cnt = t.$4_cnt; 4932de3b87aSKai Wang vnext = t.$4_next; 4942de3b87aSKai Wang 4952de3b87aSKai Wang if (aux < vermsz) 4962de3b87aSKai Wang return (0); 4972de3b87aSKai Wang 4982de3b87aSKai Wang /* Process AUX entries. */ 499cf781b2eSEd Maste for (anext = ~0U, dstaux = dst + aux, srcaux = stmp + aux; 5002de3b87aSKai Wang cnt != 0 && anext != 0 && dstaux + auxmsz <= dstend && 5012de3b87aSKai Wang srcaux + auxfsz <= srcend; 5022de3b87aSKai Wang dstaux += anext, srcaux += anext, cnt--) { 5032de3b87aSKai Wang 5042de3b87aSKai Wang s = srcaux; 5052de3b87aSKai Wang pushdef(`t',`a')READ_STRUCT($3, $5)popdef(`t') 5062de3b87aSKai Wang 5072de3b87aSKai Wang if (byteswap) { 5082de3b87aSKai Wang pushdef(`t',`a')SWAP_STRUCT($3, $5)popdef(`t') 5092de3b87aSKai Wang } 5102de3b87aSKai Wang 5112de3b87aSKai Wang anext = a.$4a_next; 5122de3b87aSKai Wang 5132de3b87aSKai Wang ap = ((Elf$5_$3 *) (uintptr_t) dstaux); 5142de3b87aSKai Wang *ap = a; 5152de3b87aSKai Wang } 5162de3b87aSKai Wang 5172de3b87aSKai Wang if (anext || cnt) 5182de3b87aSKai Wang return (0); 5192de3b87aSKai Wang } 5202de3b87aSKai Wang 5212de3b87aSKai Wang if (vnext) 5222de3b87aSKai Wang return (0); 5232de3b87aSKai Wang 5242de3b87aSKai Wang return (1); 5252de3b87aSKai Wang}') 5262de3b87aSKai Wang 5272de3b87aSKai Wangdivert(0) 5282de3b87aSKai Wang 5292de3b87aSKai Wang/* 5302de3b87aSKai Wang * C macros to byte swap integral quantities. 5312de3b87aSKai Wang */ 5322de3b87aSKai Wang 5332de3b87aSKai Wang#define SWAP_BYTE(X) do { (void) (X); } while (0) 5342de3b87aSKai Wang#define SWAP_IDENT(X) do { (void) (X); } while (0) 5352de3b87aSKai Wang#define SWAP_HALF(X) do { \ 5362de3b87aSKai Wang uint16_t _x = (uint16_t) (X); \ 537cf781b2eSEd Maste uint32_t _t = _x & 0xFFU; \ 538cf781b2eSEd Maste _t <<= 8U; _x >>= 8U; _t |= _x & 0xFFU; \ 539cf781b2eSEd Maste (X) = (uint16_t) _t; \ 5402de3b87aSKai Wang } while (0) 541cf781b2eSEd Maste#define _SWAP_WORD(X, T) do { \ 5422de3b87aSKai Wang uint32_t _x = (uint32_t) (X); \ 5432de3b87aSKai Wang uint32_t _t = _x & 0xFF; \ 5442de3b87aSKai Wang _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 5452de3b87aSKai Wang _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 5462de3b87aSKai Wang _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 547cf781b2eSEd Maste (X) = (T) _t; \ 5482de3b87aSKai Wang } while (0) 549cf781b2eSEd Maste#define SWAP_ADDR32(X) _SWAP_WORD(X, Elf32_Addr) 550cf781b2eSEd Maste#define SWAP_OFF32(X) _SWAP_WORD(X, Elf32_Off) 551cf781b2eSEd Maste#define SWAP_SWORD(X) _SWAP_WORD(X, Elf32_Sword) 552cf781b2eSEd Maste#define SWAP_WORD(X) _SWAP_WORD(X, Elf32_Word) 553cf781b2eSEd Maste#define _SWAP_WORD64(X, T) do { \ 5542de3b87aSKai Wang uint64_t _x = (uint64_t) (X); \ 5552de3b87aSKai Wang uint64_t _t = _x & 0xFF; \ 5562de3b87aSKai Wang _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 5572de3b87aSKai Wang _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 5582de3b87aSKai Wang _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 5592de3b87aSKai Wang _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 5602de3b87aSKai Wang _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 5612de3b87aSKai Wang _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 5622de3b87aSKai Wang _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 563cf781b2eSEd Maste (X) = (T) _t; \ 5642de3b87aSKai Wang } while (0) 565cf781b2eSEd Maste#define SWAP_ADDR64(X) _SWAP_WORD64(X, Elf64_Addr) 566cf781b2eSEd Maste#define SWAP_LWORD(X) _SWAP_WORD64(X, Elf64_Lword) 567cf781b2eSEd Maste#define SWAP_OFF64(X) _SWAP_WORD64(X, Elf64_Off) 568cf781b2eSEd Maste#define SWAP_SXWORD(X) _SWAP_WORD64(X, Elf64_Sxword) 569cf781b2eSEd Maste#define SWAP_XWORD(X) _SWAP_WORD64(X, Elf64_Xword) 5702de3b87aSKai Wang 5712de3b87aSKai Wang/* 5722de3b87aSKai Wang * C macros to write out various integral values. 5732de3b87aSKai Wang * 5742de3b87aSKai Wang * Note: 5752de3b87aSKai Wang * - The destination pointer could be unaligned. 5762de3b87aSKai Wang * - Values are written out in native byte order. 5772de3b87aSKai Wang * - The destination pointer is incremented after the write. 5782de3b87aSKai Wang */ 5792de3b87aSKai Wang#define WRITE_BYTE(P,X) do { \ 580cf781b2eSEd Maste unsigned char *const _p = (unsigned char *) (P); \ 581cf781b2eSEd Maste _p[0] = (unsigned char) (X); \ 5822de3b87aSKai Wang (P) = _p + 1; \ 5832de3b87aSKai Wang } while (0) 5842de3b87aSKai Wang#define WRITE_HALF(P,X) do { \ 5852de3b87aSKai Wang uint16_t _t = (X); \ 586cf781b2eSEd Maste unsigned char *const _p = (unsigned char *) (P); \ 587cf781b2eSEd Maste const unsigned char *const _q = (unsigned char *) &_t; \ 5882de3b87aSKai Wang _p[0] = _q[0]; \ 5892de3b87aSKai Wang _p[1] = _q[1]; \ 5902de3b87aSKai Wang (P) = _p + 2; \ 5912de3b87aSKai Wang } while (0) 5922de3b87aSKai Wang#define WRITE_WORD(P,X) do { \ 593cf781b2eSEd Maste uint32_t _t = (uint32_t) (X); \ 594cf781b2eSEd Maste unsigned char *const _p = (unsigned char *) (P); \ 595cf781b2eSEd Maste const unsigned char *const _q = (unsigned char *) &_t; \ 5962de3b87aSKai Wang _p[0] = _q[0]; \ 5972de3b87aSKai Wang _p[1] = _q[1]; \ 5982de3b87aSKai Wang _p[2] = _q[2]; \ 5992de3b87aSKai Wang _p[3] = _q[3]; \ 6002de3b87aSKai Wang (P) = _p + 4; \ 6012de3b87aSKai Wang } while (0) 6022de3b87aSKai Wang#define WRITE_ADDR32(P,X) WRITE_WORD(P,X) 6032de3b87aSKai Wang#define WRITE_OFF32(P,X) WRITE_WORD(P,X) 6042de3b87aSKai Wang#define WRITE_SWORD(P,X) WRITE_WORD(P,X) 6052de3b87aSKai Wang#define WRITE_WORD64(P,X) do { \ 606cf781b2eSEd Maste uint64_t _t = (uint64_t) (X); \ 607cf781b2eSEd Maste unsigned char *const _p = (unsigned char *) (P); \ 608cf781b2eSEd Maste const unsigned char *const _q = (unsigned char *) &_t; \ 6092de3b87aSKai Wang _p[0] = _q[0]; \ 6102de3b87aSKai Wang _p[1] = _q[1]; \ 6112de3b87aSKai Wang _p[2] = _q[2]; \ 6122de3b87aSKai Wang _p[3] = _q[3]; \ 6132de3b87aSKai Wang _p[4] = _q[4]; \ 6142de3b87aSKai Wang _p[5] = _q[5]; \ 6152de3b87aSKai Wang _p[6] = _q[6]; \ 6162de3b87aSKai Wang _p[7] = _q[7]; \ 6172de3b87aSKai Wang (P) = _p + 8; \ 6182de3b87aSKai Wang } while (0) 6192de3b87aSKai Wang#define WRITE_ADDR64(P,X) WRITE_WORD64(P,X) 6202de3b87aSKai Wang#define WRITE_LWORD(P,X) WRITE_WORD64(P,X) 6212de3b87aSKai Wang#define WRITE_OFF64(P,X) WRITE_WORD64(P,X) 6222de3b87aSKai Wang#define WRITE_SXWORD(P,X) WRITE_WORD64(P,X) 6232de3b87aSKai Wang#define WRITE_XWORD(P,X) WRITE_WORD64(P,X) 6242de3b87aSKai Wang#define WRITE_IDENT(P,X) do { \ 6252de3b87aSKai Wang (void) memcpy((P), (X), sizeof((X))); \ 6262de3b87aSKai Wang (P) = (P) + EI_NIDENT; \ 6272de3b87aSKai Wang } while (0) 6282de3b87aSKai Wang 6292de3b87aSKai Wang/* 6302de3b87aSKai Wang * C macros to read in various integral values. 6312de3b87aSKai Wang * 6322de3b87aSKai Wang * Note: 6332de3b87aSKai Wang * - The source pointer could be unaligned. 6342de3b87aSKai Wang * - Values are read in native byte order. 6352de3b87aSKai Wang * - The source pointer is incremented appropriately. 6362de3b87aSKai Wang */ 6372de3b87aSKai Wang 6382de3b87aSKai Wang#define READ_BYTE(P,X) do { \ 639cf781b2eSEd Maste const unsigned char *const _p = \ 640cf781b2eSEd Maste (const unsigned char *) (P); \ 6412de3b87aSKai Wang (X) = _p[0]; \ 6422de3b87aSKai Wang (P) = (P) + 1; \ 6432de3b87aSKai Wang } while (0) 6442de3b87aSKai Wang#define READ_HALF(P,X) do { \ 6452de3b87aSKai Wang uint16_t _t; \ 646cf781b2eSEd Maste unsigned char *const _q = (unsigned char *) &_t; \ 647cf781b2eSEd Maste const unsigned char *const _p = \ 648cf781b2eSEd Maste (const unsigned char *) (P); \ 6492de3b87aSKai Wang _q[0] = _p[0]; \ 6502de3b87aSKai Wang _q[1] = _p[1]; \ 6512de3b87aSKai Wang (P) = (P) + 2; \ 6522de3b87aSKai Wang (X) = _t; \ 6532de3b87aSKai Wang } while (0) 654cf781b2eSEd Maste#define _READ_WORD(P,X,T) do { \ 6552de3b87aSKai Wang uint32_t _t; \ 656cf781b2eSEd Maste unsigned char *const _q = (unsigned char *) &_t; \ 657cf781b2eSEd Maste const unsigned char *const _p = \ 658cf781b2eSEd Maste (const unsigned char *) (P); \ 6592de3b87aSKai Wang _q[0] = _p[0]; \ 6602de3b87aSKai Wang _q[1] = _p[1]; \ 6612de3b87aSKai Wang _q[2] = _p[2]; \ 6622de3b87aSKai Wang _q[3] = _p[3]; \ 6632de3b87aSKai Wang (P) = (P) + 4; \ 664cf781b2eSEd Maste (X) = (T) _t; \ 6652de3b87aSKai Wang } while (0) 666cf781b2eSEd Maste#define READ_ADDR32(P,X) _READ_WORD(P, X, Elf32_Addr) 667cf781b2eSEd Maste#define READ_OFF32(P,X) _READ_WORD(P, X, Elf32_Off) 668cf781b2eSEd Maste#define READ_SWORD(P,X) _READ_WORD(P, X, Elf32_Sword) 669cf781b2eSEd Maste#define READ_WORD(P,X) _READ_WORD(P, X, Elf32_Word) 670cf781b2eSEd Maste#define _READ_WORD64(P,X,T) do { \ 6712de3b87aSKai Wang uint64_t _t; \ 672cf781b2eSEd Maste unsigned char *const _q = (unsigned char *) &_t; \ 673cf781b2eSEd Maste const unsigned char *const _p = \ 674cf781b2eSEd Maste (const unsigned char *) (P); \ 6752de3b87aSKai Wang _q[0] = _p[0]; \ 6762de3b87aSKai Wang _q[1] = _p[1]; \ 6772de3b87aSKai Wang _q[2] = _p[2]; \ 6782de3b87aSKai Wang _q[3] = _p[3]; \ 6792de3b87aSKai Wang _q[4] = _p[4]; \ 6802de3b87aSKai Wang _q[5] = _p[5]; \ 6812de3b87aSKai Wang _q[6] = _p[6]; \ 6822de3b87aSKai Wang _q[7] = _p[7]; \ 6832de3b87aSKai Wang (P) = (P) + 8; \ 684cf781b2eSEd Maste (X) = (T) _t; \ 6852de3b87aSKai Wang } while (0) 686cf781b2eSEd Maste#define READ_ADDR64(P,X) _READ_WORD64(P, X, Elf64_Addr) 687cf781b2eSEd Maste#define READ_LWORD(P,X) _READ_WORD64(P, X, Elf64_Lword) 688cf781b2eSEd Maste#define READ_OFF64(P,X) _READ_WORD64(P, X, Elf64_Off) 689cf781b2eSEd Maste#define READ_SXWORD(P,X) _READ_WORD64(P, X, Elf64_Sxword) 690cf781b2eSEd Maste#define READ_XWORD(P,X) _READ_WORD64(P, X, Elf64_Xword) 6912de3b87aSKai Wang#define READ_IDENT(P,X) do { \ 6922de3b87aSKai Wang (void) memcpy((X), (P), sizeof((X))); \ 6932de3b87aSKai Wang (P) = (P) + EI_NIDENT; \ 6942de3b87aSKai Wang } while (0) 6952de3b87aSKai Wang 6962de3b87aSKai Wang#define ROUNDUP2(V,N) (V) = ((((V) + (N) - 1)) & ~((N) - 1)) 6972de3b87aSKai Wang 6982de3b87aSKai Wang/*[*/ 6992de3b87aSKai WangMAKE_TYPE_CONVERTERS(ELF_TYPE_LIST) 7002de3b87aSKai WangMAKE_VERSION_CONVERTERS(VDEF,Verdef,Verdaux,vd) 7012de3b87aSKai WangMAKE_VERSION_CONVERTERS(VNEED,Verneed,Vernaux,vn) 7022de3b87aSKai Wang/*]*/ 7032de3b87aSKai Wang 7042de3b87aSKai Wang/* 7052de3b87aSKai Wang * Sections of type ELF_T_BYTE are never byteswapped, consequently a 7062de3b87aSKai Wang * simple memcpy suffices for both directions of conversion. 7072de3b87aSKai Wang */ 7082de3b87aSKai Wang 7092de3b87aSKai Wangstatic int 710cf781b2eSEd Maste_libelf_cvt_BYTE_tox(unsigned char *dst, size_t dsz, unsigned char *src, 711cf781b2eSEd Maste size_t count, int byteswap) 7122de3b87aSKai Wang{ 7132de3b87aSKai Wang (void) byteswap; 7142de3b87aSKai Wang if (dsz < count) 7152de3b87aSKai Wang return (0); 7162de3b87aSKai Wang if (dst != src) 7172de3b87aSKai Wang (void) memcpy(dst, src, count); 7182de3b87aSKai Wang return (1); 7192de3b87aSKai Wang} 7202de3b87aSKai Wang 7212de3b87aSKai Wang/* 7222de3b87aSKai Wang * Sections of type ELF_T_GNUHASH start with a header containing 4 32-bit 7232de3b87aSKai Wang * words. Bloom filter data comes next, followed by hash buckets and the 7242de3b87aSKai Wang * hash chain. 7252de3b87aSKai Wang * 7262de3b87aSKai Wang * Bloom filter words are 64 bit wide on ELFCLASS64 objects and are 32 bit 7272de3b87aSKai Wang * wide on ELFCLASS32 objects. The other objects in this section are 32 7282de3b87aSKai Wang * bits wide. 7292de3b87aSKai Wang * 7302de3b87aSKai Wang * Argument `srcsz' denotes the number of bytes to be converted. In the 7312de3b87aSKai Wang * 32-bit case we need to translate `srcsz' to a count of 32-bit words. 7322de3b87aSKai Wang */ 7332de3b87aSKai Wang 7342de3b87aSKai Wangstatic int 735cf781b2eSEd Maste_libelf_cvt_GNUHASH32_tom(unsigned char *dst, size_t dsz, unsigned char *src, 736cf781b2eSEd Maste size_t srcsz, int byteswap) 7372de3b87aSKai Wang{ 7382de3b87aSKai Wang return (_libelf_cvt_WORD_tom(dst, dsz, src, srcsz / sizeof(uint32_t), 7392de3b87aSKai Wang byteswap)); 7402de3b87aSKai Wang} 7412de3b87aSKai Wang 7422de3b87aSKai Wangstatic int 743cf781b2eSEd Maste_libelf_cvt_GNUHASH32_tof(unsigned char *dst, size_t dsz, unsigned char *src, 744cf781b2eSEd Maste size_t srcsz, int byteswap) 7452de3b87aSKai Wang{ 7462de3b87aSKai Wang return (_libelf_cvt_WORD_tof(dst, dsz, src, srcsz / sizeof(uint32_t), 7472de3b87aSKai Wang byteswap)); 7482de3b87aSKai Wang} 7492de3b87aSKai Wang 7502de3b87aSKai Wangstatic int 751cf781b2eSEd Maste_libelf_cvt_GNUHASH64_tom(unsigned char *dst, size_t dsz, unsigned char *src, 752cf781b2eSEd Maste size_t srcsz, int byteswap) 7532de3b87aSKai Wang{ 7542de3b87aSKai Wang size_t sz; 7552de3b87aSKai Wang uint64_t t64, *bloom64; 7562de3b87aSKai Wang Elf_GNU_Hash_Header *gh; 7572de3b87aSKai Wang uint32_t n, nbuckets, nchains, maskwords, shift2, symndx, t32; 7582de3b87aSKai Wang uint32_t *buckets, *chains; 7592de3b87aSKai Wang 7602de3b87aSKai Wang sz = 4 * sizeof(uint32_t); /* File header is 4 words long. */ 7612de3b87aSKai Wang if (dsz < sizeof(Elf_GNU_Hash_Header) || srcsz < sz) 7622de3b87aSKai Wang return (0); 7632de3b87aSKai Wang 7642de3b87aSKai Wang /* Read in the section header and byteswap if needed. */ 7652de3b87aSKai Wang READ_WORD(src, nbuckets); 7662de3b87aSKai Wang READ_WORD(src, symndx); 7672de3b87aSKai Wang READ_WORD(src, maskwords); 7682de3b87aSKai Wang READ_WORD(src, shift2); 7692de3b87aSKai Wang 7702de3b87aSKai Wang srcsz -= sz; 7712de3b87aSKai Wang 7722de3b87aSKai Wang if (byteswap) { 7732de3b87aSKai Wang SWAP_WORD(nbuckets); 7742de3b87aSKai Wang SWAP_WORD(symndx); 7752de3b87aSKai Wang SWAP_WORD(maskwords); 7762de3b87aSKai Wang SWAP_WORD(shift2); 7772de3b87aSKai Wang } 7782de3b87aSKai Wang 7792de3b87aSKai Wang /* Check source buffer and destination buffer sizes. */ 7802de3b87aSKai Wang sz = nbuckets * sizeof(uint32_t) + maskwords * sizeof(uint64_t); 7812de3b87aSKai Wang if (srcsz < sz || dsz < sz + sizeof(Elf_GNU_Hash_Header)) 7822de3b87aSKai Wang return (0); 7832de3b87aSKai Wang 7842de3b87aSKai Wang gh = (Elf_GNU_Hash_Header *) (uintptr_t) dst; 7852de3b87aSKai Wang gh->gh_nbuckets = nbuckets; 7862de3b87aSKai Wang gh->gh_symndx = symndx; 7872de3b87aSKai Wang gh->gh_maskwords = maskwords; 7882de3b87aSKai Wang gh->gh_shift2 = shift2; 7892de3b87aSKai Wang 7902de3b87aSKai Wang dsz -= sizeof(Elf_GNU_Hash_Header); 7912de3b87aSKai Wang dst += sizeof(Elf_GNU_Hash_Header); 7922de3b87aSKai Wang 7932de3b87aSKai Wang bloom64 = (uint64_t *) (uintptr_t) dst; 7942de3b87aSKai Wang 7952de3b87aSKai Wang /* Copy bloom filter data. */ 7962de3b87aSKai Wang for (n = 0; n < maskwords; n++) { 7972de3b87aSKai Wang READ_XWORD(src, t64); 7982de3b87aSKai Wang if (byteswap) 7992de3b87aSKai Wang SWAP_XWORD(t64); 8002de3b87aSKai Wang bloom64[n] = t64; 8012de3b87aSKai Wang } 8022de3b87aSKai Wang 8032de3b87aSKai Wang /* The hash buckets follows the bloom filter. */ 8042de3b87aSKai Wang dst += maskwords * sizeof(uint64_t); 8052de3b87aSKai Wang buckets = (uint32_t *) (uintptr_t) dst; 8062de3b87aSKai Wang 8072de3b87aSKai Wang for (n = 0; n < nbuckets; n++) { 8082de3b87aSKai Wang READ_WORD(src, t32); 8092de3b87aSKai Wang if (byteswap) 8102de3b87aSKai Wang SWAP_WORD(t32); 8112de3b87aSKai Wang buckets[n] = t32; 8122de3b87aSKai Wang } 8132de3b87aSKai Wang 8142de3b87aSKai Wang dst += nbuckets * sizeof(uint32_t); 8152de3b87aSKai Wang 8162de3b87aSKai Wang /* The hash chain follows the hash buckets. */ 8172de3b87aSKai Wang dsz -= sz; 8182de3b87aSKai Wang srcsz -= sz; 8192de3b87aSKai Wang 8202de3b87aSKai Wang if (dsz < srcsz) /* Destination lacks space. */ 8212de3b87aSKai Wang return (0); 8222de3b87aSKai Wang 823d003e0d7SEd Maste nchains = (uint32_t) (srcsz / sizeof(uint32_t)); 8242de3b87aSKai Wang chains = (uint32_t *) (uintptr_t) dst; 8252de3b87aSKai Wang 8262de3b87aSKai Wang for (n = 0; n < nchains; n++) { 8272de3b87aSKai Wang READ_WORD(src, t32); 8282de3b87aSKai Wang if (byteswap) 8292de3b87aSKai Wang SWAP_WORD(t32); 8302de3b87aSKai Wang *chains++ = t32; 8312de3b87aSKai Wang } 8322de3b87aSKai Wang 8332de3b87aSKai Wang return (1); 8342de3b87aSKai Wang} 8352de3b87aSKai Wang 8362de3b87aSKai Wangstatic int 837cf781b2eSEd Maste_libelf_cvt_GNUHASH64_tof(unsigned char *dst, size_t dsz, unsigned char *src, 838cf781b2eSEd Maste size_t srcsz, int byteswap) 8392de3b87aSKai Wang{ 8402de3b87aSKai Wang uint32_t *s32; 8412de3b87aSKai Wang size_t sz, hdrsz; 8422de3b87aSKai Wang uint64_t *s64, t64; 8432de3b87aSKai Wang Elf_GNU_Hash_Header *gh; 8442de3b87aSKai Wang uint32_t maskwords, n, nbuckets, nchains, t0, t1, t2, t3, t32; 8452de3b87aSKai Wang 8462de3b87aSKai Wang hdrsz = 4 * sizeof(uint32_t); /* Header is 4x32 bits. */ 8472de3b87aSKai Wang if (dsz < hdrsz || srcsz < sizeof(Elf_GNU_Hash_Header)) 8482de3b87aSKai Wang return (0); 8492de3b87aSKai Wang 8502de3b87aSKai Wang gh = (Elf_GNU_Hash_Header *) (uintptr_t) src; 8512de3b87aSKai Wang 8522de3b87aSKai Wang t0 = nbuckets = gh->gh_nbuckets; 8532de3b87aSKai Wang t1 = gh->gh_symndx; 8542de3b87aSKai Wang t2 = maskwords = gh->gh_maskwords; 8552de3b87aSKai Wang t3 = gh->gh_shift2; 8562de3b87aSKai Wang 8572de3b87aSKai Wang src += sizeof(Elf_GNU_Hash_Header); 8582de3b87aSKai Wang srcsz -= sizeof(Elf_GNU_Hash_Header); 8592de3b87aSKai Wang dsz -= hdrsz; 8602de3b87aSKai Wang 8612de3b87aSKai Wang sz = gh->gh_nbuckets * sizeof(uint32_t) + gh->gh_maskwords * 8622de3b87aSKai Wang sizeof(uint64_t); 8632de3b87aSKai Wang 8642de3b87aSKai Wang if (srcsz < sz || dsz < sz) 8652de3b87aSKai Wang return (0); 8662de3b87aSKai Wang 8672de3b87aSKai Wang /* Write out the header. */ 8682de3b87aSKai Wang if (byteswap) { 8692de3b87aSKai Wang SWAP_WORD(t0); 8702de3b87aSKai Wang SWAP_WORD(t1); 8712de3b87aSKai Wang SWAP_WORD(t2); 8722de3b87aSKai Wang SWAP_WORD(t3); 8732de3b87aSKai Wang } 8742de3b87aSKai Wang 8752de3b87aSKai Wang WRITE_WORD(dst, t0); 8762de3b87aSKai Wang WRITE_WORD(dst, t1); 8772de3b87aSKai Wang WRITE_WORD(dst, t2); 8782de3b87aSKai Wang WRITE_WORD(dst, t3); 8792de3b87aSKai Wang 8802de3b87aSKai Wang /* Copy the bloom filter and the hash table. */ 8812de3b87aSKai Wang s64 = (uint64_t *) (uintptr_t) src; 8822de3b87aSKai Wang for (n = 0; n < maskwords; n++) { 8832de3b87aSKai Wang t64 = *s64++; 8842de3b87aSKai Wang if (byteswap) 8852de3b87aSKai Wang SWAP_XWORD(t64); 8862de3b87aSKai Wang WRITE_WORD64(dst, t64); 8872de3b87aSKai Wang } 8882de3b87aSKai Wang 8892de3b87aSKai Wang s32 = (uint32_t *) s64; 8902de3b87aSKai Wang for (n = 0; n < nbuckets; n++) { 8912de3b87aSKai Wang t32 = *s32++; 8922de3b87aSKai Wang if (byteswap) 8932de3b87aSKai Wang SWAP_WORD(t32); 8942de3b87aSKai Wang WRITE_WORD(dst, t32); 8952de3b87aSKai Wang } 8962de3b87aSKai Wang 8972de3b87aSKai Wang srcsz -= sz; 8982de3b87aSKai Wang dsz -= sz; 8992de3b87aSKai Wang 9002de3b87aSKai Wang /* Copy out the hash chains. */ 9012de3b87aSKai Wang if (dsz < srcsz) 9022de3b87aSKai Wang return (0); 9032de3b87aSKai Wang 904d003e0d7SEd Maste nchains = (uint32_t) (srcsz / sizeof(uint32_t)); 9052de3b87aSKai Wang for (n = 0; n < nchains; n++) { 9062de3b87aSKai Wang t32 = *s32++; 9072de3b87aSKai Wang if (byteswap) 9082de3b87aSKai Wang SWAP_WORD(t32); 9092de3b87aSKai Wang WRITE_WORD(dst, t32); 9102de3b87aSKai Wang } 9112de3b87aSKai Wang 9122de3b87aSKai Wang return (1); 9132de3b87aSKai Wang} 9142de3b87aSKai Wang 9152de3b87aSKai Wang/* 9162de3b87aSKai Wang * Elf_Note structures comprise a fixed size header followed by variable 9172de3b87aSKai Wang * length strings. The fixed size header needs to be byte swapped, but 9182de3b87aSKai Wang * not the strings. 9192de3b87aSKai Wang * 9202de3b87aSKai Wang * Argument `count' denotes the total number of bytes to be converted. 9212de3b87aSKai Wang * The destination buffer needs to be at least `count' bytes in size. 9222de3b87aSKai Wang */ 9232de3b87aSKai Wangstatic int 924cf781b2eSEd Maste_libelf_cvt_NOTE_tom(unsigned char *dst, size_t dsz, unsigned char *src, 925cf781b2eSEd Maste size_t count, int byteswap) 9262de3b87aSKai Wang{ 9272de3b87aSKai Wang uint32_t namesz, descsz, type; 9282de3b87aSKai Wang Elf_Note *en; 9292de3b87aSKai Wang size_t sz, hdrsz; 9302de3b87aSKai Wang 9312de3b87aSKai Wang if (dsz < count) /* Destination buffer is too small. */ 9322de3b87aSKai Wang return (0); 9332de3b87aSKai Wang 9342de3b87aSKai Wang hdrsz = 3 * sizeof(uint32_t); 9352de3b87aSKai Wang if (count < hdrsz) /* Source too small. */ 9362de3b87aSKai Wang return (0); 9372de3b87aSKai Wang 9382de3b87aSKai Wang if (!byteswap) { 9392de3b87aSKai Wang (void) memcpy(dst, src, count); 9402de3b87aSKai Wang return (1); 9412de3b87aSKai Wang } 9422de3b87aSKai Wang 9432de3b87aSKai Wang /* Process all notes in the section. */ 9442de3b87aSKai Wang while (count > hdrsz) { 9452de3b87aSKai Wang /* Read the note header. */ 9462de3b87aSKai Wang READ_WORD(src, namesz); 9472de3b87aSKai Wang READ_WORD(src, descsz); 9482de3b87aSKai Wang READ_WORD(src, type); 9492de3b87aSKai Wang 9502de3b87aSKai Wang /* Translate. */ 9512de3b87aSKai Wang SWAP_WORD(namesz); 9522de3b87aSKai Wang SWAP_WORD(descsz); 9532de3b87aSKai Wang SWAP_WORD(type); 9542de3b87aSKai Wang 9552de3b87aSKai Wang /* Copy out the translated note header. */ 9562de3b87aSKai Wang en = (Elf_Note *) (uintptr_t) dst; 9572de3b87aSKai Wang en->n_namesz = namesz; 9582de3b87aSKai Wang en->n_descsz = descsz; 9592de3b87aSKai Wang en->n_type = type; 9602de3b87aSKai Wang 9612de3b87aSKai Wang dsz -= sizeof(Elf_Note); 9622de3b87aSKai Wang dst += sizeof(Elf_Note); 9632de3b87aSKai Wang count -= hdrsz; 9642de3b87aSKai Wang 965cf781b2eSEd Maste ROUNDUP2(namesz, 4U); 966cf781b2eSEd Maste ROUNDUP2(descsz, 4U); 967ccbdcd03SEd Maste 968ccbdcd03SEd Maste sz = namesz + descsz; 969ccbdcd03SEd Maste 9702de3b87aSKai Wang if (count < sz || dsz < sz) /* Buffers are too small. */ 9712de3b87aSKai Wang return (0); 9722de3b87aSKai Wang 9732de3b87aSKai Wang (void) memcpy(dst, src, sz); 9742de3b87aSKai Wang 9752de3b87aSKai Wang src += sz; 9762de3b87aSKai Wang dst += sz; 9772de3b87aSKai Wang 9782de3b87aSKai Wang count -= sz; 9792de3b87aSKai Wang dsz -= sz; 9802de3b87aSKai Wang } 9812de3b87aSKai Wang 9822de3b87aSKai Wang return (1); 9832de3b87aSKai Wang} 9842de3b87aSKai Wang 9852de3b87aSKai Wangstatic int 986cf781b2eSEd Maste_libelf_cvt_NOTE_tof(unsigned char *dst, size_t dsz, unsigned char *src, 987cf781b2eSEd Maste size_t count, int byteswap) 9882de3b87aSKai Wang{ 9892de3b87aSKai Wang uint32_t namesz, descsz, type; 9902de3b87aSKai Wang Elf_Note *en; 9912de3b87aSKai Wang size_t sz; 9922de3b87aSKai Wang 9932de3b87aSKai Wang if (dsz < count) 9942de3b87aSKai Wang return (0); 9952de3b87aSKai Wang 9962de3b87aSKai Wang if (!byteswap) { 9972de3b87aSKai Wang (void) memcpy(dst, src, count); 9982de3b87aSKai Wang return (1); 9992de3b87aSKai Wang } 10002de3b87aSKai Wang 10012de3b87aSKai Wang while (count > sizeof(Elf_Note)) { 10022de3b87aSKai Wang 10032de3b87aSKai Wang en = (Elf_Note *) (uintptr_t) src; 10042de3b87aSKai Wang namesz = en->n_namesz; 10052de3b87aSKai Wang descsz = en->n_descsz; 10062de3b87aSKai Wang type = en->n_type; 10072de3b87aSKai Wang 1008ccbdcd03SEd Maste sz = namesz; 1009cf781b2eSEd Maste ROUNDUP2(sz, 4U); 1010ccbdcd03SEd Maste sz += descsz; 1011cf781b2eSEd Maste ROUNDUP2(sz, 4U); 1012ccbdcd03SEd Maste 10132de3b87aSKai Wang SWAP_WORD(namesz); 10142de3b87aSKai Wang SWAP_WORD(descsz); 10152de3b87aSKai Wang SWAP_WORD(type); 10162de3b87aSKai Wang 10172de3b87aSKai Wang WRITE_WORD(dst, namesz); 10182de3b87aSKai Wang WRITE_WORD(dst, descsz); 10192de3b87aSKai Wang WRITE_WORD(dst, type); 10202de3b87aSKai Wang 10212de3b87aSKai Wang src += sizeof(Elf_Note); 1022a87342e8SEd Maste count -= sizeof(Elf_Note); 10232de3b87aSKai Wang 10242de3b87aSKai Wang if (count < sz) 10252f7242edSEd Maste return (0); 10262de3b87aSKai Wang 10272de3b87aSKai Wang (void) memcpy(dst, src, sz); 10282de3b87aSKai Wang 10292de3b87aSKai Wang src += sz; 10302de3b87aSKai Wang dst += sz; 10312de3b87aSKai Wang count -= sz; 10322de3b87aSKai Wang } 10332de3b87aSKai Wang 10342de3b87aSKai Wang return (1); 10352de3b87aSKai Wang} 10362de3b87aSKai Wang 10372de3b87aSKai Wangstruct converters { 1038cf781b2eSEd Maste int (*tof32)(unsigned char *dst, size_t dsz, unsigned char *src, 1039cf781b2eSEd Maste size_t cnt, int byteswap); 1040cf781b2eSEd Maste int (*tom32)(unsigned char *dst, size_t dsz, unsigned char *src, 1041cf781b2eSEd Maste size_t cnt, int byteswap); 1042cf781b2eSEd Maste int (*tof64)(unsigned char *dst, size_t dsz, unsigned char *src, 1043cf781b2eSEd Maste size_t cnt, int byteswap); 1044cf781b2eSEd Maste int (*tom64)(unsigned char *dst, size_t dsz, unsigned char *src, 1045cf781b2eSEd Maste size_t cnt, int byteswap); 10462de3b87aSKai Wang}; 10472de3b87aSKai Wang 10482de3b87aSKai Wang 10492de3b87aSKai Wangstatic struct converters cvt[ELF_T_NUM] = { 10502de3b87aSKai Wang /*[*/ 10512de3b87aSKai WangCONVERTER_NAMES(ELF_TYPE_LIST) 10522de3b87aSKai Wang /*]*/ 10532de3b87aSKai Wang 10542de3b87aSKai Wang /* 10552de3b87aSKai Wang * Types that need hand-coded converters follow. 10562de3b87aSKai Wang */ 10572de3b87aSKai Wang 10582de3b87aSKai Wang [ELF_T_BYTE] = { 10592de3b87aSKai Wang .tof32 = _libelf_cvt_BYTE_tox, 10602de3b87aSKai Wang .tom32 = _libelf_cvt_BYTE_tox, 10612de3b87aSKai Wang .tof64 = _libelf_cvt_BYTE_tox, 10622de3b87aSKai Wang .tom64 = _libelf_cvt_BYTE_tox 10632de3b87aSKai Wang }, 10642de3b87aSKai Wang 10652de3b87aSKai Wang [ELF_T_NOTE] = { 10662de3b87aSKai Wang .tof32 = _libelf_cvt_NOTE_tof, 10672de3b87aSKai Wang .tom32 = _libelf_cvt_NOTE_tom, 10682de3b87aSKai Wang .tof64 = _libelf_cvt_NOTE_tof, 10692de3b87aSKai Wang .tom64 = _libelf_cvt_NOTE_tom 10702de3b87aSKai Wang } 10712de3b87aSKai Wang}; 10722de3b87aSKai Wang 1073ae500c1fSEd Maste/* 1074ae500c1fSEd Maste * Return a translator function for the specified ELF section type, conversion 1075ae500c1fSEd Maste * direction, ELF class and ELF machine. 1076ae500c1fSEd Maste */ 1077ae500c1fSEd Maste_libelf_translator_function * 1078ae500c1fSEd Maste_libelf_get_translator(Elf_Type t, int direction, int elfclass, int elfmachine) 10792de3b87aSKai Wang{ 10802de3b87aSKai Wang assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); 10812de3b87aSKai Wang assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY); 1082d003e0d7SEd Maste assert(t >= ELF_T_FIRST && t <= ELF_T_LAST); 10832de3b87aSKai Wang 1084ae500c1fSEd Maste /* TODO: Handle MIPS64 REL{,A} sections (ticket #559). */ 1085ae500c1fSEd Maste (void) elfmachine; 1086ae500c1fSEd Maste 10872de3b87aSKai Wang return ((elfclass == ELFCLASS32) ? 10882de3b87aSKai Wang (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) : 10892de3b87aSKai Wang (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64)); 10902de3b87aSKai Wang} 1091