1*0a6a1f1dSLionel Sambuc/* $NetBSD: libelf_convert.m4,v 1.2 2014/03/09 16:58:04 christos Exp $ */ 2*0a6a1f1dSLionel Sambuc 3*0a6a1f1dSLionel Sambuc/*- 4*0a6a1f1dSLionel Sambuc * Copyright (c) 2006-2011 Joseph Koshy 5*0a6a1f1dSLionel Sambuc * All rights reserved. 6*0a6a1f1dSLionel Sambuc * 7*0a6a1f1dSLionel Sambuc * Redistribution and use in source and binary forms, with or without 8*0a6a1f1dSLionel Sambuc * modification, are permitted provided that the following conditions 9*0a6a1f1dSLionel Sambuc * are met: 10*0a6a1f1dSLionel Sambuc * 1. Redistributions of source code must retain the above copyright 11*0a6a1f1dSLionel Sambuc * notice, this list of conditions and the following disclaimer. 12*0a6a1f1dSLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright 13*0a6a1f1dSLionel Sambuc * notice, this list of conditions and the following disclaimer in the 14*0a6a1f1dSLionel Sambuc * documentation and/or other materials provided with the distribution. 15*0a6a1f1dSLionel Sambuc * 16*0a6a1f1dSLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17*0a6a1f1dSLionel Sambuc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18*0a6a1f1dSLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19*0a6a1f1dSLionel Sambuc * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20*0a6a1f1dSLionel Sambuc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21*0a6a1f1dSLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22*0a6a1f1dSLionel Sambuc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23*0a6a1f1dSLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24*0a6a1f1dSLionel Sambuc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25*0a6a1f1dSLionel Sambuc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26*0a6a1f1dSLionel Sambuc * SUCH DAMAGE. 27*0a6a1f1dSLionel Sambuc */ 28*0a6a1f1dSLionel Sambuc 29*0a6a1f1dSLionel Sambuc#if HAVE_NBTOOL_CONFIG_H 30*0a6a1f1dSLionel Sambuc# include "nbtool_config.h" 31*0a6a1f1dSLionel Sambuc#endif 32*0a6a1f1dSLionel Sambuc 33*0a6a1f1dSLionel Sambuc#include <sys/cdefs.h> 34*0a6a1f1dSLionel Sambuc 35*0a6a1f1dSLionel Sambuc#include <assert.h> 36*0a6a1f1dSLionel Sambuc#include <libelf.h> 37*0a6a1f1dSLionel Sambuc#include <string.h> 38*0a6a1f1dSLionel Sambuc 39*0a6a1f1dSLionel Sambuc#include "_libelf.h" 40*0a6a1f1dSLionel Sambuc 41*0a6a1f1dSLionel Sambuc__RCSID("$NetBSD: libelf_convert.m4,v 1.2 2014/03/09 16:58:04 christos Exp $"); 42*0a6a1f1dSLionel SambucELFTC_VCSID("Id: libelf_convert.m4 2361 2011-12-28 12:03:05Z jkoshy "); 43*0a6a1f1dSLionel Sambuc 44*0a6a1f1dSLionel Sambuc/* WARNING: GENERATED FROM __file__. */ 45*0a6a1f1dSLionel Sambuc 46*0a6a1f1dSLionel Sambucdivert(-1) 47*0a6a1f1dSLionel Sambuc 48*0a6a1f1dSLionel Sambuc# Generate conversion routines for converting between in-memory and 49*0a6a1f1dSLionel Sambuc# file representations of Elf data structures. 50*0a6a1f1dSLionel Sambuc# 51*0a6a1f1dSLionel Sambuc# These conversions use the type information defined in `elf_types.m4'. 52*0a6a1f1dSLionel Sambuc 53*0a6a1f1dSLionel Sambucinclude(SRCDIR`/elf_types.m4') 54*0a6a1f1dSLionel Sambuc 55*0a6a1f1dSLionel Sambuc# For the purposes of generating conversion code, ELF types may be 56*0a6a1f1dSLionel Sambuc# classified according to the following characteristics: 57*0a6a1f1dSLionel Sambuc# 58*0a6a1f1dSLionel Sambuc# 1. Whether the ELF type can be directly mapped to an integral C 59*0a6a1f1dSLionel Sambuc# language type. For example, the ELF_T_WORD type maps directly to 60*0a6a1f1dSLionel Sambuc# a 'uint32_t', but ELF_T_GNUHASH lacks a matching C type. 61*0a6a1f1dSLionel Sambuc# 62*0a6a1f1dSLionel Sambuc# 2. Whether the type has word size dependent variants. For example, 63*0a6a1f1dSLionel Sambuc# ELT_T_EHDR is represented using C types Elf32_Ehdr and El64_Ehdr, 64*0a6a1f1dSLionel Sambuc# and the ELF_T_ADDR and ELF_T_OFF types have integral C types that 65*0a6a1f1dSLionel Sambuc# can be 32- or 64- bit wide. 66*0a6a1f1dSLionel Sambuc# 67*0a6a1f1dSLionel Sambuc# 3. Whether the ELF types has a fixed representation or not. For 68*0a6a1f1dSLionel Sambuc# example, the ELF_T_SYM type has a fixed size file representation, 69*0a6a1f1dSLionel Sambuc# some types like ELF_T_NOTE and ELF_T_GNUHASH use a variable size 70*0a6a1f1dSLionel Sambuc# representation. 71*0a6a1f1dSLionel Sambuc# 72*0a6a1f1dSLionel Sambuc# We use m4 macros to generate conversion code for ELF types that have 73*0a6a1f1dSLionel Sambuc# a fixed size representation. Conversion functions for the remaining 74*0a6a1f1dSLionel Sambuc# types are coded by hand. 75*0a6a1f1dSLionel Sambuc# 76*0a6a1f1dSLionel Sambuc#* Handling File and Memory Representations 77*0a6a1f1dSLionel Sambuc# 78*0a6a1f1dSLionel Sambuc# `In-memory' representations of an Elf data structure use natural 79*0a6a1f1dSLionel Sambuc# alignments and native byte ordering. This allows pointer arithmetic 80*0a6a1f1dSLionel Sambuc# and casting to work as expected. On the other hand, the `file' 81*0a6a1f1dSLionel Sambuc# representation of an ELF data structure could possibly be packed 82*0a6a1f1dSLionel Sambuc# tighter than its `in-memory' representation, and could be of a 83*0a6a1f1dSLionel Sambuc# differing byte order. Reading ELF objects that are members of `ar' 84*0a6a1f1dSLionel Sambuc# archives present an additional complication: `ar' pads file data to 85*0a6a1f1dSLionel Sambuc# even addresses, so file data structures in an archive member 86*0a6a1f1dSLionel Sambuc# residing inside an `ar' archive could be at misaligned memory 87*0a6a1f1dSLionel Sambuc# addresses when brought into memory. 88*0a6a1f1dSLionel Sambuc# 89*0a6a1f1dSLionel Sambuc# In summary, casting the `char *' pointers that point to memory 90*0a6a1f1dSLionel Sambuc# representations (i.e., source pointers for the *_tof() functions and 91*0a6a1f1dSLionel Sambuc# the destination pointers for the *_tom() functions), is safe, as 92*0a6a1f1dSLionel Sambuc# these pointers should be correctly aligned for the memory type 93*0a6a1f1dSLionel Sambuc# already. However, pointers to file representations have to be 94*0a6a1f1dSLionel Sambuc# treated as being potentially unaligned and no casting can be done. 95*0a6a1f1dSLionel Sambuc 96*0a6a1f1dSLionel Sambuc# NOCVT(TYPE) -- Do not generate the cvt[] structure entry for TYPE 97*0a6a1f1dSLionel Sambucdefine(`NOCVT',`define(`NOCVT_'$1,1)') 98*0a6a1f1dSLionel Sambuc 99*0a6a1f1dSLionel Sambuc# NOFUNC(TYPE) -- Do not generate a conversion function for TYPE 100*0a6a1f1dSLionel Sambucdefine(`NOFUNC',`define(`NOFUNC_'$1,1)') 101*0a6a1f1dSLionel Sambuc 102*0a6a1f1dSLionel Sambuc# IGNORE(TYPE) -- Completely ignore the type. 103*0a6a1f1dSLionel Sambucdefine(`IGNORE',`NOCVT($1)NOFUNC($1)') 104*0a6a1f1dSLionel Sambuc 105*0a6a1f1dSLionel Sambuc# Mark ELF types that should not be processed by the M4 macros below. 106*0a6a1f1dSLionel Sambuc 107*0a6a1f1dSLionel Sambuc# Types for which we use functions with non-standard names. 108*0a6a1f1dSLionel SambucIGNORE(`BYTE') # Uses a wrapper around memcpy(). 109*0a6a1f1dSLionel SambucIGNORE(`NOTE') # Not a fixed size type. 110*0a6a1f1dSLionel Sambuc 111*0a6a1f1dSLionel Sambuc# Types for which we supply hand-coded functions. 112*0a6a1f1dSLionel SambucNOFUNC(`GNUHASH') # A type with complex internal structure. 113*0a6a1f1dSLionel SambucNOFUNC(`VDEF') # See MAKE_VERSION_CONVERTERS below. 114*0a6a1f1dSLionel SambucNOFUNC(`VNEED') # .. 115*0a6a1f1dSLionel Sambuc 116*0a6a1f1dSLionel Sambuc# Unimplemented types. 117*0a6a1f1dSLionel SambucIGNORE(`MOVEP') 118*0a6a1f1dSLionel Sambuc 119*0a6a1f1dSLionel Sambuc# ELF types that don't exist in a 32-bit world. 120*0a6a1f1dSLionel SambucNOFUNC(`XWORD32') 121*0a6a1f1dSLionel SambucNOFUNC(`SXWORD32') 122*0a6a1f1dSLionel Sambuc 123*0a6a1f1dSLionel Sambuc# `Primitive' ELF types are those that are an alias for an integral 124*0a6a1f1dSLionel Sambuc# type. As they have no internal structure, they can be copied using 125*0a6a1f1dSLionel Sambuc# a `memcpy()', and byteswapped in straightforward way. 126*0a6a1f1dSLionel Sambuc# 127*0a6a1f1dSLionel Sambuc# Mark all ELF types that directly map to integral C types. 128*0a6a1f1dSLionel Sambucdefine(`PRIM_ADDR', 1) 129*0a6a1f1dSLionel Sambucdefine(`PRIM_BYTE', 1) 130*0a6a1f1dSLionel Sambucdefine(`PRIM_HALF', 1) 131*0a6a1f1dSLionel Sambucdefine(`PRIM_LWORD', 1) 132*0a6a1f1dSLionel Sambucdefine(`PRIM_OFF', 1) 133*0a6a1f1dSLionel Sambucdefine(`PRIM_SWORD', 1) 134*0a6a1f1dSLionel Sambucdefine(`PRIM_SXWORD', 1) 135*0a6a1f1dSLionel Sambucdefine(`PRIM_WORD', 1) 136*0a6a1f1dSLionel Sambucdefine(`PRIM_XWORD', 1) 137*0a6a1f1dSLionel Sambuc 138*0a6a1f1dSLionel Sambuc# Note the primitive types that are size-dependent. 139*0a6a1f1dSLionel Sambucdefine(`SIZEDEP_ADDR', 1) 140*0a6a1f1dSLionel Sambucdefine(`SIZEDEP_OFF', 1) 141*0a6a1f1dSLionel Sambuc 142*0a6a1f1dSLionel Sambuc# Generate conversion functions for primitive types. 143*0a6a1f1dSLionel Sambuc# 144*0a6a1f1dSLionel Sambuc# Macro use: MAKEPRIMFUNCS(ELFTYPE,CTYPE,TYPESIZE,SYMSIZE) 145*0a6a1f1dSLionel Sambuc# `$1': Name of the ELF type. 146*0a6a1f1dSLionel Sambuc# `$2': C structure name suffix. 147*0a6a1f1dSLionel Sambuc# `$3': ELF class specifier for types, one of [`32', `64']. 148*0a6a1f1dSLionel Sambuc# `$4': Additional ELF class specifier, one of [`', `32', `64']. 149*0a6a1f1dSLionel Sambuc# 150*0a6a1f1dSLionel Sambuc# Generates a pair of conversion functions. 151*0a6a1f1dSLionel Sambucdefine(`MAKEPRIMFUNCS',` 152*0a6a1f1dSLionel Sambucstatic int 153*0a6a1f1dSLionel Sambuc_libelf_cvt_$1$4_tof(char *dst, size_t dsz, char *src, size_t count, 154*0a6a1f1dSLionel Sambuc int byteswap) 155*0a6a1f1dSLionel Sambuc{ 156*0a6a1f1dSLionel Sambuc Elf$3_$2 t, *s = (Elf$3_$2 *) (uintptr_t) src; 157*0a6a1f1dSLionel Sambuc size_t c; 158*0a6a1f1dSLionel Sambuc 159*0a6a1f1dSLionel Sambuc (void) dsz; 160*0a6a1f1dSLionel Sambuc 161*0a6a1f1dSLionel Sambuc if (!byteswap) { 162*0a6a1f1dSLionel Sambuc (void) memcpy(dst, src, count * sizeof(*s)); 163*0a6a1f1dSLionel Sambuc return (1); 164*0a6a1f1dSLionel Sambuc } 165*0a6a1f1dSLionel Sambuc 166*0a6a1f1dSLionel Sambuc for (c = 0; c < count; c++) { 167*0a6a1f1dSLionel Sambuc t = *s++; 168*0a6a1f1dSLionel Sambuc SWAP_$1$4(t); 169*0a6a1f1dSLionel Sambuc WRITE_$1$4(dst,t); 170*0a6a1f1dSLionel Sambuc } 171*0a6a1f1dSLionel Sambuc 172*0a6a1f1dSLionel Sambuc return (1); 173*0a6a1f1dSLionel Sambuc} 174*0a6a1f1dSLionel Sambuc 175*0a6a1f1dSLionel Sambucstatic int 176*0a6a1f1dSLionel Sambuc_libelf_cvt_$1$4_tom(char *dst, size_t dsz, char *src, size_t count, 177*0a6a1f1dSLionel Sambuc int byteswap) 178*0a6a1f1dSLionel Sambuc{ 179*0a6a1f1dSLionel Sambuc Elf$3_$2 t, *d = (Elf$3_$2 *) (uintptr_t) dst; 180*0a6a1f1dSLionel Sambuc size_t c; 181*0a6a1f1dSLionel Sambuc 182*0a6a1f1dSLionel Sambuc if (dsz < count * sizeof(Elf$3_$2)) 183*0a6a1f1dSLionel Sambuc return (0); 184*0a6a1f1dSLionel Sambuc 185*0a6a1f1dSLionel Sambuc if (!byteswap) { 186*0a6a1f1dSLionel Sambuc (void) memcpy(dst, src, count * sizeof(*d)); 187*0a6a1f1dSLionel Sambuc return (1); 188*0a6a1f1dSLionel Sambuc } 189*0a6a1f1dSLionel Sambuc 190*0a6a1f1dSLionel Sambuc for (c = 0; c < count; c++) { 191*0a6a1f1dSLionel Sambuc READ_$1$4(src,t); 192*0a6a1f1dSLionel Sambuc SWAP_$1$4(t); 193*0a6a1f1dSLionel Sambuc *d++ = t; 194*0a6a1f1dSLionel Sambuc } 195*0a6a1f1dSLionel Sambuc 196*0a6a1f1dSLionel Sambuc return (1); 197*0a6a1f1dSLionel Sambuc} 198*0a6a1f1dSLionel Sambuc') 199*0a6a1f1dSLionel Sambuc 200*0a6a1f1dSLionel Sambuc# 201*0a6a1f1dSLionel Sambuc# Handling composite ELF types 202*0a6a1f1dSLionel Sambuc# 203*0a6a1f1dSLionel Sambuc 204*0a6a1f1dSLionel Sambuc# SWAP_FIELD(FIELDNAME,ELFTYPE) -- Generate code to swap one field. 205*0a6a1f1dSLionel Sambucdefine(`SWAP_FIELD', 206*0a6a1f1dSLionel Sambuc `ifdef(`SIZEDEP_'$2, 207*0a6a1f1dSLionel Sambuc `SWAP_$2'SZ()`(t.$1); 208*0a6a1f1dSLionel Sambuc ', 209*0a6a1f1dSLionel Sambuc `SWAP_$2(t.$1); 210*0a6a1f1dSLionel Sambuc ')') 211*0a6a1f1dSLionel Sambuc 212*0a6a1f1dSLionel Sambuc# SWAP_MEMBERS(STRUCT) -- Iterate over a structure definition. 213*0a6a1f1dSLionel Sambucdefine(`SWAP_MEMBERS', 214*0a6a1f1dSLionel Sambuc `ifelse($#,1,`/**/', 215*0a6a1f1dSLionel Sambuc `SWAP_FIELD($1)SWAP_MEMBERS(shift($@))')') 216*0a6a1f1dSLionel Sambuc 217*0a6a1f1dSLionel Sambuc# SWAP_STRUCT(CTYPE,SIZE) -- Generate code to swap an ELF structure. 218*0a6a1f1dSLionel Sambucdefine(`SWAP_STRUCT', 219*0a6a1f1dSLionel Sambuc `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */ 220*0a6a1f1dSLionel Sambuc SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') 221*0a6a1f1dSLionel Sambuc 222*0a6a1f1dSLionel Sambuc# WRITE_FIELD(ELFTYPE,FIELDNAME) -- Generate code to write one field. 223*0a6a1f1dSLionel Sambucdefine(`WRITE_FIELD', 224*0a6a1f1dSLionel Sambuc `ifdef(`SIZEDEP_'$2, 225*0a6a1f1dSLionel Sambuc `WRITE_$2'SZ()`(dst,t.$1); 226*0a6a1f1dSLionel Sambuc ', 227*0a6a1f1dSLionel Sambuc `WRITE_$2(dst,t.$1); 228*0a6a1f1dSLionel Sambuc ')') 229*0a6a1f1dSLionel Sambuc 230*0a6a1f1dSLionel Sambuc# WRITE_MEMBERS(ELFTYPELIST) -- Iterate over a structure definition. 231*0a6a1f1dSLionel Sambucdefine(`WRITE_MEMBERS', 232*0a6a1f1dSLionel Sambuc `ifelse($#,1,`/**/', 233*0a6a1f1dSLionel Sambuc `WRITE_FIELD($1)WRITE_MEMBERS(shift($@))')') 234*0a6a1f1dSLionel Sambuc 235*0a6a1f1dSLionel Sambuc# WRITE_STRUCT(CTYPE,SIZE) -- Generate code to write out an ELF structure. 236*0a6a1f1dSLionel Sambucdefine(`WRITE_STRUCT', 237*0a6a1f1dSLionel Sambuc `pushdef(`SZ',$2)/* Write an Elf$2_$1 */ 238*0a6a1f1dSLionel Sambuc WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') 239*0a6a1f1dSLionel Sambuc 240*0a6a1f1dSLionel Sambuc# READ_FIELD(ELFTYPE,CTYPE) -- Generate code to read one field. 241*0a6a1f1dSLionel Sambucdefine(`READ_FIELD', 242*0a6a1f1dSLionel Sambuc `ifdef(`SIZEDEP_'$2, 243*0a6a1f1dSLionel Sambuc `READ_$2'SZ()`(s,t.$1); 244*0a6a1f1dSLionel Sambuc ', 245*0a6a1f1dSLionel Sambuc `READ_$2(s,t.$1); 246*0a6a1f1dSLionel Sambuc ')') 247*0a6a1f1dSLionel Sambuc 248*0a6a1f1dSLionel Sambuc# READ_MEMBERS(ELFTYPELIST) -- Iterate over a structure definition. 249*0a6a1f1dSLionel Sambucdefine(`READ_MEMBERS', 250*0a6a1f1dSLionel Sambuc `ifelse($#,1,`/**/', 251*0a6a1f1dSLionel Sambuc `READ_FIELD($1)READ_MEMBERS(shift($@))')') 252*0a6a1f1dSLionel Sambuc 253*0a6a1f1dSLionel Sambuc# READ_STRUCT(CTYPE,SIZE) -- Generate code to read an ELF structure. 254*0a6a1f1dSLionel Sambucdefine(`READ_STRUCT', 255*0a6a1f1dSLionel Sambuc `pushdef(`SZ',$2)/* Read an Elf$2_$1 */ 256*0a6a1f1dSLionel Sambuc READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') 257*0a6a1f1dSLionel Sambuc 258*0a6a1f1dSLionel Sambuc 259*0a6a1f1dSLionel Sambuc# MAKECOMPFUNCS -- Generate converters for composite ELF structures. 260*0a6a1f1dSLionel Sambuc# 261*0a6a1f1dSLionel Sambuc# When converting data to file representation, the source pointer will 262*0a6a1f1dSLionel Sambuc# be naturally aligned for a data structure's in-memory 263*0a6a1f1dSLionel Sambuc# representation. When converting data to memory, the destination 264*0a6a1f1dSLionel Sambuc# pointer will be similarly aligned. 265*0a6a1f1dSLionel Sambuc# 266*0a6a1f1dSLionel Sambuc# For in-place conversions, when converting to file representations, 267*0a6a1f1dSLionel Sambuc# the source buffer is large enough to hold `file' data. When 268*0a6a1f1dSLionel Sambuc# converting from file to memory, we need to be careful to work 269*0a6a1f1dSLionel Sambuc# `backwards', to avoid overwriting unconverted data. 270*0a6a1f1dSLionel Sambuc# 271*0a6a1f1dSLionel Sambuc# Macro use: 272*0a6a1f1dSLionel Sambuc# `$1': Name of the ELF type. 273*0a6a1f1dSLionel Sambuc# `$2': C structure name suffix. 274*0a6a1f1dSLionel Sambuc# `$3': ELF class specifier, one of [`', `32', `64'] 275*0a6a1f1dSLionel Sambucdefine(`MAKECOMPFUNCS', `ifdef(`NOFUNC_'$1$3,`',` 276*0a6a1f1dSLionel Sambucstatic int 277*0a6a1f1dSLionel Sambuc_libelf_cvt_$1$3_tof(char *dst, size_t dsz, char *src, size_t count, 278*0a6a1f1dSLionel Sambuc int byteswap) 279*0a6a1f1dSLionel Sambuc{ 280*0a6a1f1dSLionel Sambuc Elf$3_$2 t, *s; 281*0a6a1f1dSLionel Sambuc size_t c; 282*0a6a1f1dSLionel Sambuc 283*0a6a1f1dSLionel Sambuc (void) dsz; 284*0a6a1f1dSLionel Sambuc 285*0a6a1f1dSLionel Sambuc s = (Elf$3_$2 *) (uintptr_t) src; 286*0a6a1f1dSLionel Sambuc for (c = 0; c < count; c++) { 287*0a6a1f1dSLionel Sambuc t = *s++; 288*0a6a1f1dSLionel Sambuc if (byteswap) { 289*0a6a1f1dSLionel Sambuc SWAP_STRUCT($2,$3) 290*0a6a1f1dSLionel Sambuc } 291*0a6a1f1dSLionel Sambuc WRITE_STRUCT($2,$3) 292*0a6a1f1dSLionel Sambuc } 293*0a6a1f1dSLionel Sambuc 294*0a6a1f1dSLionel Sambuc return (1); 295*0a6a1f1dSLionel Sambuc} 296*0a6a1f1dSLionel Sambuc 297*0a6a1f1dSLionel Sambucstatic int 298*0a6a1f1dSLionel Sambuc_libelf_cvt_$1$3_tom(char *dst, size_t dsz, char *src, size_t count, 299*0a6a1f1dSLionel Sambuc int byteswap) 300*0a6a1f1dSLionel Sambuc{ 301*0a6a1f1dSLionel Sambuc Elf$3_$2 t, *d; 302*0a6a1f1dSLionel Sambuc char *s,*s0; 303*0a6a1f1dSLionel Sambuc size_t fsz; 304*0a6a1f1dSLionel Sambuc 305*0a6a1f1dSLionel Sambuc fsz = elf$3_fsize(ELF_T_$1, (size_t) 1, EV_CURRENT); 306*0a6a1f1dSLionel Sambuc d = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1); 307*0a6a1f1dSLionel Sambuc s0 = (char *) src + (count - 1) * fsz; 308*0a6a1f1dSLionel Sambuc 309*0a6a1f1dSLionel Sambuc if (dsz < count * sizeof(Elf$3_$2)) 310*0a6a1f1dSLionel Sambuc return (0); 311*0a6a1f1dSLionel Sambuc 312*0a6a1f1dSLionel Sambuc while (count--) { 313*0a6a1f1dSLionel Sambuc s = s0; 314*0a6a1f1dSLionel Sambuc READ_STRUCT($2,$3) 315*0a6a1f1dSLionel Sambuc if (byteswap) { 316*0a6a1f1dSLionel Sambuc SWAP_STRUCT($2,$3) 317*0a6a1f1dSLionel Sambuc } 318*0a6a1f1dSLionel Sambuc *d-- = t; s0 -= fsz; 319*0a6a1f1dSLionel Sambuc } 320*0a6a1f1dSLionel Sambuc 321*0a6a1f1dSLionel Sambuc return (1); 322*0a6a1f1dSLionel Sambuc} 323*0a6a1f1dSLionel Sambuc')') 324*0a6a1f1dSLionel Sambuc 325*0a6a1f1dSLionel Sambuc# MAKE_TYPE_CONVERTER(ELFTYPE,CTYPE) 326*0a6a1f1dSLionel Sambuc# 327*0a6a1f1dSLionel Sambuc# Make type convertor functions from the type definition 328*0a6a1f1dSLionel Sambuc# of the ELF type: 329*0a6a1f1dSLionel Sambuc# - Skip convertors marked as `NOFUNC'. 330*0a6a1f1dSLionel Sambuc# - Invoke `MAKEPRIMFUNCS' or `MAKECOMPFUNCS' as appropriate. 331*0a6a1f1dSLionel Sambucdefine(`MAKE_TYPE_CONVERTER', 332*0a6a1f1dSLionel Sambuc `ifdef(`NOFUNC_'$1,`', 333*0a6a1f1dSLionel Sambuc `ifdef(`PRIM_'$1, 334*0a6a1f1dSLionel Sambuc `ifdef(`SIZEDEP_'$1, 335*0a6a1f1dSLionel Sambuc `MAKEPRIMFUNCS($1,$2,32,32)dnl 336*0a6a1f1dSLionel Sambuc MAKEPRIMFUNCS($1,$2,64,64)', 337*0a6a1f1dSLionel Sambuc `MAKEPRIMFUNCS($1,$2,64)')', 338*0a6a1f1dSLionel Sambuc `MAKECOMPFUNCS($1,$2,32)dnl 339*0a6a1f1dSLionel Sambuc MAKECOMPFUNCS($1,$2,64)')')') 340*0a6a1f1dSLionel Sambuc 341*0a6a1f1dSLionel Sambuc# MAKE_TYPE_CONVERTERS(ELFTYPELIST) -- Generate conversion functions. 342*0a6a1f1dSLionel Sambucdefine(`MAKE_TYPE_CONVERTERS', 343*0a6a1f1dSLionel Sambuc `ifelse($#,1,`', 344*0a6a1f1dSLionel Sambuc `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')') 345*0a6a1f1dSLionel Sambuc 346*0a6a1f1dSLionel Sambuc 347*0a6a1f1dSLionel Sambuc# 348*0a6a1f1dSLionel Sambuc# Macros to generate entries for the table of convertors. 349*0a6a1f1dSLionel Sambuc# 350*0a6a1f1dSLionel Sambuc 351*0a6a1f1dSLionel Sambuc# CONV(ELFTYPE,SIZE,DIRECTION) 352*0a6a1f1dSLionel Sambuc# 353*0a6a1f1dSLionel Sambuc# Generate the name of a convertor function. 354*0a6a1f1dSLionel Sambucdefine(`CONV', 355*0a6a1f1dSLionel Sambuc `ifdef(`NOFUNC_'$1$2, 356*0a6a1f1dSLionel Sambuc `.$3$2 = NULL', 357*0a6a1f1dSLionel Sambuc `ifdef(`PRIM_'$1, 358*0a6a1f1dSLionel Sambuc `ifdef(`SIZEDEP_'$1, 359*0a6a1f1dSLionel Sambuc `.$3$2 = _libelf_cvt_$1$2_$3', 360*0a6a1f1dSLionel Sambuc `.$3$2 = _libelf_cvt_$1_$3')', 361*0a6a1f1dSLionel Sambuc `.$3$2 = _libelf_cvt_$1$2_$3')')') 362*0a6a1f1dSLionel Sambuc 363*0a6a1f1dSLionel Sambuc# CONVERTER_NAME(ELFTYPE) 364*0a6a1f1dSLionel Sambuc# 365*0a6a1f1dSLionel Sambuc# Generate the contents of one `struct cvt' instance. 366*0a6a1f1dSLionel Sambucdefine(`CONVERTER_NAME', 367*0a6a1f1dSLionel Sambuc `ifdef(`NOCVT_'$1,`', 368*0a6a1f1dSLionel Sambuc ` [ELF_T_$1] = { 369*0a6a1f1dSLionel Sambuc CONV($1,32,tof), 370*0a6a1f1dSLionel Sambuc CONV($1,32,tom), 371*0a6a1f1dSLionel Sambuc CONV($1,64,tof), 372*0a6a1f1dSLionel Sambuc CONV($1,64,tom) 373*0a6a1f1dSLionel Sambuc }, 374*0a6a1f1dSLionel Sambuc 375*0a6a1f1dSLionel Sambuc')') 376*0a6a1f1dSLionel Sambuc 377*0a6a1f1dSLionel Sambuc# CONVERTER_NAMES(ELFTYPELIST) 378*0a6a1f1dSLionel Sambuc# 379*0a6a1f1dSLionel Sambuc# Generate the `struct cvt[]' array. 380*0a6a1f1dSLionel Sambucdefine(`CONVERTER_NAMES', 381*0a6a1f1dSLionel Sambuc `ifelse($#,1,`', 382*0a6a1f1dSLionel Sambuc `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')') 383*0a6a1f1dSLionel Sambuc 384*0a6a1f1dSLionel Sambuc# 385*0a6a1f1dSLionel Sambuc# Handling ELF version sections. 386*0a6a1f1dSLionel Sambuc# 387*0a6a1f1dSLionel Sambuc 388*0a6a1f1dSLionel Sambuc# _FSZ(FIELD,BASETYPE) - return the file size for a field. 389*0a6a1f1dSLionel Sambucdefine(`_FSZ', 390*0a6a1f1dSLionel Sambuc `ifelse($2,`HALF',2, 391*0a6a1f1dSLionel Sambuc $2,`WORD',4)') 392*0a6a1f1dSLionel Sambuc 393*0a6a1f1dSLionel Sambuc# FSZ(STRUCT) - determine the file size of a structure. 394*0a6a1f1dSLionel Sambucdefine(`FSZ', 395*0a6a1f1dSLionel Sambuc `ifelse($#,1,0, 396*0a6a1f1dSLionel Sambuc `eval(_FSZ($1) + FSZ(shift($@)))')') 397*0a6a1f1dSLionel Sambuc 398*0a6a1f1dSLionel Sambuc# MAKE_VERSION_CONVERTERS(TYPE,BASE,AUX,PFX) -- Generate conversion 399*0a6a1f1dSLionel Sambuc# functions for versioning structures. 400*0a6a1f1dSLionel Sambucdefine(`MAKE_VERSION_CONVERTERS', 401*0a6a1f1dSLionel Sambuc `MAKE_VERSION_CONVERTER($1,$2,$3,$4,32) 402*0a6a1f1dSLionel Sambuc MAKE_VERSION_CONVERTER($1,$2,$3,$4,64)') 403*0a6a1f1dSLionel Sambuc 404*0a6a1f1dSLionel Sambuc# MAKE_VERSION_CONVERTOR(TYPE,CBASE,CAUX,PFX,SIZE) -- Generate a 405*0a6a1f1dSLionel Sambuc# conversion function. 406*0a6a1f1dSLionel Sambucdefine(`MAKE_VERSION_CONVERTER',` 407*0a6a1f1dSLionel Sambucstatic int 408*0a6a1f1dSLionel Sambuc_libelf_cvt_$1$5_tof(char *dst, size_t dsz, char *src, size_t count, 409*0a6a1f1dSLionel Sambuc int byteswap) 410*0a6a1f1dSLionel Sambuc{ 411*0a6a1f1dSLionel Sambuc Elf$5_$2 t; 412*0a6a1f1dSLionel Sambuc Elf$5_$3 a; 413*0a6a1f1dSLionel Sambuc const size_t verfsz = FSZ(Elf$5_$2_DEF); 414*0a6a1f1dSLionel Sambuc const size_t auxfsz = FSZ(Elf$5_$3_DEF); 415*0a6a1f1dSLionel Sambuc const size_t vermsz = sizeof(Elf$5_$2); 416*0a6a1f1dSLionel Sambuc const size_t auxmsz = sizeof(Elf$5_$3); 417*0a6a1f1dSLionel Sambuc char * const dstend = dst + dsz; 418*0a6a1f1dSLionel Sambuc char * const srcend = src + count; 419*0a6a1f1dSLionel Sambuc char *dtmp, *dstaux, *srcaux; 420*0a6a1f1dSLionel Sambuc Elf$5_Word aux, anext, cnt, vnext; 421*0a6a1f1dSLionel Sambuc 422*0a6a1f1dSLionel Sambuc for (dtmp = dst, vnext = ~0; 423*0a6a1f1dSLionel Sambuc vnext != 0 && dtmp + verfsz <= dstend && src + vermsz <= srcend; 424*0a6a1f1dSLionel Sambuc dtmp += vnext, src += vnext) { 425*0a6a1f1dSLionel Sambuc 426*0a6a1f1dSLionel Sambuc /* Read in an Elf$5_$2 structure. */ 427*0a6a1f1dSLionel Sambuc t = *((Elf$5_$2 *) (uintptr_t) src); 428*0a6a1f1dSLionel Sambuc 429*0a6a1f1dSLionel Sambuc aux = t.$4_aux; 430*0a6a1f1dSLionel Sambuc cnt = t.$4_cnt; 431*0a6a1f1dSLionel Sambuc vnext = t.$4_next; 432*0a6a1f1dSLionel Sambuc 433*0a6a1f1dSLionel Sambuc if (byteswap) { 434*0a6a1f1dSLionel Sambuc SWAP_STRUCT($2, $5) 435*0a6a1f1dSLionel Sambuc } 436*0a6a1f1dSLionel Sambuc 437*0a6a1f1dSLionel Sambuc dst = dtmp; 438*0a6a1f1dSLionel Sambuc WRITE_STRUCT($2, $5) 439*0a6a1f1dSLionel Sambuc 440*0a6a1f1dSLionel Sambuc if (aux < verfsz) 441*0a6a1f1dSLionel Sambuc return (0); 442*0a6a1f1dSLionel Sambuc 443*0a6a1f1dSLionel Sambuc /* Process AUX entries. */ 444*0a6a1f1dSLionel Sambuc for (anext = ~0, dstaux = dtmp + aux, srcaux = src + aux; 445*0a6a1f1dSLionel Sambuc cnt != 0 && anext != 0 && dstaux + auxfsz <= dstend && 446*0a6a1f1dSLionel Sambuc srcaux + auxmsz <= srcend; 447*0a6a1f1dSLionel Sambuc dstaux += anext, srcaux += anext, cnt--) { 448*0a6a1f1dSLionel Sambuc 449*0a6a1f1dSLionel Sambuc /* Read in an Elf$5_$3 structure. */ 450*0a6a1f1dSLionel Sambuc a = *((Elf$5_$3 *) (uintptr_t) srcaux); 451*0a6a1f1dSLionel Sambuc anext = a.$4a_next; 452*0a6a1f1dSLionel Sambuc 453*0a6a1f1dSLionel Sambuc if (byteswap) { 454*0a6a1f1dSLionel Sambuc pushdef(`t',`a')SWAP_STRUCT($3, $5)popdef(`t') 455*0a6a1f1dSLionel Sambuc } 456*0a6a1f1dSLionel Sambuc 457*0a6a1f1dSLionel Sambuc dst = dstaux; 458*0a6a1f1dSLionel Sambuc pushdef(`t',`a')WRITE_STRUCT($3, $5)popdef(`t') 459*0a6a1f1dSLionel Sambuc } 460*0a6a1f1dSLionel Sambuc 461*0a6a1f1dSLionel Sambuc if (anext || cnt) 462*0a6a1f1dSLionel Sambuc return (0); 463*0a6a1f1dSLionel Sambuc } 464*0a6a1f1dSLionel Sambuc 465*0a6a1f1dSLionel Sambuc if (vnext) 466*0a6a1f1dSLionel Sambuc return (0); 467*0a6a1f1dSLionel Sambuc 468*0a6a1f1dSLionel Sambuc return (1); 469*0a6a1f1dSLionel Sambuc} 470*0a6a1f1dSLionel Sambuc 471*0a6a1f1dSLionel Sambucstatic int 472*0a6a1f1dSLionel Sambuc_libelf_cvt_$1$5_tom(char *dst, size_t dsz, char *src, size_t count, 473*0a6a1f1dSLionel Sambuc int byteswap) 474*0a6a1f1dSLionel Sambuc{ 475*0a6a1f1dSLionel Sambuc Elf$5_$2 t, *dp; 476*0a6a1f1dSLionel Sambuc Elf$5_$3 a, *ap; 477*0a6a1f1dSLionel Sambuc const size_t verfsz = FSZ(Elf$5_$2_DEF); 478*0a6a1f1dSLionel Sambuc const size_t auxfsz = FSZ(Elf$5_$3_DEF); 479*0a6a1f1dSLionel Sambuc const size_t vermsz = sizeof(Elf$5_$2); 480*0a6a1f1dSLionel Sambuc const size_t auxmsz = sizeof(Elf$5_$3); 481*0a6a1f1dSLionel Sambuc char * const dstend = dst + dsz; 482*0a6a1f1dSLionel Sambuc char * const srcend = src + count; 483*0a6a1f1dSLionel Sambuc char *dstaux, *s, *srcaux, *stmp; 484*0a6a1f1dSLionel Sambuc Elf$5_Word aux, anext, cnt, vnext; 485*0a6a1f1dSLionel Sambuc 486*0a6a1f1dSLionel Sambuc for (stmp = src, vnext = ~0; 487*0a6a1f1dSLionel Sambuc vnext != 0 && stmp + verfsz <= srcend && dst + vermsz <= dstend; 488*0a6a1f1dSLionel Sambuc stmp += vnext, dst += vnext) { 489*0a6a1f1dSLionel Sambuc 490*0a6a1f1dSLionel Sambuc /* Read in a $1 structure. */ 491*0a6a1f1dSLionel Sambuc s = stmp; 492*0a6a1f1dSLionel Sambuc READ_STRUCT($2, $5) 493*0a6a1f1dSLionel Sambuc if (byteswap) { 494*0a6a1f1dSLionel Sambuc SWAP_STRUCT($2, $5) 495*0a6a1f1dSLionel Sambuc } 496*0a6a1f1dSLionel Sambuc 497*0a6a1f1dSLionel Sambuc dp = (Elf$5_$2 *) (uintptr_t) dst; 498*0a6a1f1dSLionel Sambuc *dp = t; 499*0a6a1f1dSLionel Sambuc 500*0a6a1f1dSLionel Sambuc aux = t.$4_aux; 501*0a6a1f1dSLionel Sambuc cnt = t.$4_cnt; 502*0a6a1f1dSLionel Sambuc vnext = t.$4_next; 503*0a6a1f1dSLionel Sambuc 504*0a6a1f1dSLionel Sambuc if (aux < vermsz) 505*0a6a1f1dSLionel Sambuc return (0); 506*0a6a1f1dSLionel Sambuc 507*0a6a1f1dSLionel Sambuc /* Process AUX entries. */ 508*0a6a1f1dSLionel Sambuc for (anext = ~0, dstaux = dst + aux, srcaux = stmp + aux; 509*0a6a1f1dSLionel Sambuc cnt != 0 && anext != 0 && dstaux + auxmsz <= dstend && 510*0a6a1f1dSLionel Sambuc srcaux + auxfsz <= srcend; 511*0a6a1f1dSLionel Sambuc dstaux += anext, srcaux += anext, cnt--) { 512*0a6a1f1dSLionel Sambuc 513*0a6a1f1dSLionel Sambuc s = srcaux; 514*0a6a1f1dSLionel Sambuc pushdef(`t',`a')READ_STRUCT($3, $5)popdef(`t') 515*0a6a1f1dSLionel Sambuc 516*0a6a1f1dSLionel Sambuc if (byteswap) { 517*0a6a1f1dSLionel Sambuc pushdef(`t',`a')SWAP_STRUCT($3, $5)popdef(`t') 518*0a6a1f1dSLionel Sambuc } 519*0a6a1f1dSLionel Sambuc 520*0a6a1f1dSLionel Sambuc anext = a.$4a_next; 521*0a6a1f1dSLionel Sambuc 522*0a6a1f1dSLionel Sambuc ap = ((Elf$5_$3 *) (uintptr_t) dstaux); 523*0a6a1f1dSLionel Sambuc *ap = a; 524*0a6a1f1dSLionel Sambuc } 525*0a6a1f1dSLionel Sambuc 526*0a6a1f1dSLionel Sambuc if (anext || cnt) 527*0a6a1f1dSLionel Sambuc return (0); 528*0a6a1f1dSLionel Sambuc } 529*0a6a1f1dSLionel Sambuc 530*0a6a1f1dSLionel Sambuc if (vnext) 531*0a6a1f1dSLionel Sambuc return (0); 532*0a6a1f1dSLionel Sambuc 533*0a6a1f1dSLionel Sambuc return (1); 534*0a6a1f1dSLionel Sambuc}') 535*0a6a1f1dSLionel Sambuc 536*0a6a1f1dSLionel Sambucdivert(0) 537*0a6a1f1dSLionel Sambuc 538*0a6a1f1dSLionel Sambuc/* 539*0a6a1f1dSLionel Sambuc * C macros to byte swap integral quantities. 540*0a6a1f1dSLionel Sambuc */ 541*0a6a1f1dSLionel Sambuc 542*0a6a1f1dSLionel Sambuc#define SWAP_BYTE(X) do { (void) (X); } while (0) 543*0a6a1f1dSLionel Sambuc#define SWAP_IDENT(X) do { (void) (X); } while (0) 544*0a6a1f1dSLionel Sambuc#define SWAP_HALF(X) do { \ 545*0a6a1f1dSLionel Sambuc uint16_t _x = (uint16_t) (X); \ 546*0a6a1f1dSLionel Sambuc uint32_t _t = _x & 0xFF; \ 547*0a6a1f1dSLionel Sambuc _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 548*0a6a1f1dSLionel Sambuc (X) = _t; \ 549*0a6a1f1dSLionel Sambuc } while (/*CONSTCOND*/0) 550*0a6a1f1dSLionel Sambuc#define SWAP_WORD(X) do { \ 551*0a6a1f1dSLionel Sambuc uint32_t _x = (uint32_t) (X); \ 552*0a6a1f1dSLionel Sambuc uint32_t _t = _x & 0xFF; \ 553*0a6a1f1dSLionel Sambuc _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 554*0a6a1f1dSLionel Sambuc _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 555*0a6a1f1dSLionel Sambuc _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 556*0a6a1f1dSLionel Sambuc (X) = _t; \ 557*0a6a1f1dSLionel Sambuc } while (/*CONSTCOND*/0) 558*0a6a1f1dSLionel Sambuc#define SWAP_ADDR32(X) SWAP_WORD(X) 559*0a6a1f1dSLionel Sambuc#define SWAP_OFF32(X) SWAP_WORD(X) 560*0a6a1f1dSLionel Sambuc#define SWAP_SWORD(X) SWAP_WORD(X) 561*0a6a1f1dSLionel Sambuc#define SWAP_WORD64(X) do { \ 562*0a6a1f1dSLionel Sambuc uint64_t _x = (uint64_t) (X); \ 563*0a6a1f1dSLionel Sambuc uint64_t _t = _x & 0xFF; \ 564*0a6a1f1dSLionel Sambuc _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 565*0a6a1f1dSLionel Sambuc _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 566*0a6a1f1dSLionel Sambuc _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 567*0a6a1f1dSLionel Sambuc _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 568*0a6a1f1dSLionel Sambuc _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 569*0a6a1f1dSLionel Sambuc _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 570*0a6a1f1dSLionel Sambuc _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 571*0a6a1f1dSLionel Sambuc (X) = _t; \ 572*0a6a1f1dSLionel Sambuc } while (/*CONSTCOND*/0) 573*0a6a1f1dSLionel Sambuc#define SWAP_ADDR64(X) SWAP_WORD64(X) 574*0a6a1f1dSLionel Sambuc#define SWAP_LWORD(X) SWAP_WORD64(X) 575*0a6a1f1dSLionel Sambuc#define SWAP_OFF64(X) SWAP_WORD64(X) 576*0a6a1f1dSLionel Sambuc#define SWAP_SXWORD(X) SWAP_WORD64(X) 577*0a6a1f1dSLionel Sambuc#define SWAP_XWORD(X) SWAP_WORD64(X) 578*0a6a1f1dSLionel Sambuc 579*0a6a1f1dSLionel Sambuc/* 580*0a6a1f1dSLionel Sambuc * C macros to write out various integral values. 581*0a6a1f1dSLionel Sambuc * 582*0a6a1f1dSLionel Sambuc * Note: 583*0a6a1f1dSLionel Sambuc * - The destination pointer could be unaligned. 584*0a6a1f1dSLionel Sambuc * - Values are written out in native byte order. 585*0a6a1f1dSLionel Sambuc * - The destination pointer is incremented after the write. 586*0a6a1f1dSLionel Sambuc */ 587*0a6a1f1dSLionel Sambuc#define WRITE_BYTE(P,X) do { \ 588*0a6a1f1dSLionel Sambuc char *const _p = (void *) (P); \ 589*0a6a1f1dSLionel Sambuc _p[0] = (char) (X); \ 590*0a6a1f1dSLionel Sambuc (P) = (void *)(_p + 1); \ 591*0a6a1f1dSLionel Sambuc } while (/*CONSTCOND*/0) 592*0a6a1f1dSLionel Sambuc#define WRITE_HALF(P,X) do { \ 593*0a6a1f1dSLionel Sambuc union { \ 594*0a6a1f1dSLionel Sambuc uint16_t val; \ 595*0a6a1f1dSLionel Sambuc uint8_t bytes[2]; \ 596*0a6a1f1dSLionel Sambuc } _t; \ 597*0a6a1f1dSLionel Sambuc unsigned char *const _p = (void *) (P); \ 598*0a6a1f1dSLionel Sambuc _t.val = (X); \ 599*0a6a1f1dSLionel Sambuc _p[0] = _t.bytes[0]; \ 600*0a6a1f1dSLionel Sambuc _p[1] = _t.bytes[1]; \ 601*0a6a1f1dSLionel Sambuc (P) = (void *)(_p + 2); \ 602*0a6a1f1dSLionel Sambuc } while (/*CONSTCOND*/0) 603*0a6a1f1dSLionel Sambuc#define WRITE_WORD(P,X) do { \ 604*0a6a1f1dSLionel Sambuc union { \ 605*0a6a1f1dSLionel Sambuc uint32_t val; \ 606*0a6a1f1dSLionel Sambuc uint8_t bytes[4]; \ 607*0a6a1f1dSLionel Sambuc } _t; \ 608*0a6a1f1dSLionel Sambuc unsigned char *const _p = (void *) (P); \ 609*0a6a1f1dSLionel Sambuc _t.val = (X); \ 610*0a6a1f1dSLionel Sambuc _p[0] = _t.bytes[0]; \ 611*0a6a1f1dSLionel Sambuc _p[1] = _t.bytes[1]; \ 612*0a6a1f1dSLionel Sambuc _p[2] = _t.bytes[2]; \ 613*0a6a1f1dSLionel Sambuc _p[3] = _t.bytes[3]; \ 614*0a6a1f1dSLionel Sambuc (P) = (void *)(_p + 4); \ 615*0a6a1f1dSLionel Sambuc } while (/*CONSTCOND*/0) 616*0a6a1f1dSLionel Sambuc#define WRITE_ADDR32(P,X) WRITE_WORD(P,X) 617*0a6a1f1dSLionel Sambuc#define WRITE_OFF32(P,X) WRITE_WORD(P,X) 618*0a6a1f1dSLionel Sambuc#define WRITE_SWORD(P,X) WRITE_WORD(P,X) 619*0a6a1f1dSLionel Sambuc#define WRITE_WORD64(P,X) do { \ 620*0a6a1f1dSLionel Sambuc union { \ 621*0a6a1f1dSLionel Sambuc uint64_t val; \ 622*0a6a1f1dSLionel Sambuc uint8_t bytes[8]; \ 623*0a6a1f1dSLionel Sambuc } _t; \ 624*0a6a1f1dSLionel Sambuc unsigned char *const _p = (void *) (P); \ 625*0a6a1f1dSLionel Sambuc _t.val = (X); \ 626*0a6a1f1dSLionel Sambuc _p[0] = _t.bytes[0]; \ 627*0a6a1f1dSLionel Sambuc _p[1] = _t.bytes[1]; \ 628*0a6a1f1dSLionel Sambuc _p[2] = _t.bytes[2]; \ 629*0a6a1f1dSLionel Sambuc _p[3] = _t.bytes[3]; \ 630*0a6a1f1dSLionel Sambuc _p[4] = _t.bytes[4]; \ 631*0a6a1f1dSLionel Sambuc _p[5] = _t.bytes[5]; \ 632*0a6a1f1dSLionel Sambuc _p[6] = _t.bytes[6]; \ 633*0a6a1f1dSLionel Sambuc _p[7] = _t.bytes[7]; \ 634*0a6a1f1dSLionel Sambuc (P) = (void *)(_p + 8); \ 635*0a6a1f1dSLionel Sambuc } while (/*CONSTCOND*/0) 636*0a6a1f1dSLionel Sambuc#define WRITE_ADDR64(P,X) WRITE_WORD64(P,X) 637*0a6a1f1dSLionel Sambuc#define WRITE_LWORD(P,X) WRITE_WORD64(P,X) 638*0a6a1f1dSLionel Sambuc#define WRITE_OFF64(P,X) WRITE_WORD64(P,X) 639*0a6a1f1dSLionel Sambuc#define WRITE_SXWORD(P,X) WRITE_WORD64(P,X) 640*0a6a1f1dSLionel Sambuc#define WRITE_XWORD(P,X) WRITE_WORD64(P,X) 641*0a6a1f1dSLionel Sambuc#define WRITE_IDENT(P,X) do { \ 642*0a6a1f1dSLionel Sambuc (void) memcpy((P), (X), sizeof((X))); \ 643*0a6a1f1dSLionel Sambuc (P) = (P) + EI_NIDENT; \ 644*0a6a1f1dSLionel Sambuc } while (/*CONSTCOND*/0) 645*0a6a1f1dSLionel Sambuc 646*0a6a1f1dSLionel Sambuc/* 647*0a6a1f1dSLionel Sambuc * C macros to read in various integral values. 648*0a6a1f1dSLionel Sambuc * 649*0a6a1f1dSLionel Sambuc * Note: 650*0a6a1f1dSLionel Sambuc * - The source pointer could be unaligned. 651*0a6a1f1dSLionel Sambuc * - Values are read in native byte order. 652*0a6a1f1dSLionel Sambuc * - The source pointer is incremented appropriately. 653*0a6a1f1dSLionel Sambuc */ 654*0a6a1f1dSLionel Sambuc 655*0a6a1f1dSLionel Sambuc#define READ_BYTE(P,X) do { \ 656*0a6a1f1dSLionel Sambuc const char *const _p = \ 657*0a6a1f1dSLionel Sambuc (const void *) (P); \ 658*0a6a1f1dSLionel Sambuc (X) = _p[0]; \ 659*0a6a1f1dSLionel Sambuc (P) = (P) + 1; \ 660*0a6a1f1dSLionel Sambuc } while (/*CONSTCOND*/0) 661*0a6a1f1dSLionel Sambuc#define READ_HALF(P,X) do { \ 662*0a6a1f1dSLionel Sambuc uint16_t _t; \ 663*0a6a1f1dSLionel Sambuc char *const _q = (char *) &_t; \ 664*0a6a1f1dSLionel Sambuc const char *const _p = \ 665*0a6a1f1dSLionel Sambuc (const char *) (P); \ 666*0a6a1f1dSLionel Sambuc _q[0] = _p[0]; \ 667*0a6a1f1dSLionel Sambuc _q[1] = _p[1]; \ 668*0a6a1f1dSLionel Sambuc (P) = (P) + 2; \ 669*0a6a1f1dSLionel Sambuc (X) = _t; \ 670*0a6a1f1dSLionel Sambuc } while (/*CONSTCOND*/0) 671*0a6a1f1dSLionel Sambuc#define READ_WORD(P,X) do { \ 672*0a6a1f1dSLionel Sambuc uint32_t _t; \ 673*0a6a1f1dSLionel Sambuc char *const _q = (void *) &_t; \ 674*0a6a1f1dSLionel Sambuc const char *const _p = \ 675*0a6a1f1dSLionel Sambuc (const void *) (P); \ 676*0a6a1f1dSLionel Sambuc _q[0] = _p[0]; \ 677*0a6a1f1dSLionel Sambuc _q[1] = _p[1]; \ 678*0a6a1f1dSLionel Sambuc _q[2] = _p[2]; \ 679*0a6a1f1dSLionel Sambuc _q[3] = _p[3]; \ 680*0a6a1f1dSLionel Sambuc (P) = (P) + 4; \ 681*0a6a1f1dSLionel Sambuc (X) = _t; \ 682*0a6a1f1dSLionel Sambuc } while (/*CONSTCOND*/0) 683*0a6a1f1dSLionel Sambuc#define READ_ADDR32(P,X) READ_WORD(P,X) 684*0a6a1f1dSLionel Sambuc#define READ_OFF32(P,X) READ_WORD(P,X) 685*0a6a1f1dSLionel Sambuc#define READ_SWORD(P,X) READ_WORD(P,X) 686*0a6a1f1dSLionel Sambuc#define READ_WORD64(P,X) do { \ 687*0a6a1f1dSLionel Sambuc uint64_t _t; \ 688*0a6a1f1dSLionel Sambuc char *const _q = (void *) &_t; \ 689*0a6a1f1dSLionel Sambuc const char *const _p = \ 690*0a6a1f1dSLionel Sambuc (const void *) (P); \ 691*0a6a1f1dSLionel Sambuc _q[0] = _p[0]; \ 692*0a6a1f1dSLionel Sambuc _q[1] = _p[1]; \ 693*0a6a1f1dSLionel Sambuc _q[2] = _p[2]; \ 694*0a6a1f1dSLionel Sambuc _q[3] = _p[3]; \ 695*0a6a1f1dSLionel Sambuc _q[4] = _p[4]; \ 696*0a6a1f1dSLionel Sambuc _q[5] = _p[5]; \ 697*0a6a1f1dSLionel Sambuc _q[6] = _p[6]; \ 698*0a6a1f1dSLionel Sambuc _q[7] = _p[7]; \ 699*0a6a1f1dSLionel Sambuc (P) = (P) + 8; \ 700*0a6a1f1dSLionel Sambuc (X) = _t; \ 701*0a6a1f1dSLionel Sambuc } while (/*CONSTCOND*/0) 702*0a6a1f1dSLionel Sambuc#define READ_ADDR64(P,X) READ_WORD64(P,X) 703*0a6a1f1dSLionel Sambuc#define READ_LWORD(P,X) READ_WORD64(P,X) 704*0a6a1f1dSLionel Sambuc#define READ_OFF64(P,X) READ_WORD64(P,X) 705*0a6a1f1dSLionel Sambuc#define READ_SXWORD(P,X) READ_WORD64(P,X) 706*0a6a1f1dSLionel Sambuc#define READ_XWORD(P,X) READ_WORD64(P,X) 707*0a6a1f1dSLionel Sambuc#define READ_IDENT(P,X) do { \ 708*0a6a1f1dSLionel Sambuc (void) memcpy((X), (P), sizeof((X))); \ 709*0a6a1f1dSLionel Sambuc (P) = (P) + EI_NIDENT; \ 710*0a6a1f1dSLionel Sambuc } while (/*CONSTCOND*/0) 711*0a6a1f1dSLionel Sambuc 712*0a6a1f1dSLionel Sambuc#define ROUNDUP2(V,N) (V) = ((((V) + (N) - 1)) & ~((N) - 1)) 713*0a6a1f1dSLionel Sambuc 714*0a6a1f1dSLionel Sambuc/*[*/ 715*0a6a1f1dSLionel SambucMAKE_TYPE_CONVERTERS(ELF_TYPE_LIST) 716*0a6a1f1dSLionel SambucMAKE_VERSION_CONVERTERS(VDEF,Verdef,Verdaux,vd) 717*0a6a1f1dSLionel SambucMAKE_VERSION_CONVERTERS(VNEED,Verneed,Vernaux,vn) 718*0a6a1f1dSLionel Sambuc/*]*/ 719*0a6a1f1dSLionel Sambuc 720*0a6a1f1dSLionel Sambuc/* 721*0a6a1f1dSLionel Sambuc * Sections of type ELF_T_BYTE are never byteswapped, consequently a 722*0a6a1f1dSLionel Sambuc * simple memcpy suffices for both directions of conversion. 723*0a6a1f1dSLionel Sambuc */ 724*0a6a1f1dSLionel Sambuc 725*0a6a1f1dSLionel Sambuc/*ARGSUSED*/ 726*0a6a1f1dSLionel Sambucstatic int 727*0a6a1f1dSLionel Sambuc_libelf_cvt_BYTE_tox(char *dst, size_t dsz, char *src, size_t count, 728*0a6a1f1dSLionel Sambuc int byteswap) 729*0a6a1f1dSLionel Sambuc{ 730*0a6a1f1dSLionel Sambuc (void) byteswap; 731*0a6a1f1dSLionel Sambuc if (dsz < count) 732*0a6a1f1dSLionel Sambuc return (0); 733*0a6a1f1dSLionel Sambuc if (dst != src) 734*0a6a1f1dSLionel Sambuc (void) memcpy(dst, src, count); 735*0a6a1f1dSLionel Sambuc return (1); 736*0a6a1f1dSLionel Sambuc} 737*0a6a1f1dSLionel Sambuc 738*0a6a1f1dSLionel Sambuc/* 739*0a6a1f1dSLionel Sambuc * Sections of type ELF_T_GNUHASH start with a header containing 4 32-bit 740*0a6a1f1dSLionel Sambuc * words. Bloom filter data comes next, followed by hash buckets and the 741*0a6a1f1dSLionel Sambuc * hash chain. 742*0a6a1f1dSLionel Sambuc * 743*0a6a1f1dSLionel Sambuc * Bloom filter words are 64 bit wide on ELFCLASS64 objects and are 32 bit 744*0a6a1f1dSLionel Sambuc * wide on ELFCLASS32 objects. The other objects in this section are 32 745*0a6a1f1dSLionel Sambuc * bits wide. 746*0a6a1f1dSLionel Sambuc * 747*0a6a1f1dSLionel Sambuc * Argument `srcsz' denotes the number of bytes to be converted. In the 748*0a6a1f1dSLionel Sambuc * 32-bit case we need to translate `srcsz' to a count of 32-bit words. 749*0a6a1f1dSLionel Sambuc */ 750*0a6a1f1dSLionel Sambuc 751*0a6a1f1dSLionel Sambucstatic int 752*0a6a1f1dSLionel Sambuc_libelf_cvt_GNUHASH32_tom(char *dst, size_t dsz, char *src, size_t srcsz, 753*0a6a1f1dSLionel Sambuc int byteswap) 754*0a6a1f1dSLionel Sambuc{ 755*0a6a1f1dSLionel Sambuc return (_libelf_cvt_WORD_tom(dst, dsz, src, srcsz / sizeof(uint32_t), 756*0a6a1f1dSLionel Sambuc byteswap)); 757*0a6a1f1dSLionel Sambuc} 758*0a6a1f1dSLionel Sambuc 759*0a6a1f1dSLionel Sambucstatic int 760*0a6a1f1dSLionel Sambuc_libelf_cvt_GNUHASH32_tof(char *dst, size_t dsz, char *src, size_t srcsz, 761*0a6a1f1dSLionel Sambuc int byteswap) 762*0a6a1f1dSLionel Sambuc{ 763*0a6a1f1dSLionel Sambuc return (_libelf_cvt_WORD_tof(dst, dsz, src, srcsz / sizeof(uint32_t), 764*0a6a1f1dSLionel Sambuc byteswap)); 765*0a6a1f1dSLionel Sambuc} 766*0a6a1f1dSLionel Sambuc 767*0a6a1f1dSLionel Sambucstatic int 768*0a6a1f1dSLionel Sambuc_libelf_cvt_GNUHASH64_tom(char *dst, size_t dsz, char *src, size_t srcsz, 769*0a6a1f1dSLionel Sambuc int byteswap) 770*0a6a1f1dSLionel Sambuc{ 771*0a6a1f1dSLionel Sambuc size_t sz; 772*0a6a1f1dSLionel Sambuc uint64_t t64, *bloom64; 773*0a6a1f1dSLionel Sambuc Elf_GNU_Hash_Header *gh; 774*0a6a1f1dSLionel Sambuc uint32_t n, nbuckets, nchains, maskwords, shift2, symndx, t32; 775*0a6a1f1dSLionel Sambuc uint32_t *buckets, *chains; 776*0a6a1f1dSLionel Sambuc 777*0a6a1f1dSLionel Sambuc sz = 4 * sizeof(uint32_t); /* File header is 4 words long. */ 778*0a6a1f1dSLionel Sambuc if (dsz < sizeof(Elf_GNU_Hash_Header) || srcsz < sz) 779*0a6a1f1dSLionel Sambuc return (0); 780*0a6a1f1dSLionel Sambuc 781*0a6a1f1dSLionel Sambuc /* Read in the section header and byteswap if needed. */ 782*0a6a1f1dSLionel Sambuc READ_WORD(src, nbuckets); 783*0a6a1f1dSLionel Sambuc READ_WORD(src, symndx); 784*0a6a1f1dSLionel Sambuc READ_WORD(src, maskwords); 785*0a6a1f1dSLionel Sambuc READ_WORD(src, shift2); 786*0a6a1f1dSLionel Sambuc 787*0a6a1f1dSLionel Sambuc srcsz -= sz; 788*0a6a1f1dSLionel Sambuc 789*0a6a1f1dSLionel Sambuc if (byteswap) { 790*0a6a1f1dSLionel Sambuc SWAP_WORD(nbuckets); 791*0a6a1f1dSLionel Sambuc SWAP_WORD(symndx); 792*0a6a1f1dSLionel Sambuc SWAP_WORD(maskwords); 793*0a6a1f1dSLionel Sambuc SWAP_WORD(shift2); 794*0a6a1f1dSLionel Sambuc } 795*0a6a1f1dSLionel Sambuc 796*0a6a1f1dSLionel Sambuc /* Check source buffer and destination buffer sizes. */ 797*0a6a1f1dSLionel Sambuc sz = nbuckets * sizeof(uint32_t) + maskwords * sizeof(uint64_t); 798*0a6a1f1dSLionel Sambuc if (srcsz < sz || dsz < sz + sizeof(Elf_GNU_Hash_Header)) 799*0a6a1f1dSLionel Sambuc return (0); 800*0a6a1f1dSLionel Sambuc 801*0a6a1f1dSLionel Sambuc gh = (Elf_GNU_Hash_Header *) (uintptr_t) dst; 802*0a6a1f1dSLionel Sambuc gh->gh_nbuckets = nbuckets; 803*0a6a1f1dSLionel Sambuc gh->gh_symndx = symndx; 804*0a6a1f1dSLionel Sambuc gh->gh_maskwords = maskwords; 805*0a6a1f1dSLionel Sambuc gh->gh_shift2 = shift2; 806*0a6a1f1dSLionel Sambuc 807*0a6a1f1dSLionel Sambuc dsz -= sizeof(Elf_GNU_Hash_Header); 808*0a6a1f1dSLionel Sambuc dst += sizeof(Elf_GNU_Hash_Header); 809*0a6a1f1dSLionel Sambuc 810*0a6a1f1dSLionel Sambuc bloom64 = (uint64_t *) (uintptr_t) dst; 811*0a6a1f1dSLionel Sambuc 812*0a6a1f1dSLionel Sambuc /* Copy bloom filter data. */ 813*0a6a1f1dSLionel Sambuc for (n = 0; n < maskwords; n++) { 814*0a6a1f1dSLionel Sambuc READ_XWORD(src, t64); 815*0a6a1f1dSLionel Sambuc if (byteswap) 816*0a6a1f1dSLionel Sambuc SWAP_XWORD(t64); 817*0a6a1f1dSLionel Sambuc bloom64[n] = t64; 818*0a6a1f1dSLionel Sambuc } 819*0a6a1f1dSLionel Sambuc 820*0a6a1f1dSLionel Sambuc /* The hash buckets follows the bloom filter. */ 821*0a6a1f1dSLionel Sambuc dst += maskwords * sizeof(uint64_t); 822*0a6a1f1dSLionel Sambuc buckets = (uint32_t *) (uintptr_t) dst; 823*0a6a1f1dSLionel Sambuc 824*0a6a1f1dSLionel Sambuc for (n = 0; n < nbuckets; n++) { 825*0a6a1f1dSLionel Sambuc READ_WORD(src, t32); 826*0a6a1f1dSLionel Sambuc if (byteswap) 827*0a6a1f1dSLionel Sambuc SWAP_WORD(t32); 828*0a6a1f1dSLionel Sambuc buckets[n] = t32; 829*0a6a1f1dSLionel Sambuc } 830*0a6a1f1dSLionel Sambuc 831*0a6a1f1dSLionel Sambuc dst += nbuckets * sizeof(uint32_t); 832*0a6a1f1dSLionel Sambuc 833*0a6a1f1dSLionel Sambuc /* The hash chain follows the hash buckets. */ 834*0a6a1f1dSLionel Sambuc dsz -= sz; 835*0a6a1f1dSLionel Sambuc srcsz -= sz; 836*0a6a1f1dSLionel Sambuc 837*0a6a1f1dSLionel Sambuc if (dsz < srcsz) /* Destination lacks space. */ 838*0a6a1f1dSLionel Sambuc return (0); 839*0a6a1f1dSLionel Sambuc 840*0a6a1f1dSLionel Sambuc nchains = srcsz / sizeof(uint32_t); 841*0a6a1f1dSLionel Sambuc chains = (uint32_t *) (uintptr_t) dst; 842*0a6a1f1dSLionel Sambuc 843*0a6a1f1dSLionel Sambuc for (n = 0; n < nchains; n++) { 844*0a6a1f1dSLionel Sambuc READ_WORD(src, t32); 845*0a6a1f1dSLionel Sambuc if (byteswap) 846*0a6a1f1dSLionel Sambuc SWAP_WORD(t32); 847*0a6a1f1dSLionel Sambuc *chains++ = t32; 848*0a6a1f1dSLionel Sambuc } 849*0a6a1f1dSLionel Sambuc 850*0a6a1f1dSLionel Sambuc return (1); 851*0a6a1f1dSLionel Sambuc} 852*0a6a1f1dSLionel Sambuc 853*0a6a1f1dSLionel Sambucstatic int 854*0a6a1f1dSLionel Sambuc_libelf_cvt_GNUHASH64_tof(char *dst, size_t dsz, char *src, size_t srcsz, 855*0a6a1f1dSLionel Sambuc int byteswap) 856*0a6a1f1dSLionel Sambuc{ 857*0a6a1f1dSLionel Sambuc uint32_t *s32; 858*0a6a1f1dSLionel Sambuc size_t sz, hdrsz; 859*0a6a1f1dSLionel Sambuc uint64_t *s64, t64; 860*0a6a1f1dSLionel Sambuc Elf_GNU_Hash_Header *gh; 861*0a6a1f1dSLionel Sambuc uint32_t maskwords, n, nbuckets, nchains, t0, t1, t2, t3, t32; 862*0a6a1f1dSLionel Sambuc 863*0a6a1f1dSLionel Sambuc hdrsz = 4 * sizeof(uint32_t); /* Header is 4x32 bits. */ 864*0a6a1f1dSLionel Sambuc if (dsz < hdrsz || srcsz < sizeof(Elf_GNU_Hash_Header)) 865*0a6a1f1dSLionel Sambuc return (0); 866*0a6a1f1dSLionel Sambuc 867*0a6a1f1dSLionel Sambuc gh = (Elf_GNU_Hash_Header *) (uintptr_t) src; 868*0a6a1f1dSLionel Sambuc 869*0a6a1f1dSLionel Sambuc t0 = nbuckets = gh->gh_nbuckets; 870*0a6a1f1dSLionel Sambuc t1 = gh->gh_symndx; 871*0a6a1f1dSLionel Sambuc t2 = maskwords = gh->gh_maskwords; 872*0a6a1f1dSLionel Sambuc t3 = gh->gh_shift2; 873*0a6a1f1dSLionel Sambuc 874*0a6a1f1dSLionel Sambuc src += sizeof(Elf_GNU_Hash_Header); 875*0a6a1f1dSLionel Sambuc srcsz -= sizeof(Elf_GNU_Hash_Header); 876*0a6a1f1dSLionel Sambuc dsz -= hdrsz; 877*0a6a1f1dSLionel Sambuc 878*0a6a1f1dSLionel Sambuc sz = gh->gh_nbuckets * sizeof(uint32_t) + gh->gh_maskwords * 879*0a6a1f1dSLionel Sambuc sizeof(uint64_t); 880*0a6a1f1dSLionel Sambuc 881*0a6a1f1dSLionel Sambuc if (srcsz < sz || dsz < sz) 882*0a6a1f1dSLionel Sambuc return (0); 883*0a6a1f1dSLionel Sambuc 884*0a6a1f1dSLionel Sambuc /* Write out the header. */ 885*0a6a1f1dSLionel Sambuc if (byteswap) { 886*0a6a1f1dSLionel Sambuc SWAP_WORD(t0); 887*0a6a1f1dSLionel Sambuc SWAP_WORD(t1); 888*0a6a1f1dSLionel Sambuc SWAP_WORD(t2); 889*0a6a1f1dSLionel Sambuc SWAP_WORD(t3); 890*0a6a1f1dSLionel Sambuc } 891*0a6a1f1dSLionel Sambuc 892*0a6a1f1dSLionel Sambuc WRITE_WORD(dst, t0); 893*0a6a1f1dSLionel Sambuc WRITE_WORD(dst, t1); 894*0a6a1f1dSLionel Sambuc WRITE_WORD(dst, t2); 895*0a6a1f1dSLionel Sambuc WRITE_WORD(dst, t3); 896*0a6a1f1dSLionel Sambuc 897*0a6a1f1dSLionel Sambuc /* Copy the bloom filter and the hash table. */ 898*0a6a1f1dSLionel Sambuc s64 = (uint64_t *) (uintptr_t) src; 899*0a6a1f1dSLionel Sambuc for (n = 0; n < maskwords; n++) { 900*0a6a1f1dSLionel Sambuc t64 = *s64++; 901*0a6a1f1dSLionel Sambuc if (byteswap) 902*0a6a1f1dSLionel Sambuc SWAP_XWORD(t64); 903*0a6a1f1dSLionel Sambuc WRITE_WORD64(dst, t64); 904*0a6a1f1dSLionel Sambuc } 905*0a6a1f1dSLionel Sambuc 906*0a6a1f1dSLionel Sambuc s32 = (uint32_t *) s64; 907*0a6a1f1dSLionel Sambuc for (n = 0; n < nbuckets; n++) { 908*0a6a1f1dSLionel Sambuc t32 = *s32++; 909*0a6a1f1dSLionel Sambuc if (byteswap) 910*0a6a1f1dSLionel Sambuc SWAP_WORD(t32); 911*0a6a1f1dSLionel Sambuc WRITE_WORD(dst, t32); 912*0a6a1f1dSLionel Sambuc } 913*0a6a1f1dSLionel Sambuc 914*0a6a1f1dSLionel Sambuc srcsz -= sz; 915*0a6a1f1dSLionel Sambuc dsz -= sz; 916*0a6a1f1dSLionel Sambuc 917*0a6a1f1dSLionel Sambuc /* Copy out the hash chains. */ 918*0a6a1f1dSLionel Sambuc if (dsz < srcsz) 919*0a6a1f1dSLionel Sambuc return (0); 920*0a6a1f1dSLionel Sambuc 921*0a6a1f1dSLionel Sambuc nchains = srcsz / sizeof(uint32_t); 922*0a6a1f1dSLionel Sambuc for (n = 0; n < nchains; n++) { 923*0a6a1f1dSLionel Sambuc t32 = *s32++; 924*0a6a1f1dSLionel Sambuc if (byteswap) 925*0a6a1f1dSLionel Sambuc SWAP_WORD(t32); 926*0a6a1f1dSLionel Sambuc WRITE_WORD(dst, t32); 927*0a6a1f1dSLionel Sambuc } 928*0a6a1f1dSLionel Sambuc 929*0a6a1f1dSLionel Sambuc return (1); 930*0a6a1f1dSLionel Sambuc} 931*0a6a1f1dSLionel Sambuc 932*0a6a1f1dSLionel Sambuc/* 933*0a6a1f1dSLionel Sambuc * Elf note structures comprise a fixed size header followed by variable 934*0a6a1f1dSLionel Sambuc * length strings. The fixed size header needs to be byte swapped, but 935*0a6a1f1dSLionel Sambuc * not the strings. 936*0a6a1f1dSLionel Sambuc * 937*0a6a1f1dSLionel Sambuc * Argument `count' denotes the total number of bytes to be converted. 938*0a6a1f1dSLionel Sambuc * The destination buffer needs to be at least `count' bytes in size. 939*0a6a1f1dSLionel Sambuc */ 940*0a6a1f1dSLionel Sambucstatic int 941*0a6a1f1dSLionel Sambuc_libelf_cvt_NOTE_tom(char *dst, size_t dsz, char *src, size_t count, 942*0a6a1f1dSLionel Sambuc int byteswap) 943*0a6a1f1dSLionel Sambuc{ 944*0a6a1f1dSLionel Sambuc uint32_t namesz, descsz, type; 945*0a6a1f1dSLionel Sambuc Elf_Note *en; 946*0a6a1f1dSLionel Sambuc size_t sz, hdrsz; 947*0a6a1f1dSLionel Sambuc 948*0a6a1f1dSLionel Sambuc if (dsz < count) /* Destination buffer is too small. */ 949*0a6a1f1dSLionel Sambuc return (0); 950*0a6a1f1dSLionel Sambuc 951*0a6a1f1dSLionel Sambuc hdrsz = 3 * sizeof(uint32_t); 952*0a6a1f1dSLionel Sambuc if (count < hdrsz) /* Source too small. */ 953*0a6a1f1dSLionel Sambuc return (0); 954*0a6a1f1dSLionel Sambuc 955*0a6a1f1dSLionel Sambuc if (!byteswap) { 956*0a6a1f1dSLionel Sambuc (void) memcpy(dst, src, count); 957*0a6a1f1dSLionel Sambuc return (1); 958*0a6a1f1dSLionel Sambuc } 959*0a6a1f1dSLionel Sambuc 960*0a6a1f1dSLionel Sambuc /* Process all notes in the section. */ 961*0a6a1f1dSLionel Sambuc while (count > hdrsz) { 962*0a6a1f1dSLionel Sambuc /* Read the note header. */ 963*0a6a1f1dSLionel Sambuc READ_WORD(src, namesz); 964*0a6a1f1dSLionel Sambuc READ_WORD(src, descsz); 965*0a6a1f1dSLionel Sambuc READ_WORD(src, type); 966*0a6a1f1dSLionel Sambuc 967*0a6a1f1dSLionel Sambuc /* Translate. */ 968*0a6a1f1dSLionel Sambuc SWAP_WORD(namesz); 969*0a6a1f1dSLionel Sambuc SWAP_WORD(descsz); 970*0a6a1f1dSLionel Sambuc SWAP_WORD(type); 971*0a6a1f1dSLionel Sambuc 972*0a6a1f1dSLionel Sambuc /* Copy out the translated note header. */ 973*0a6a1f1dSLionel Sambuc en = (Elf_Note *) (uintptr_t) dst; 974*0a6a1f1dSLionel Sambuc en->n_namesz = namesz; 975*0a6a1f1dSLionel Sambuc en->n_descsz = descsz; 976*0a6a1f1dSLionel Sambuc en->n_type = type; 977*0a6a1f1dSLionel Sambuc 978*0a6a1f1dSLionel Sambuc dsz -= sizeof(Elf_Note); 979*0a6a1f1dSLionel Sambuc dst += sizeof(Elf_Note); 980*0a6a1f1dSLionel Sambuc count -= hdrsz; 981*0a6a1f1dSLionel Sambuc 982*0a6a1f1dSLionel Sambuc ROUNDUP2(namesz, 4); 983*0a6a1f1dSLionel Sambuc ROUNDUP2(descsz, 4); 984*0a6a1f1dSLionel Sambuc 985*0a6a1f1dSLionel Sambuc sz = namesz + descsz; 986*0a6a1f1dSLionel Sambuc 987*0a6a1f1dSLionel Sambuc if (count < sz || dsz < sz) /* Buffers are too small. */ 988*0a6a1f1dSLionel Sambuc return (0); 989*0a6a1f1dSLionel Sambuc 990*0a6a1f1dSLionel Sambuc (void) memcpy(dst, src, sz); 991*0a6a1f1dSLionel Sambuc 992*0a6a1f1dSLionel Sambuc src += sz; 993*0a6a1f1dSLionel Sambuc dst += sz; 994*0a6a1f1dSLionel Sambuc 995*0a6a1f1dSLionel Sambuc count -= sz; 996*0a6a1f1dSLionel Sambuc dsz -= sz; 997*0a6a1f1dSLionel Sambuc } 998*0a6a1f1dSLionel Sambuc 999*0a6a1f1dSLionel Sambuc return (1); 1000*0a6a1f1dSLionel Sambuc} 1001*0a6a1f1dSLionel Sambuc 1002*0a6a1f1dSLionel Sambucstatic int 1003*0a6a1f1dSLionel Sambuc_libelf_cvt_NOTE_tof(char *dst, size_t dsz, char *src, size_t count, 1004*0a6a1f1dSLionel Sambuc int byteswap) 1005*0a6a1f1dSLionel Sambuc{ 1006*0a6a1f1dSLionel Sambuc uint32_t namesz, descsz, type; 1007*0a6a1f1dSLionel Sambuc Elf_Note *en; 1008*0a6a1f1dSLionel Sambuc size_t sz; 1009*0a6a1f1dSLionel Sambuc 1010*0a6a1f1dSLionel Sambuc if (dsz < count) 1011*0a6a1f1dSLionel Sambuc return (0); 1012*0a6a1f1dSLionel Sambuc 1013*0a6a1f1dSLionel Sambuc if (!byteswap) { 1014*0a6a1f1dSLionel Sambuc (void) memcpy(dst, src, count); 1015*0a6a1f1dSLionel Sambuc return (1); 1016*0a6a1f1dSLionel Sambuc } 1017*0a6a1f1dSLionel Sambuc 1018*0a6a1f1dSLionel Sambuc while (count > sizeof(Elf_Note)) { 1019*0a6a1f1dSLionel Sambuc 1020*0a6a1f1dSLionel Sambuc en = (Elf_Note *) (uintptr_t) src; 1021*0a6a1f1dSLionel Sambuc namesz = en->n_namesz; 1022*0a6a1f1dSLionel Sambuc descsz = en->n_descsz; 1023*0a6a1f1dSLionel Sambuc type = en->n_type; 1024*0a6a1f1dSLionel Sambuc 1025*0a6a1f1dSLionel Sambuc SWAP_WORD(namesz); 1026*0a6a1f1dSLionel Sambuc SWAP_WORD(descsz); 1027*0a6a1f1dSLionel Sambuc SWAP_WORD(type); 1028*0a6a1f1dSLionel Sambuc 1029*0a6a1f1dSLionel Sambuc WRITE_WORD(dst, namesz); 1030*0a6a1f1dSLionel Sambuc WRITE_WORD(dst, descsz); 1031*0a6a1f1dSLionel Sambuc WRITE_WORD(dst, type); 1032*0a6a1f1dSLionel Sambuc 1033*0a6a1f1dSLionel Sambuc src += sizeof(Elf_Note); 1034*0a6a1f1dSLionel Sambuc 1035*0a6a1f1dSLionel Sambuc ROUNDUP2(namesz, 4); 1036*0a6a1f1dSLionel Sambuc ROUNDUP2(descsz, 4); 1037*0a6a1f1dSLionel Sambuc 1038*0a6a1f1dSLionel Sambuc sz = namesz + descsz; 1039*0a6a1f1dSLionel Sambuc 1040*0a6a1f1dSLionel Sambuc if (count < sz) 1041*0a6a1f1dSLionel Sambuc sz = count; 1042*0a6a1f1dSLionel Sambuc 1043*0a6a1f1dSLionel Sambuc (void) memcpy(dst, src, sz); 1044*0a6a1f1dSLionel Sambuc 1045*0a6a1f1dSLionel Sambuc src += sz; 1046*0a6a1f1dSLionel Sambuc dst += sz; 1047*0a6a1f1dSLionel Sambuc count -= sz; 1048*0a6a1f1dSLionel Sambuc } 1049*0a6a1f1dSLionel Sambuc 1050*0a6a1f1dSLionel Sambuc return (1); 1051*0a6a1f1dSLionel Sambuc} 1052*0a6a1f1dSLionel Sambuc 1053*0a6a1f1dSLionel Sambucstruct converters { 1054*0a6a1f1dSLionel Sambuc int (*tof32)(char *dst, size_t dsz, char *src, size_t cnt, 1055*0a6a1f1dSLionel Sambuc int byteswap); 1056*0a6a1f1dSLionel Sambuc int (*tom32)(char *dst, size_t dsz, char *src, size_t cnt, 1057*0a6a1f1dSLionel Sambuc int byteswap); 1058*0a6a1f1dSLionel Sambuc int (*tof64)(char *dst, size_t dsz, char *src, size_t cnt, 1059*0a6a1f1dSLionel Sambuc int byteswap); 1060*0a6a1f1dSLionel Sambuc int (*tom64)(char *dst, size_t dsz, char *src, size_t cnt, 1061*0a6a1f1dSLionel Sambuc int byteswap); 1062*0a6a1f1dSLionel Sambuc}; 1063*0a6a1f1dSLionel Sambuc 1064*0a6a1f1dSLionel Sambuc 1065*0a6a1f1dSLionel Sambucstatic struct converters cvt[ELF_T_NUM] = { 1066*0a6a1f1dSLionel Sambuc /*[*/ 1067*0a6a1f1dSLionel SambucCONVERTER_NAMES(ELF_TYPE_LIST) 1068*0a6a1f1dSLionel Sambuc /*]*/ 1069*0a6a1f1dSLionel Sambuc 1070*0a6a1f1dSLionel Sambuc /* 1071*0a6a1f1dSLionel Sambuc * Types that need hand-coded converters follow. 1072*0a6a1f1dSLionel Sambuc */ 1073*0a6a1f1dSLionel Sambuc 1074*0a6a1f1dSLionel Sambuc [ELF_T_BYTE] = { 1075*0a6a1f1dSLionel Sambuc .tof32 = _libelf_cvt_BYTE_tox, 1076*0a6a1f1dSLionel Sambuc .tom32 = _libelf_cvt_BYTE_tox, 1077*0a6a1f1dSLionel Sambuc .tof64 = _libelf_cvt_BYTE_tox, 1078*0a6a1f1dSLionel Sambuc .tom64 = _libelf_cvt_BYTE_tox 1079*0a6a1f1dSLionel Sambuc }, 1080*0a6a1f1dSLionel Sambuc 1081*0a6a1f1dSLionel Sambuc [ELF_T_NOTE] = { 1082*0a6a1f1dSLionel Sambuc .tof32 = _libelf_cvt_NOTE_tof, 1083*0a6a1f1dSLionel Sambuc .tom32 = _libelf_cvt_NOTE_tom, 1084*0a6a1f1dSLionel Sambuc .tof64 = _libelf_cvt_NOTE_tof, 1085*0a6a1f1dSLionel Sambuc .tom64 = _libelf_cvt_NOTE_tom 1086*0a6a1f1dSLionel Sambuc } 1087*0a6a1f1dSLionel Sambuc}; 1088*0a6a1f1dSLionel Sambuc 1089*0a6a1f1dSLionel Sambucint (*_libelf_get_translator(Elf_Type t, int direction, int elfclass)) 1090*0a6a1f1dSLionel Sambuc (char *_dst, size_t dsz, char *_src, size_t _cnt, int _byteswap) 1091*0a6a1f1dSLionel Sambuc{ 1092*0a6a1f1dSLionel Sambuc assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); 1093*0a6a1f1dSLionel Sambuc assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY); 1094*0a6a1f1dSLionel Sambuc 1095*0a6a1f1dSLionel Sambuc if (t >= ELF_T_NUM || 1096*0a6a1f1dSLionel Sambuc (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) || 1097*0a6a1f1dSLionel Sambuc (direction != ELF_TOFILE && direction != ELF_TOMEMORY)) 1098*0a6a1f1dSLionel Sambuc return (NULL); 1099*0a6a1f1dSLionel Sambuc 1100*0a6a1f1dSLionel Sambuc return ((elfclass == ELFCLASS32) ? 1101*0a6a1f1dSLionel Sambuc (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) : 1102*0a6a1f1dSLionel Sambuc (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64)); 1103*0a6a1f1dSLionel Sambuc} 1104