1164190Sjkoshy/*- 2210344Skaiw * Copyright (c) 2006-2008 Joseph Koshy 3164190Sjkoshy * All rights reserved. 4164190Sjkoshy * 5164190Sjkoshy * Redistribution and use in source and binary forms, with or without 6164190Sjkoshy * modification, are permitted provided that the following conditions 7164190Sjkoshy * are met: 8164190Sjkoshy * 1. Redistributions of source code must retain the above copyright 9164190Sjkoshy * notice, this list of conditions and the following disclaimer. 10164190Sjkoshy * 2. Redistributions in binary form must reproduce the above copyright 11164190Sjkoshy * notice, this list of conditions and the following disclaimer in the 12164190Sjkoshy * documentation and/or other materials provided with the distribution. 13164190Sjkoshy * 14164190Sjkoshy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15164190Sjkoshy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16164190Sjkoshy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17164190Sjkoshy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18164190Sjkoshy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19164190Sjkoshy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20164190Sjkoshy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21164190Sjkoshy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22164190Sjkoshy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23164190Sjkoshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24164190Sjkoshy * SUCH DAMAGE. 25164190Sjkoshy */ 26164190Sjkoshy 27164190Sjkoshy#include <sys/cdefs.h> 28164190Sjkoshy__FBSDID("$FreeBSD: releng/10.2/lib/libelf/libelf_convert.m4 219126 2011-03-01 11:47:51Z brucec $"); 29164190Sjkoshy 30164190Sjkoshy#include <sys/types.h> 31164190Sjkoshy#include <sys/elf32.h> 32164190Sjkoshy#include <sys/elf64.h> 33164190Sjkoshy 34164190Sjkoshy#include <assert.h> 35164190Sjkoshy#include <libelf.h> 36165317Sjkoshy#include <osreldate.h> 37164190Sjkoshy#include <string.h> 38164190Sjkoshy 39164190Sjkoshy#include "_libelf.h" 40164190Sjkoshy 41164190Sjkoshy/* WARNING: GENERATED FROM __file__. */ 42164190Sjkoshy 43164190Sjkoshy/* 44164190Sjkoshy * Macros to swap various integral quantities. 45164190Sjkoshy */ 46164190Sjkoshy 47164190Sjkoshy#define SWAP_HALF(X) do { \ 48164190Sjkoshy uint16_t _x = (uint16_t) (X); \ 49164190Sjkoshy uint16_t _t = _x & 0xFF; \ 50164190Sjkoshy _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 51164190Sjkoshy (X) = _t; \ 52164190Sjkoshy } while (0) 53164190Sjkoshy#define SWAP_WORD(X) do { \ 54164190Sjkoshy uint32_t _x = (uint32_t) (X); \ 55164190Sjkoshy uint32_t _t = _x & 0xFF; \ 56164190Sjkoshy _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 57164190Sjkoshy _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 58164190Sjkoshy _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 59164190Sjkoshy (X) = _t; \ 60164190Sjkoshy } while (0) 61164190Sjkoshy#define SWAP_ADDR32(X) SWAP_WORD(X) 62164190Sjkoshy#define SWAP_OFF32(X) SWAP_WORD(X) 63164190Sjkoshy#define SWAP_SWORD(X) SWAP_WORD(X) 64164190Sjkoshy#define SWAP_WORD64(X) do { \ 65164190Sjkoshy uint64_t _x = (uint64_t) (X); \ 66164190Sjkoshy uint64_t _t = _x & 0xFF; \ 67164190Sjkoshy _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 68164190Sjkoshy _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 69164190Sjkoshy _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 70164190Sjkoshy _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 71164190Sjkoshy _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 72164190Sjkoshy _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 73164190Sjkoshy _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 74164190Sjkoshy (X) = _t; \ 75164190Sjkoshy } while (0) 76164190Sjkoshy#define SWAP_ADDR64(X) SWAP_WORD64(X) 77164190Sjkoshy#define SWAP_LWORD(X) SWAP_WORD64(X) 78164190Sjkoshy#define SWAP_OFF64(X) SWAP_WORD64(X) 79164190Sjkoshy#define SWAP_SXWORD(X) SWAP_WORD64(X) 80164190Sjkoshy#define SWAP_XWORD(X) SWAP_WORD64(X) 81164190Sjkoshy 82164190Sjkoshy/* 83164190Sjkoshy * Write out various integral values. The destination pointer could 84164190Sjkoshy * be unaligned. Values are written out in native byte order. The 85164190Sjkoshy * destination pointer is incremented after the write. 86164190Sjkoshy */ 87164190Sjkoshy#define WRITE_BYTE(P,X) do { \ 88210344Skaiw char *const _p = (char *) (P); \ 89210344Skaiw _p[0] = (char) (X); \ 90164190Sjkoshy (P) = _p + 1; \ 91164190Sjkoshy } while (0) 92164190Sjkoshy#define WRITE_HALF(P,X) do { \ 93164190Sjkoshy uint16_t _t = (X); \ 94210344Skaiw char *const _p = (char *) (P); \ 95210344Skaiw const char *const _q = (char *) &_t; \ 96164190Sjkoshy _p[0] = _q[0]; \ 97164190Sjkoshy _p[1] = _q[1]; \ 98164190Sjkoshy (P) = _p + 2; \ 99164190Sjkoshy } while (0) 100164190Sjkoshy#define WRITE_WORD(P,X) do { \ 101164190Sjkoshy uint32_t _t = (X); \ 102210344Skaiw char *const _p = (char *) (P); \ 103210344Skaiw const char *const _q = (char *) &_t; \ 104164190Sjkoshy _p[0] = _q[0]; \ 105164190Sjkoshy _p[1] = _q[1]; \ 106164190Sjkoshy _p[2] = _q[2]; \ 107164190Sjkoshy _p[3] = _q[3]; \ 108164190Sjkoshy (P) = _p + 4; \ 109164190Sjkoshy } while (0) 110164190Sjkoshy#define WRITE_ADDR32(P,X) WRITE_WORD(P,X) 111164190Sjkoshy#define WRITE_OFF32(P,X) WRITE_WORD(P,X) 112164190Sjkoshy#define WRITE_SWORD(P,X) WRITE_WORD(P,X) 113164190Sjkoshy#define WRITE_WORD64(P,X) do { \ 114164190Sjkoshy uint64_t _t = (X); \ 115210344Skaiw char *const _p = (char *) (P); \ 116210344Skaiw const char *const _q = (char *) &_t; \ 117164190Sjkoshy _p[0] = _q[0]; \ 118164190Sjkoshy _p[1] = _q[1]; \ 119164190Sjkoshy _p[2] = _q[2]; \ 120164190Sjkoshy _p[3] = _q[3]; \ 121164190Sjkoshy _p[4] = _q[4]; \ 122164190Sjkoshy _p[5] = _q[5]; \ 123164190Sjkoshy _p[6] = _q[6]; \ 124164190Sjkoshy _p[7] = _q[7]; \ 125164190Sjkoshy (P) = _p + 8; \ 126164190Sjkoshy } while (0) 127164190Sjkoshy#define WRITE_ADDR64(P,X) WRITE_WORD64(P,X) 128164190Sjkoshy#define WRITE_LWORD(P,X) WRITE_WORD64(P,X) 129164190Sjkoshy#define WRITE_OFF64(P,X) WRITE_WORD64(P,X) 130164190Sjkoshy#define WRITE_SXWORD(P,X) WRITE_WORD64(P,X) 131164190Sjkoshy#define WRITE_XWORD(P,X) WRITE_WORD64(P,X) 132164190Sjkoshy#define WRITE_IDENT(P,X) do { \ 133164190Sjkoshy (void) memcpy((P), (X), sizeof((X))); \ 134164190Sjkoshy (P) = (P) + EI_NIDENT; \ 135164190Sjkoshy } while (0) 136164190Sjkoshy 137164190Sjkoshy/* 138164190Sjkoshy * Read in various integral values. The source pointer could be 139219126Sbrucec * unaligned. Values are read in native byte order. The source 140164190Sjkoshy * pointer is incremented appropriately. 141164190Sjkoshy */ 142164190Sjkoshy 143164190Sjkoshy#define READ_BYTE(P,X) do { \ 144210344Skaiw const char *const _p = \ 145210344Skaiw (const char *) (P); \ 146164190Sjkoshy (X) = _p[0]; \ 147164190Sjkoshy (P) = (P) + 1; \ 148164190Sjkoshy } while (0) 149164190Sjkoshy#define READ_HALF(P,X) do { \ 150164190Sjkoshy uint16_t _t; \ 151210344Skaiw char *const _q = (char *) &_t; \ 152210344Skaiw const char *const _p = \ 153210344Skaiw (const char *) (P); \ 154164190Sjkoshy _q[0] = _p[0]; \ 155164190Sjkoshy _q[1] = _p[1]; \ 156164190Sjkoshy (P) = (P) + 2; \ 157164190Sjkoshy (X) = _t; \ 158164190Sjkoshy } while (0) 159164190Sjkoshy#define READ_WORD(P,X) do { \ 160164190Sjkoshy uint32_t _t; \ 161210344Skaiw char *const _q = (char *) &_t; \ 162210344Skaiw const char *const _p = \ 163210344Skaiw (const char *) (P); \ 164164190Sjkoshy _q[0] = _p[0]; \ 165164190Sjkoshy _q[1] = _p[1]; \ 166164190Sjkoshy _q[2] = _p[2]; \ 167164190Sjkoshy _q[3] = _p[3]; \ 168164190Sjkoshy (P) = (P) + 4; \ 169164190Sjkoshy (X) = _t; \ 170164190Sjkoshy } while (0) 171164190Sjkoshy#define READ_ADDR32(P,X) READ_WORD(P,X) 172164190Sjkoshy#define READ_OFF32(P,X) READ_WORD(P,X) 173164190Sjkoshy#define READ_SWORD(P,X) READ_WORD(P,X) 174164190Sjkoshy#define READ_WORD64(P,X) do { \ 175164190Sjkoshy uint64_t _t; \ 176210344Skaiw char *const _q = (char *) &_t; \ 177210344Skaiw const char *const _p = \ 178210344Skaiw (const char *) (P); \ 179164190Sjkoshy _q[0] = _p[0]; \ 180164190Sjkoshy _q[1] = _p[1]; \ 181164190Sjkoshy _q[2] = _p[2]; \ 182164190Sjkoshy _q[3] = _p[3]; \ 183164190Sjkoshy _q[4] = _p[4]; \ 184164190Sjkoshy _q[5] = _p[5]; \ 185164190Sjkoshy _q[6] = _p[6]; \ 186164190Sjkoshy _q[7] = _p[7]; \ 187164190Sjkoshy (P) = (P) + 8; \ 188164190Sjkoshy (X) = _t; \ 189164190Sjkoshy } while (0) 190164190Sjkoshy#define READ_ADDR64(P,X) READ_WORD64(P,X) 191164190Sjkoshy#define READ_LWORD(P,X) READ_WORD64(P,X) 192164190Sjkoshy#define READ_OFF64(P,X) READ_WORD64(P,X) 193164190Sjkoshy#define READ_SXWORD(P,X) READ_WORD64(P,X) 194164190Sjkoshy#define READ_XWORD(P,X) READ_WORD64(P,X) 195164190Sjkoshy#define READ_IDENT(P,X) do { \ 196164190Sjkoshy (void) memcpy((X), (P), sizeof((X))); \ 197164190Sjkoshy (P) = (P) + EI_NIDENT; \ 198164190Sjkoshy } while (0) 199164190Sjkoshy 200164190Sjkoshy#define ROUNDUP2(V,N) (V) = ((((V) + (N) - 1)) & ~((N) - 1)) 201164190Sjkoshy 202164190Sjkoshydivert(-1) 203164190Sjkoshy 204164190Sjkoshy/* 205164190Sjkoshy * Generate conversion routines for converting between in-memory and 206164190Sjkoshy * file representations of Elf data structures. 207164190Sjkoshy * 208164190Sjkoshy * `In-memory' representations of an Elf data structure use natural 209164190Sjkoshy * alignments and native byte ordering. This allows arithmetic and 210164190Sjkoshy * casting to work as expected. On the other hand the `file' 211164190Sjkoshy * representation of an ELF data structure could be packed tighter 212164190Sjkoshy * than its `in-memory' representation, and could be of a differing 213164190Sjkoshy * byte order. An additional complication is that `ar' only pads data 214164190Sjkoshy * to even addresses and so ELF archive member data being read from 215164190Sjkoshy * inside an `ar' archive could end up at misaligned memory addresses. 216164190Sjkoshy * 217164190Sjkoshy * Consequently, casting the `char *' pointers that point to memory 218164190Sjkoshy * representations (i.e., source pointers for the *_tof() functions 219164190Sjkoshy * and the destination pointers for the *_tom() functions), is safe, 220164190Sjkoshy * as these pointers should be correctly aligned for the memory type 221164190Sjkoshy * already. However, pointers to file representations have to be 222164190Sjkoshy * treated as being potentially unaligned and no casting can be done. 223164190Sjkoshy */ 224164190Sjkoshy 225164190Sjkoshyinclude(SRCDIR`/elf_types.m4') 226164190Sjkoshy 227164190Sjkoshy/* 228164190Sjkoshy * `IGNORE'_* flags turn off generation of template code. 229164190Sjkoshy */ 230164190Sjkoshy 231164190Sjkoshydefine(`IGNORE', 232164190Sjkoshy `define(IGNORE_$1`'32, 1) 233164190Sjkoshy define(IGNORE_$1`'64, 1)') 234164190Sjkoshy 235164190SjkoshyIGNORE(MOVEP) 236164190SjkoshyIGNORE(NOTE) 237210341SkaiwIGNORE(GNUHASH) 238164190Sjkoshy 239164190Sjkoshydefine(IGNORE_BYTE, 1) /* 'lator, leave 'em bytes alone */ 240210338Skaiwdefine(IGNORE_GNUHASH, 1) 241164190Sjkoshydefine(IGNORE_NOTE, 1) 242164190Sjkoshydefine(IGNORE_SXWORD32, 1) 243164190Sjkoshydefine(IGNORE_XWORD32, 1) 244164190Sjkoshy 245164190Sjkoshy/* 246164190Sjkoshy * `BASE'_XXX flags cause class agnostic template functions 247164190Sjkoshy * to be generated. 248164190Sjkoshy */ 249164190Sjkoshy 250164190Sjkoshydefine(`BASE_BYTE', 1) 251164190Sjkoshydefine(`BASE_HALF', 1) 252164190Sjkoshydefine(`BASE_NOTE', 1) 253164190Sjkoshydefine(`BASE_WORD', 1) 254164190Sjkoshydefine(`BASE_LWORD', 1) 255164190Sjkoshydefine(`BASE_SWORD', 1) 256164190Sjkoshydefine(`BASE_XWORD', 1) 257164190Sjkoshydefine(`BASE_SXWORD', 1) 258164190Sjkoshy 259164190Sjkoshy/* 260164190Sjkoshy * `SIZEDEP'_XXX flags cause 32/64 bit variants to be generated 261164190Sjkoshy * for each primitive type. 262164190Sjkoshy */ 263164190Sjkoshy 264164190Sjkoshydefine(`SIZEDEP_ADDR', 1) 265164190Sjkoshydefine(`SIZEDEP_OFF', 1) 266164190Sjkoshy 267164190Sjkoshy/* 268164190Sjkoshy * `Primitive' ELF types are those that are an alias for an integral 269164190Sjkoshy * type. They have no internal structure. These can be copied using 270164190Sjkoshy * a `memcpy()', and byteswapped in straightforward way. 271164190Sjkoshy * 272164190Sjkoshy * Macro use: 273164190Sjkoshy * `$1': Name of the ELF type. 274164190Sjkoshy * `$2': C structure name suffix 275164190Sjkoshy * `$3': ELF class specifier for symbols, one of [`', `32', `64'] 276164190Sjkoshy * `$4': ELF class specifier for types, one of [`32', `64'] 277164190Sjkoshy */ 278164190Sjkoshydefine(`MAKEPRIM_TO_F',` 279210338Skaiwstatic int 280210338Skaiwlibelf_cvt_$1$3_tof(char *dst, size_t dsz, char *src, size_t count, 281210338Skaiw int byteswap) 282164190Sjkoshy{ 283164190Sjkoshy Elf$4_$2 t, *s = (Elf$4_$2 *) (uintptr_t) src; 284164190Sjkoshy size_t c; 285164190Sjkoshy 286210338Skaiw (void) dsz; 287164190Sjkoshy 288164190Sjkoshy if (!byteswap) { 289164190Sjkoshy (void) memcpy(dst, src, count * sizeof(*s)); 290210338Skaiw return (1); 291164190Sjkoshy } 292164190Sjkoshy 293164190Sjkoshy for (c = 0; c < count; c++) { 294164190Sjkoshy t = *s++; 295164190Sjkoshy SWAP_$1$3(t); 296164190Sjkoshy WRITE_$1$3(dst,t); 297164190Sjkoshy } 298210338Skaiw 299210338Skaiw return (1); 300164190Sjkoshy} 301164190Sjkoshy') 302164190Sjkoshy 303164190Sjkoshydefine(`MAKEPRIM_TO_M',` 304210338Skaiwstatic int 305210338Skaiwlibelf_cvt_$1$3_tom(char *dst, size_t dsz, char *src, size_t count, 306210338Skaiw int byteswap) 307164190Sjkoshy{ 308164190Sjkoshy Elf$4_$2 t, *d = (Elf$4_$2 *) (uintptr_t) dst; 309164190Sjkoshy size_t c; 310164190Sjkoshy 311210338Skaiw if (dsz < count * sizeof(Elf$4_$2)) 312210338Skaiw return (0); 313164190Sjkoshy 314164190Sjkoshy if (!byteswap) { 315164190Sjkoshy (void) memcpy(dst, src, count * sizeof(*d)); 316210338Skaiw return (1); 317164190Sjkoshy } 318164190Sjkoshy 319164190Sjkoshy for (c = 0; c < count; c++) { 320164190Sjkoshy READ_$1$3(src,t); 321164190Sjkoshy SWAP_$1$3(t); 322164190Sjkoshy *d++ = t; 323164190Sjkoshy } 324210338Skaiw 325210338Skaiw return (1); 326164190Sjkoshy} 327164190Sjkoshy') 328164190Sjkoshy 329164190Sjkoshydefine(`SWAP_FIELD', 330164190Sjkoshy `ifdef(`IGNORE_'$2,`', 331164190Sjkoshy `ifelse(BASE_$2,1, 332164190Sjkoshy `SWAP_$2(t.$1); 333164190Sjkoshy ', 334164190Sjkoshy `ifelse($2,BYTE,`', 335164190Sjkoshy `ifelse($2,IDENT,`', 336164190Sjkoshy `SWAP_$2'SZ()`(t.$1); 337164190Sjkoshy ')')')')') 338164190Sjkoshydefine(`SWAP_MEMBERS', 339164190Sjkoshy `ifelse($#,1,`/**/', 340164190Sjkoshy `SWAP_FIELD($1)SWAP_MEMBERS(shift($@))')') 341164190Sjkoshy 342164190Sjkoshydefine(`SWAP_STRUCT', 343164190Sjkoshy `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */ 344164190Sjkoshy SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') 345164190Sjkoshy 346164190Sjkoshydefine(`WRITE_FIELD', 347164190Sjkoshy `ifelse(BASE_$2,1, 348164190Sjkoshy `WRITE_$2(dst,t.$1); 349164190Sjkoshy ', 350164190Sjkoshy `ifelse($2,IDENT, 351164190Sjkoshy `WRITE_$2(dst,t.$1); 352164190Sjkoshy ', 353164190Sjkoshy `WRITE_$2'SZ()`(dst,t.$1); 354164190Sjkoshy ')')') 355164190Sjkoshydefine(`WRITE_MEMBERS', 356164190Sjkoshy `ifelse($#,1,`/**/', 357164190Sjkoshy `WRITE_FIELD($1)WRITE_MEMBERS(shift($@))')') 358164190Sjkoshy 359164190Sjkoshydefine(`WRITE_STRUCT', 360164190Sjkoshy `pushdef(`SZ',$2)/* Write an Elf$2_$1 */ 361164190Sjkoshy WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') 362164190Sjkoshy 363164190Sjkoshydefine(`READ_FIELD', 364164190Sjkoshy `ifelse(BASE_$2,1, 365164190Sjkoshy `READ_$2(s,t.$1); 366164190Sjkoshy ', 367164190Sjkoshy `ifelse($2,IDENT, 368164190Sjkoshy `READ_$2(s,t.$1); 369164190Sjkoshy ', 370164190Sjkoshy `READ_$2'SZ()`(s,t.$1); 371164190Sjkoshy ')')') 372164190Sjkoshy 373164190Sjkoshydefine(`READ_MEMBERS', 374164190Sjkoshy `ifelse($#,1,`/**/', 375164190Sjkoshy `READ_FIELD($1)READ_MEMBERS(shift($@))')') 376164190Sjkoshy 377164190Sjkoshydefine(`READ_STRUCT', 378164190Sjkoshy `pushdef(`SZ',$2)/* Read an Elf$2_$1 */ 379164190Sjkoshy READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') 380164190Sjkoshy 381164190Sjkoshy/* 382164190Sjkoshy * Converters for non-integral ELF data structures. 383164190Sjkoshy * 384164190Sjkoshy * When converting data to file representation, the source pointer 385164190Sjkoshy * will be naturally aligned for a data structure's in-memory 386164190Sjkoshy * representation. When converting data to memory, the destination 387164190Sjkoshy * pointer will be similarly aligned. 388164190Sjkoshy * 389164190Sjkoshy * For in-place conversions, when converting to file representations, 390164190Sjkoshy * the source buffer is large enough to hold `file' data. When 391164190Sjkoshy * converting from file to memory, we need to be careful to work 392164190Sjkoshy * `backwards', to avoid overwriting unconverted data. 393164190Sjkoshy * 394164190Sjkoshy * Macro use: 395164190Sjkoshy * `$1': Name of the ELF type. 396164190Sjkoshy * `$2': C structure name suffix. 397164190Sjkoshy * `$3': ELF class specifier, one of [`', `32', `64'] 398164190Sjkoshy */ 399164190Sjkoshy 400164190Sjkoshydefine(`MAKE_TO_F', 401164190Sjkoshy `ifdef(`IGNORE_'$1$3,`',` 402210338Skaiwstatic int 403210338Skaiwlibelf_cvt$3_$1_tof(char *dst, size_t dsz, char *src, size_t count, 404210338Skaiw int byteswap) 405164190Sjkoshy{ 406164190Sjkoshy Elf$3_$2 t, *s; 407164190Sjkoshy size_t c; 408164190Sjkoshy 409210338Skaiw (void) dsz; 410210338Skaiw 411164190Sjkoshy s = (Elf$3_$2 *) (uintptr_t) src; 412164190Sjkoshy for (c = 0; c < count; c++) { 413164190Sjkoshy t = *s++; 414164190Sjkoshy if (byteswap) { 415164190Sjkoshy SWAP_STRUCT($2,$3) 416164190Sjkoshy } 417164190Sjkoshy WRITE_STRUCT($2,$3) 418164190Sjkoshy } 419210338Skaiw 420210338Skaiw return (1); 421164190Sjkoshy} 422164190Sjkoshy')') 423164190Sjkoshy 424164190Sjkoshydefine(`MAKE_TO_M', 425164190Sjkoshy `ifdef(`IGNORE_'$1$3,`',` 426210338Skaiwstatic int 427210338Skaiwlibelf_cvt$3_$1_tom(char *dst, size_t dsz, char *src, size_t count, 428210338Skaiw int byteswap) 429164190Sjkoshy{ 430164190Sjkoshy Elf$3_$2 t, *d; 431210344Skaiw char *s,*s0; 432164190Sjkoshy size_t fsz; 433164190Sjkoshy 434164190Sjkoshy fsz = elf$3_fsize(ELF_T_$1, (size_t) 1, EV_CURRENT); 435164190Sjkoshy d = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1); 436210344Skaiw s0 = (char *) src + (count - 1) * fsz; 437164190Sjkoshy 438210338Skaiw if (dsz < count * sizeof(Elf$3_$2)) 439210338Skaiw return (0); 440210338Skaiw 441164190Sjkoshy while (count--) { 442164190Sjkoshy s = s0; 443164190Sjkoshy READ_STRUCT($2,$3) 444164190Sjkoshy if (byteswap) { 445164190Sjkoshy SWAP_STRUCT($2,$3) 446164190Sjkoshy } 447164190Sjkoshy *d-- = t; s0 -= fsz; 448164190Sjkoshy } 449210338Skaiw 450210338Skaiw return (1); 451164190Sjkoshy} 452164190Sjkoshy')') 453164190Sjkoshy 454164190Sjkoshy/* 455164190Sjkoshy * Make type convertor functions from the type definition 456164190Sjkoshy * of the ELF type: 457164190Sjkoshy * - if the type is a base (i.e., `primitive') type: 458164190Sjkoshy * - if it is marked as to be ignored (i.e., `IGNORE_'TYPE) 459164190Sjkoshy * is defined, we skip the code generation step. 460164190Sjkoshy * - if the type is declared as `SIZEDEP', then 32 and 64 bit 461164190Sjkoshy * variants of the conversion functions are generated. 462164190Sjkoshy * - otherwise a 32 bit variant is generated. 463164190Sjkoshy * - if the type is a structure type, we generate 32 and 64 bit 464164190Sjkoshy * variants of the conversion functions. 465164190Sjkoshy */ 466164190Sjkoshy 467164190Sjkoshydefine(`MAKE_TYPE_CONVERTER', 468165317Sjkoshy `#if __FreeBSD_version >= $3 /* $1 */ 469165317Sjkoshyifdef(`BASE'_$1, 470164190Sjkoshy `ifdef(`IGNORE_'$1,`', 471164190Sjkoshy `MAKEPRIM_TO_F($1,$2,`',64) 472164190Sjkoshy MAKEPRIM_TO_M($1,$2,`',64)')', 473164190Sjkoshy `ifdef(`SIZEDEP_'$1, 474164190Sjkoshy `MAKEPRIM_TO_F($1,$2,32,32)dnl 475164190Sjkoshy MAKEPRIM_TO_M($1,$2,32,32)dnl 476164190Sjkoshy MAKEPRIM_TO_F($1,$2,64,64)dnl 477164190Sjkoshy MAKEPRIM_TO_M($1,$2,64,64)', 478164190Sjkoshy `MAKE_TO_F($1,$2,32)dnl 479164190Sjkoshy MAKE_TO_F($1,$2,64)dnl 480164190Sjkoshy MAKE_TO_M($1,$2,32)dnl 481165317Sjkoshy MAKE_TO_M($1,$2,64)')') 482165317Sjkoshy#endif /* $1 */ 483165317Sjkoshy') 484164190Sjkoshy 485164190Sjkoshydefine(`MAKE_TYPE_CONVERTERS', 486164190Sjkoshy `ifelse($#,1,`', 487164190Sjkoshy `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')') 488164190Sjkoshy 489164190Sjkoshydivert(0) 490164190Sjkoshy 491164190Sjkoshy/* 492164190Sjkoshy * Sections of type ELF_T_BYTE are never byteswapped, consequently a 493164190Sjkoshy * simple memcpy suffices for both directions of conversion. 494164190Sjkoshy */ 495164190Sjkoshy 496210338Skaiwstatic int 497210338Skaiwlibelf_cvt_BYTE_tox(char *dst, size_t dsz, char *src, size_t count, 498210338Skaiw int byteswap) 499164190Sjkoshy{ 500164190Sjkoshy (void) byteswap; 501210338Skaiw if (dsz < count) 502210338Skaiw return (0); 503164190Sjkoshy if (dst != src) 504164190Sjkoshy (void) memcpy(dst, src, count); 505210338Skaiw return (1); 506164190Sjkoshy} 507164190Sjkoshy 508210341SkaiwMAKE_TYPE_CONVERTERS(ELF_TYPE_LIST) 509210341Skaiw 510210559Skaiw#if __FreeBSD_version >= 800062 511164190Sjkoshy/* 512210341Skaiw * Sections of type ELF_T_GNUHASH start with a header containing 4 32-bit 513210341Skaiw * words. Bloom filter data comes next, followed by hash buckets and the 514210341Skaiw * hash chain. 515210341Skaiw * 516210341Skaiw * Bloom filter words are 64 bit wide on ELFCLASS64 objects and are 32 bit 517210341Skaiw * wide on ELFCLASS32 objects. The other objects in this section are 32 518210341Skaiw * bits wide. 519210341Skaiw * 520210341Skaiw * Argument `srcsz' denotes the number of bytes to be converted. In the 521210341Skaiw * 32-bit case we need to translate `srcsz' to a count of 32-bit words. 522210341Skaiw */ 523210341Skaiw 524210341Skaiwstatic int 525210341Skaiwlibelf_cvt32_GNUHASH_tom(char *dst, size_t dsz, char *src, size_t srcsz, 526210341Skaiw int byteswap) 527210341Skaiw{ 528210341Skaiw return (libelf_cvt_WORD_tom(dst, dsz, src, srcsz / sizeof(uint32_t), 529210341Skaiw byteswap)); 530210341Skaiw} 531210341Skaiw 532210341Skaiwstatic int 533210341Skaiwlibelf_cvt32_GNUHASH_tof(char *dst, size_t dsz, char *src, size_t srcsz, 534210341Skaiw int byteswap) 535210341Skaiw{ 536210341Skaiw return (libelf_cvt_WORD_tof(dst, dsz, src, srcsz / sizeof(uint32_t), 537210341Skaiw byteswap)); 538210341Skaiw} 539210341Skaiw 540210341Skaiwstatic int 541210341Skaiwlibelf_cvt64_GNUHASH_tom(char *dst, size_t dsz, char *src, size_t srcsz, 542210341Skaiw int byteswap) 543210341Skaiw{ 544210341Skaiw size_t sz; 545210341Skaiw uint64_t t64, *bloom64; 546210341Skaiw Elf_GNU_Hash_Header *gh; 547210341Skaiw uint32_t n, nbuckets, nchains, maskwords, shift2, symndx, t32; 548210341Skaiw uint32_t *buckets, *chains; 549210341Skaiw 550210341Skaiw sz = 4 * sizeof(uint32_t); /* File header is 4 words long. */ 551210341Skaiw if (dsz < sizeof(Elf_GNU_Hash_Header) || srcsz < sz) 552210341Skaiw return (0); 553210341Skaiw 554210341Skaiw /* Read in the section header and byteswap if needed. */ 555210341Skaiw READ_WORD(src, nbuckets); 556210341Skaiw READ_WORD(src, symndx); 557210341Skaiw READ_WORD(src, maskwords); 558210341Skaiw READ_WORD(src, shift2); 559210341Skaiw 560210341Skaiw srcsz -= sz; 561210341Skaiw 562210341Skaiw if (byteswap) { 563210341Skaiw SWAP_WORD(nbuckets); 564210341Skaiw SWAP_WORD(symndx); 565210341Skaiw SWAP_WORD(maskwords); 566210341Skaiw SWAP_WORD(shift2); 567210341Skaiw } 568210341Skaiw 569210341Skaiw /* Check source buffer and destination buffer sizes. */ 570210341Skaiw sz = nbuckets * sizeof(uint32_t) + maskwords * sizeof(uint64_t); 571210341Skaiw if (srcsz < sz || dsz < sz + sizeof(Elf_GNU_Hash_Header)) 572210341Skaiw return (0); 573210341Skaiw 574210341Skaiw gh = (Elf_GNU_Hash_Header *) (uintptr_t) dst; 575210341Skaiw gh->gh_nbuckets = nbuckets; 576210341Skaiw gh->gh_symndx = symndx; 577210341Skaiw gh->gh_maskwords = maskwords; 578210341Skaiw gh->gh_shift2 = shift2; 579210341Skaiw 580210341Skaiw dsz -= sizeof(Elf_GNU_Hash_Header); 581210341Skaiw dst += sizeof(Elf_GNU_Hash_Header); 582210341Skaiw 583210341Skaiw bloom64 = (uint64_t *) (uintptr_t) dst; 584210341Skaiw 585210341Skaiw /* Copy bloom filter data. */ 586210341Skaiw for (n = 0; n < maskwords; n++) { 587210341Skaiw READ_XWORD(src, t64); 588210341Skaiw if (byteswap) 589210341Skaiw SWAP_XWORD(t64); 590210341Skaiw bloom64[n] = t64; 591210341Skaiw } 592210341Skaiw 593210341Skaiw /* The hash buckets follows the bloom filter. */ 594210341Skaiw dst += maskwords * sizeof(uint64_t); 595210341Skaiw buckets = (uint32_t *) (uintptr_t) dst; 596210341Skaiw 597210341Skaiw for (n = 0; n < nbuckets; n++) { 598210341Skaiw READ_WORD(src, t32); 599210341Skaiw if (byteswap) 600210341Skaiw SWAP_WORD(t32); 601210341Skaiw buckets[n] = t32; 602210341Skaiw } 603210341Skaiw 604210341Skaiw dst += nbuckets * sizeof(uint32_t); 605210341Skaiw 606210341Skaiw /* The hash chain follows the hash buckets. */ 607210341Skaiw dsz -= sz; 608210341Skaiw srcsz -= sz; 609210341Skaiw 610210341Skaiw if (dsz < srcsz) /* Destination lacks space. */ 611210341Skaiw return (0); 612210341Skaiw 613210341Skaiw nchains = srcsz / sizeof(uint32_t); 614210341Skaiw chains = (uint32_t *) (uintptr_t) dst; 615210341Skaiw 616210341Skaiw for (n = 0; n < nchains; n++) { 617210341Skaiw READ_WORD(src, t32); 618210341Skaiw if (byteswap) 619210341Skaiw SWAP_WORD(t32); 620210341Skaiw *chains++ = t32; 621210341Skaiw } 622210341Skaiw 623210341Skaiw return (1); 624210341Skaiw} 625210341Skaiw 626210341Skaiwstatic int 627210341Skaiwlibelf_cvt64_GNUHASH_tof(char *dst, size_t dsz, char *src, size_t srcsz, 628210341Skaiw int byteswap) 629210341Skaiw{ 630210341Skaiw uint32_t *s32; 631210341Skaiw size_t sz, hdrsz; 632210341Skaiw uint64_t *s64, t64; 633210341Skaiw Elf_GNU_Hash_Header *gh; 634210341Skaiw uint32_t maskwords, n, nbuckets, nchains, t0, t1, t2, t3, t32; 635210341Skaiw 636210341Skaiw hdrsz = 4 * sizeof(uint32_t); /* Header is 4x32 bits. */ 637210341Skaiw if (dsz < hdrsz || srcsz < sizeof(Elf_GNU_Hash_Header)) 638210341Skaiw return (0); 639210341Skaiw 640210341Skaiw gh = (Elf_GNU_Hash_Header *) (uintptr_t) src; 641210341Skaiw 642210341Skaiw t0 = nbuckets = gh->gh_nbuckets; 643210341Skaiw t1 = gh->gh_symndx; 644210341Skaiw t2 = maskwords = gh->gh_maskwords; 645210341Skaiw t3 = gh->gh_shift2; 646210341Skaiw 647210341Skaiw src += sizeof(Elf_GNU_Hash_Header); 648210341Skaiw srcsz -= sizeof(Elf_GNU_Hash_Header); 649210341Skaiw dsz -= hdrsz; 650210341Skaiw 651210341Skaiw sz = gh->gh_nbuckets * sizeof(uint32_t) + gh->gh_maskwords * 652210341Skaiw sizeof(uint64_t); 653210341Skaiw 654210341Skaiw if (srcsz < sz || dsz < sz) 655210341Skaiw return (0); 656210341Skaiw 657210341Skaiw /* Write out the header. */ 658210341Skaiw if (byteswap) { 659210341Skaiw SWAP_WORD(t0); 660210341Skaiw SWAP_WORD(t1); 661210341Skaiw SWAP_WORD(t2); 662210341Skaiw SWAP_WORD(t3); 663210341Skaiw } 664210341Skaiw 665210341Skaiw WRITE_WORD(dst, t0); 666210341Skaiw WRITE_WORD(dst, t1); 667210341Skaiw WRITE_WORD(dst, t2); 668210341Skaiw WRITE_WORD(dst, t3); 669210341Skaiw 670210341Skaiw /* Copy the bloom filter and the hash table. */ 671210341Skaiw s64 = (uint64_t *) (uintptr_t) src; 672210341Skaiw for (n = 0; n < maskwords; n++) { 673210341Skaiw t64 = *s64++; 674210341Skaiw if (byteswap) 675210341Skaiw SWAP_XWORD(t64); 676210341Skaiw WRITE_WORD64(dst, t64); 677210341Skaiw } 678210341Skaiw 679210341Skaiw s32 = (uint32_t *) s64; 680210341Skaiw for (n = 0; n < nbuckets; n++) { 681210341Skaiw t32 = *s32++; 682210341Skaiw if (byteswap) 683210341Skaiw SWAP_WORD(t32); 684210341Skaiw WRITE_WORD(dst, t32); 685210341Skaiw } 686210341Skaiw 687210341Skaiw srcsz -= sz; 688210341Skaiw dsz -= sz; 689210341Skaiw 690210341Skaiw /* Copy out the hash chains. */ 691210341Skaiw if (dsz < srcsz) 692210341Skaiw return (0); 693210341Skaiw 694210341Skaiw nchains = srcsz / sizeof(uint32_t); 695210341Skaiw for (n = 0; n < nchains; n++) { 696210341Skaiw t32 = *s32++; 697210341Skaiw if (byteswap) 698210341Skaiw SWAP_WORD(t32); 699210341Skaiw WRITE_WORD(dst, t32); 700210341Skaiw } 701210341Skaiw 702210341Skaiw return (1); 703210341Skaiw} 704210559Skaiw#endif 705210341Skaiw 706210341Skaiw/* 707164190Sjkoshy * Elf_Note structures comprise a fixed size header followed by variable 708164190Sjkoshy * length strings. The fixed size header needs to be byte swapped, but 709164190Sjkoshy * not the strings. 710164190Sjkoshy * 711164190Sjkoshy * Argument `count' denotes the total number of bytes to be converted. 712210341Skaiw * The destination buffer needs to be at least `count' bytes in size. 713164190Sjkoshy */ 714210338Skaiwstatic int 715210338Skaiwlibelf_cvt_NOTE_tom(char *dst, size_t dsz, char *src, size_t count, 716210338Skaiw int byteswap) 717164190Sjkoshy{ 718164190Sjkoshy uint32_t namesz, descsz, type; 719164190Sjkoshy Elf_Note *en; 720210338Skaiw size_t sz, hdrsz; 721164190Sjkoshy 722210338Skaiw if (dsz < count) /* Destination buffer is too small. */ 723210338Skaiw return (0); 724164190Sjkoshy 725210338Skaiw hdrsz = 3 * sizeof(uint32_t); 726210338Skaiw if (count < hdrsz) /* Source too small. */ 727210338Skaiw return (0); 728210338Skaiw 729164190Sjkoshy if (!byteswap) { 730164190Sjkoshy (void) memcpy(dst, src, count); 731210338Skaiw return (1); 732164190Sjkoshy } 733164190Sjkoshy 734210338Skaiw /* Process all notes in the section. */ 735210338Skaiw while (count > hdrsz) { 736210338Skaiw /* Read the note header. */ 737164190Sjkoshy READ_WORD(src, namesz); 738164190Sjkoshy READ_WORD(src, descsz); 739164190Sjkoshy READ_WORD(src, type); 740164190Sjkoshy 741210338Skaiw /* Translate. */ 742210338Skaiw SWAP_WORD(namesz); 743210338Skaiw SWAP_WORD(descsz); 744210338Skaiw SWAP_WORD(type); 745164190Sjkoshy 746210338Skaiw /* Copy out the translated note header. */ 747164190Sjkoshy en = (Elf_Note *) (uintptr_t) dst; 748164190Sjkoshy en->n_namesz = namesz; 749164190Sjkoshy en->n_descsz = descsz; 750164190Sjkoshy en->n_type = type; 751164190Sjkoshy 752210338Skaiw dsz -= sizeof(Elf_Note); 753164190Sjkoshy dst += sizeof(Elf_Note); 754210338Skaiw count -= hdrsz; 755164190Sjkoshy 756164190Sjkoshy ROUNDUP2(namesz, 4); 757164190Sjkoshy ROUNDUP2(descsz, 4); 758164190Sjkoshy 759164190Sjkoshy sz = namesz + descsz; 760164190Sjkoshy 761210338Skaiw if (count < sz || dsz < sz) /* Buffers are too small. */ 762210338Skaiw return (0); 763164190Sjkoshy 764164190Sjkoshy (void) memcpy(dst, src, sz); 765164190Sjkoshy 766164190Sjkoshy src += sz; 767164190Sjkoshy dst += sz; 768210338Skaiw 769164190Sjkoshy count -= sz; 770210341Skaiw dsz -= sz; 771164190Sjkoshy } 772210338Skaiw 773210338Skaiw return (1); 774164190Sjkoshy} 775164190Sjkoshy 776210338Skaiwstatic int 777210338Skaiwlibelf_cvt_NOTE_tof(char *dst, size_t dsz, char *src, size_t count, 778210338Skaiw int byteswap) 779164190Sjkoshy{ 780164190Sjkoshy uint32_t namesz, descsz, type; 781164190Sjkoshy Elf_Note *en; 782164190Sjkoshy size_t sz; 783164190Sjkoshy 784210338Skaiw if (dsz < count) 785210338Skaiw return (0); 786164190Sjkoshy 787164190Sjkoshy if (!byteswap) { 788164190Sjkoshy (void) memcpy(dst, src, count); 789210338Skaiw return (1); 790164190Sjkoshy } 791164190Sjkoshy 792164190Sjkoshy while (count > sizeof(Elf_Note)) { 793164190Sjkoshy 794164190Sjkoshy en = (Elf_Note *) (uintptr_t) src; 795164190Sjkoshy namesz = en->n_namesz; 796164190Sjkoshy descsz = en->n_descsz; 797164190Sjkoshy type = en->n_type; 798164190Sjkoshy 799210338Skaiw SWAP_WORD(namesz); 800210338Skaiw SWAP_WORD(descsz); 801210338Skaiw SWAP_WORD(type); 802164190Sjkoshy 803164190Sjkoshy WRITE_WORD(dst, namesz); 804164190Sjkoshy WRITE_WORD(dst, descsz); 805164190Sjkoshy WRITE_WORD(dst, type); 806164190Sjkoshy 807164190Sjkoshy src += sizeof(Elf_Note); 808164190Sjkoshy 809164190Sjkoshy ROUNDUP2(namesz, 4); 810164190Sjkoshy ROUNDUP2(descsz, 4); 811164190Sjkoshy 812164190Sjkoshy sz = namesz + descsz; 813164190Sjkoshy 814164190Sjkoshy if (count < sz) 815164190Sjkoshy sz = count; 816164190Sjkoshy 817164190Sjkoshy (void) memcpy(dst, src, sz); 818164190Sjkoshy 819164190Sjkoshy src += sz; 820164190Sjkoshy dst += sz; 821164190Sjkoshy count -= sz; 822164190Sjkoshy } 823210338Skaiw 824210338Skaiw return (1); 825164190Sjkoshy} 826164190Sjkoshy 827164190Sjkoshystruct converters { 828210338Skaiw int (*tof32)(char *dst, size_t dsz, char *src, size_t cnt, 829210338Skaiw int byteswap); 830210338Skaiw int (*tom32)(char *dst, size_t dsz, char *src, size_t cnt, 831210338Skaiw int byteswap); 832210338Skaiw int (*tof64)(char *dst, size_t dsz, char *src, size_t cnt, 833210338Skaiw int byteswap); 834210338Skaiw int (*tom64)(char *dst, size_t dsz, char *src, size_t cnt, 835210338Skaiw int byteswap); 836164190Sjkoshy}; 837164190Sjkoshy 838164190Sjkoshydivert(-1) 839164190Sjkoshydefine(`CONV', 840164190Sjkoshy `ifdef(`IGNORE_'$1$2, 841164190Sjkoshy `.$3$2 = NULL', 842164190Sjkoshy `ifdef(`BASE_'$1, 843172099Sjkoshy `.$3$2 = libelf_cvt_$1_$3', 844164190Sjkoshy `ifdef(`SIZEDEP_'$1, 845164190Sjkoshy `.$3$2 = libelf_cvt_$1$2_$3', 846164190Sjkoshy `.$3$2 = libelf_cvt$2_$1_$3')')')') 847164190Sjkoshy 848164190Sjkoshydefine(`CONVERTER_NAME', 849172099Sjkoshy `ifdef(`IGNORE_'$1,`', 850172099Sjkoshy `#if __FreeBSD_version >= $3 851165317Sjkoshy [ELF_T_$1] = { 852164190Sjkoshy CONV($1,32,tof), CONV($1,32,tom), 853164190Sjkoshy CONV($1,64,tof), CONV($1,64,tom) }, 854165317Sjkoshy#endif 855164190Sjkoshy')') 856164190Sjkoshy 857164190Sjkoshydefine(`CONVERTER_NAMES', 858164190Sjkoshy `ifelse($#,1,`', 859164190Sjkoshy `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')') 860164190Sjkoshy 861164190Sjkoshyundefine(`IGNORE_BYTE32', `IGNORE_BYTE64') 862164190Sjkoshydivert(0) 863164190Sjkoshy 864164190Sjkoshystatic struct converters cvt[ELF_T_NUM] = { 865164190SjkoshyCONVERTER_NAMES(ELF_TYPE_LIST) 866164190Sjkoshy 867164190Sjkoshy /* 868164190Sjkoshy * Types that needs hand-coded converters follow. 869164190Sjkoshy */ 870164190Sjkoshy 871164190Sjkoshy [ELF_T_BYTE] = { 872164190Sjkoshy .tof32 = libelf_cvt_BYTE_tox, 873164190Sjkoshy .tom32 = libelf_cvt_BYTE_tox, 874164190Sjkoshy .tof64 = libelf_cvt_BYTE_tox, 875164190Sjkoshy .tom64 = libelf_cvt_BYTE_tox 876164190Sjkoshy }, 877210341Skaiw 878210559Skaiw#if __FreeBSD_version >= 800062 879210341Skaiw [ELF_T_GNUHASH] = { 880210341Skaiw .tof32 = libelf_cvt32_GNUHASH_tof, 881210341Skaiw .tom32 = libelf_cvt32_GNUHASH_tom, 882210341Skaiw .tof64 = libelf_cvt64_GNUHASH_tof, 883210341Skaiw .tom64 = libelf_cvt64_GNUHASH_tom 884210341Skaiw }, 885210559Skaiw#endif 886210341Skaiw 887164190Sjkoshy [ELF_T_NOTE] = { 888164190Sjkoshy .tof32 = libelf_cvt_NOTE_tof, 889164190Sjkoshy .tom32 = libelf_cvt_NOTE_tom, 890164190Sjkoshy .tof64 = libelf_cvt_NOTE_tof, 891164190Sjkoshy .tom64 = libelf_cvt_NOTE_tom 892164190Sjkoshy } 893164190Sjkoshy}; 894164190Sjkoshy 895210338Skaiwint (*_libelf_get_translator(Elf_Type t, int direction, int elfclass)) 896210338Skaiw (char *_dst, size_t dsz, char *_src, size_t _cnt, int _byteswap) 897164190Sjkoshy{ 898164190Sjkoshy assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); 899164190Sjkoshy assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY); 900164190Sjkoshy 901164190Sjkoshy if (t >= ELF_T_NUM || 902164190Sjkoshy (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) || 903164190Sjkoshy (direction != ELF_TOFILE && direction != ELF_TOMEMORY)) 904164190Sjkoshy return (NULL); 905164190Sjkoshy 906164190Sjkoshy return ((elfclass == ELFCLASS32) ? 907164190Sjkoshy (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) : 908164190Sjkoshy (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64)); 909164190Sjkoshy} 910