1/*- 2 * Copyright (c) 2006 Joseph Koshy 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/types.h> 28 29#include <assert.h> 30#include <string.h> 31 32#include "elf32.h" 33#include "elf64.h" 34#include "libelf.h" 35#include "_libelf.h" 36 37/* WARNING: GENERATED FROM __file__. */ 38 39/* 40 * Macros to swap various integral quantities. 41 */ 42 43#define SWAP_HALF(X) do { \ 44 uint16_t _x = (uint16_t) (X); \ 45 uint16_t _t = _x & 0xFF; \ 46 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 47 (X) = _t; \ 48 } while (0) 49#define SWAP_WORD(X) do { \ 50 uint32_t _x = (uint32_t) (X); \ 51 uint32_t _t = _x & 0xFF; \ 52 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 53 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 54 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 55 (X) = _t; \ 56 } while (0) 57#define SWAP_ADDR32(X) SWAP_WORD(X) 58#define SWAP_OFF32(X) SWAP_WORD(X) 59#define SWAP_SWORD(X) SWAP_WORD(X) 60#define SWAP_WORD64(X) do { \ 61 uint64_t _x = (uint64_t) (X); \ 62 uint64_t _t = _x & 0xFF; \ 63 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 64 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 65 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 66 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 67 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 68 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 69 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 70 (X) = _t; \ 71 } while (0) 72#define SWAP_ADDR64(X) SWAP_WORD64(X) 73#define SWAP_LWORD(X) SWAP_WORD64(X) 74#define SWAP_OFF64(X) SWAP_WORD64(X) 75#define SWAP_SXWORD(X) SWAP_WORD64(X) 76#define SWAP_XWORD(X) SWAP_WORD64(X) 77 78/* 79 * Write out various integral values. The destination pointer could 80 * be unaligned. Values are written out in native byte order. The 81 * destination pointer is incremented after the write. 82 */ 83#define WRITE_BYTE(P,X) do { \ 84 unsigned char *const _p = (unsigned char *) (P); \ 85 _p[0] = (unsigned char) (X); \ 86 (P) = _p + 1; \ 87 } while (0) 88#define WRITE_HALF(P,X) do { \ 89 uint16_t _t = (X); \ 90 unsigned char *const _p = (unsigned char *) (P); \ 91 unsigned const char *const _q = (unsigned char *) &_t; \ 92 _p[0] = _q[0]; \ 93 _p[1] = _q[1]; \ 94 (P) = _p + 2; \ 95 } while (0) 96#define WRITE_WORD(P,X) do { \ 97 uint32_t _t = (X); \ 98 unsigned char *const _p = (unsigned char *) (P); \ 99 unsigned const char *const _q = (unsigned char *) &_t; \ 100 _p[0] = _q[0]; \ 101 _p[1] = _q[1]; \ 102 _p[2] = _q[2]; \ 103 _p[3] = _q[3]; \ 104 (P) = _p + 4; \ 105 } while (0) 106#define WRITE_ADDR32(P,X) WRITE_WORD(P,X) 107#define WRITE_OFF32(P,X) WRITE_WORD(P,X) 108#define WRITE_SWORD(P,X) WRITE_WORD(P,X) 109#define WRITE_WORD64(P,X) do { \ 110 uint64_t _t = (X); \ 111 unsigned char *const _p = (unsigned char *) (P); \ 112 unsigned const char *const _q = (unsigned char *) &_t; \ 113 _p[0] = _q[0]; \ 114 _p[1] = _q[1]; \ 115 _p[2] = _q[2]; \ 116 _p[3] = _q[3]; \ 117 _p[4] = _q[4]; \ 118 _p[5] = _q[5]; \ 119 _p[6] = _q[6]; \ 120 _p[7] = _q[7]; \ 121 (P) = _p + 8; \ 122 } while (0) 123#define WRITE_ADDR64(P,X) WRITE_WORD64(P,X) 124#define WRITE_LWORD(P,X) WRITE_WORD64(P,X) 125#define WRITE_OFF64(P,X) WRITE_WORD64(P,X) 126#define WRITE_SXWORD(P,X) WRITE_WORD64(P,X) 127#define WRITE_XWORD(P,X) WRITE_WORD64(P,X) 128#define WRITE_IDENT(P,X) do { \ 129 (void) memcpy((P), (X), sizeof((X))); \ 130 (P) = (P) + EI_NIDENT; \ 131 } while (0) 132 133/* 134 * Read in various integral values. The source pointer could be 135 * unaligned. Values are read in in native byte order. The source 136 * pointer is incremented appropriately. 137 */ 138 139#define READ_BYTE(P,X) do { \ 140 const unsigned char *const _p = \ 141 (const unsigned char *) (P); \ 142 (X) = _p[0]; \ 143 (P) = (P) + 1; \ 144 } while (0) 145#define READ_HALF(P,X) do { \ 146 uint16_t _t; \ 147 unsigned char *const _q = (unsigned char *) &_t; \ 148 const unsigned char *const _p = \ 149 (const unsigned char *) (P); \ 150 _q[0] = _p[0]; \ 151 _q[1] = _p[1]; \ 152 (P) = (P) + 2; \ 153 (X) = _t; \ 154 } while (0) 155#define READ_WORD(P,X) do { \ 156 uint32_t _t; \ 157 unsigned char *const _q = (unsigned char *) &_t; \ 158 const unsigned char *const _p = \ 159 (const unsigned char *) (P); \ 160 _q[0] = _p[0]; \ 161 _q[1] = _p[1]; \ 162 _q[2] = _p[2]; \ 163 _q[3] = _p[3]; \ 164 (P) = (P) + 4; \ 165 (X) = _t; \ 166 } while (0) 167#define READ_ADDR32(P,X) READ_WORD(P,X) 168#define READ_OFF32(P,X) READ_WORD(P,X) 169#define READ_SWORD(P,X) READ_WORD(P,X) 170#define READ_WORD64(P,X) do { \ 171 uint64_t _t; \ 172 unsigned char *const _q = (unsigned char *) &_t; \ 173 const unsigned char *const _p = \ 174 (const unsigned char *) (P); \ 175 _q[0] = _p[0]; \ 176 _q[1] = _p[1]; \ 177 _q[2] = _p[2]; \ 178 _q[3] = _p[3]; \ 179 _q[4] = _p[4]; \ 180 _q[5] = _p[5]; \ 181 _q[6] = _p[6]; \ 182 _q[7] = _p[7]; \ 183 (P) = (P) + 8; \ 184 (X) = _t; \ 185 } while (0) 186#define READ_ADDR64(P,X) READ_WORD64(P,X) 187#define READ_LWORD(P,X) READ_WORD64(P,X) 188#define READ_OFF64(P,X) READ_WORD64(P,X) 189#define READ_SXWORD(P,X) READ_WORD64(P,X) 190#define READ_XWORD(P,X) READ_WORD64(P,X) 191#define READ_IDENT(P,X) do { \ 192 (void) memcpy((X), (P), sizeof((X))); \ 193 (P) = (P) + EI_NIDENT; \ 194 } while (0) 195 196#define ROUNDUP2(V,N) (V) = ((((V) + (N) - 1)) & ~((N) - 1)) 197 198divert(-1) 199 200/* 201 * Generate conversion routines for converting between in-memory and 202 * file representations of Elf data structures. 203 * 204 * `In-memory' representations of an Elf data structure use natural 205 * alignments and native byte ordering. This allows arithmetic and 206 * casting to work as expected. On the other hand the `file' 207 * representation of an ELF data structure could be packed tighter 208 * than its `in-memory' representation, and could be of a differing 209 * byte order. An additional complication is that `ar' only pads data 210 * to even addresses and so ELF archive member data being read from 211 * inside an `ar' archive could end up at misaligned memory addresses. 212 * 213 * Consequently, casting the `char *' pointers that point to memory 214 * representations (i.e., source pointers for the *_tof() functions 215 * and the destination pointers for the *_tom() functions), is safe, 216 * as these pointers should be correctly aligned for the memory type 217 * already. However, pointers to file representations have to be 218 * treated as being potentially unaligned and no casting can be done. 219 */ 220 221include(SRCDIR`/elf_types.m4') 222 223/* 224 * `IGNORE'_* flags turn off generation of template code. 225 */ 226 227define(`IGNORE', 228 `define(IGNORE_$1`'32, 1) 229 define(IGNORE_$1`'64, 1)') 230 231IGNORE(MOVEP) 232IGNORE(NOTE) 233 234define(IGNORE_BYTE, 1) /* 'lator, leave 'em bytes alone */ 235define(IGNORE_NOTE, 1) 236define(IGNORE_SXWORD32, 1) 237define(IGNORE_XWORD32, 1) 238 239/* 240 * `BASE'_XXX flags cause class agnostic template functions 241 * to be generated. 242 */ 243 244define(`BASE_BYTE', 1) 245define(`BASE_HALF', 1) 246define(`BASE_NOTE', 1) 247define(`BASE_WORD', 1) 248define(`BASE_LWORD', 1) 249define(`BASE_SWORD', 1) 250define(`BASE_XWORD', 1) 251define(`BASE_SXWORD', 1) 252 253/* 254 * `SIZEDEP'_XXX flags cause 32/64 bit variants to be generated 255 * for each primitive type. 256 */ 257 258define(`SIZEDEP_ADDR', 1) 259define(`SIZEDEP_OFF', 1) 260 261/* 262 * `Primitive' ELF types are those that are an alias for an integral 263 * type. They have no internal structure. These can be copied using 264 * a `memcpy()', and byteswapped in straightforward way. 265 * 266 * Macro use: 267 * `$1': Name of the ELF type. 268 * `$2': C structure name suffix 269 * `$3': ELF class specifier for symbols, one of [`', `32', `64'] 270 * `$4': ELF class specifier for types, one of [`32', `64'] 271 */ 272define(`MAKEPRIM_TO_F',` 273static void 274libelf_cvt_$1$3_tof(char *dst, char *src, size_t count, int byteswap) 275{ 276 Elf$4_$2 t, *s = (Elf$4_$2 *) (uintptr_t) src; 277 size_t c; 278 279 if (dst == src && !byteswap) 280 return; 281 282 if (!byteswap) { 283 (void) memcpy(dst, src, count * sizeof(*s)); 284 return; 285 } 286 287 for (c = 0; c < count; c++) { 288 t = *s++; 289 SWAP_$1$3(t); 290 WRITE_$1$3(dst,t); 291 } 292} 293') 294 295define(`MAKEPRIM_TO_M',` 296static void 297libelf_cvt_$1$3_tom(char *dst, char *src, size_t count, int byteswap) 298{ 299 Elf$4_$2 t, *d = (Elf$4_$2 *) (uintptr_t) dst; 300 size_t c; 301 302 if (dst == src && !byteswap) 303 return; 304 305 if (!byteswap) { 306 (void) memcpy(dst, src, count * sizeof(*d)); 307 return; 308 } 309 310 for (c = 0; c < count; c++) { 311 READ_$1$3(src,t); 312 SWAP_$1$3(t); 313 *d++ = t; 314 } 315} 316') 317 318define(`SWAP_FIELD', 319 `ifdef(`IGNORE_'$2,`', 320 `ifelse(BASE_$2,1, 321 `SWAP_$2(t.$1); 322 ', 323 `ifelse($2,BYTE,`', 324 `ifelse($2,IDENT,`', 325 `SWAP_$2'SZ()`(t.$1); 326 ')')')')') 327define(`SWAP_MEMBERS', 328 `ifelse($#,1,`/**/', 329 `SWAP_FIELD($1)SWAP_MEMBERS(shift($@))')') 330 331define(`SWAP_STRUCT', 332 `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */ 333 SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') 334 335define(`WRITE_FIELD', 336 `ifelse(BASE_$2,1, 337 `WRITE_$2(dst,t.$1); 338 ', 339 `ifelse($2,IDENT, 340 `WRITE_$2(dst,t.$1); 341 ', 342 `WRITE_$2'SZ()`(dst,t.$1); 343 ')')') 344define(`WRITE_MEMBERS', 345 `ifelse($#,1,`/**/', 346 `WRITE_FIELD($1)WRITE_MEMBERS(shift($@))')') 347 348define(`WRITE_STRUCT', 349 `pushdef(`SZ',$2)/* Write an Elf$2_$1 */ 350 WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') 351 352define(`READ_FIELD', 353 `ifelse(BASE_$2,1, 354 `READ_$2(s,t.$1); 355 ', 356 `ifelse($2,IDENT, 357 `READ_$2(s,t.$1); 358 ', 359 `READ_$2'SZ()`(s,t.$1); 360 ')')') 361 362define(`READ_MEMBERS', 363 `ifelse($#,1,`/**/', 364 `READ_FIELD($1)READ_MEMBERS(shift($@))')') 365 366define(`READ_STRUCT', 367 `pushdef(`SZ',$2)/* Read an Elf$2_$1 */ 368 READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') 369 370/* 371 * Converters for non-integral ELF data structures. 372 * 373 * When converting data to file representation, the source pointer 374 * will be naturally aligned for a data structure's in-memory 375 * representation. When converting data to memory, the destination 376 * pointer will be similarly aligned. 377 * 378 * For in-place conversions, when converting to file representations, 379 * the source buffer is large enough to hold `file' data. When 380 * converting from file to memory, we need to be careful to work 381 * `backwards', to avoid overwriting unconverted data. 382 * 383 * Macro use: 384 * `$1': Name of the ELF type. 385 * `$2': C structure name suffix. 386 * `$3': ELF class specifier, one of [`', `32', `64'] 387 */ 388 389define(`MAKE_TO_F', 390 `ifdef(`IGNORE_'$1$3,`',` 391static void 392libelf_cvt$3_$1_tof(char *dst, char *src, size_t count, int byteswap) 393{ 394 Elf$3_$2 t, *s; 395 size_t c; 396 397 s = (Elf$3_$2 *) (uintptr_t) src; 398 for (c = 0; c < count; c++) { 399 t = *s++; 400 if (byteswap) { 401 SWAP_STRUCT($2,$3) 402 } 403 WRITE_STRUCT($2,$3) 404 } 405} 406')') 407 408define(`MAKE_TO_M', 409 `ifdef(`IGNORE_'$1$3,`',` 410static void 411libelf_cvt$3_$1_tom(char *dst, char *src, size_t count, int byteswap) 412{ 413 Elf$3_$2 t, *d; 414 unsigned char *s,*s0; 415 size_t fsz; 416 417 fsz = elf$3_fsize(ELF_T_$1, (size_t) 1, EV_CURRENT); 418 d = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1); 419 s0 = (unsigned char *) src + (count - 1) * fsz; 420 421 while (count--) { 422 s = s0; 423 READ_STRUCT($2,$3) 424 if (byteswap) { 425 SWAP_STRUCT($2,$3) 426 } 427 *d-- = t; s0 -= fsz; 428 } 429} 430')') 431 432/* 433 * Make type convertor functions from the type definition 434 * of the ELF type: 435 * - if the type is a base (i.e., `primitive') type: 436 * - if it is marked as to be ignored (i.e., `IGNORE_'TYPE) 437 * is defined, we skip the code generation step. 438 * - if the type is declared as `SIZEDEP', then 32 and 64 bit 439 * variants of the conversion functions are generated. 440 * - otherwise a 32 bit variant is generated. 441 * - if the type is a structure type, we generate 32 and 64 bit 442 * variants of the conversion functions. 443 */ 444 445define(`MAKE_TYPE_CONVERTER', 446 `ifdef(`BASE'_$1, 447 `ifdef(`IGNORE_'$1,`', 448 `MAKEPRIM_TO_F($1,$2,`',64) 449 MAKEPRIM_TO_M($1,$2,`',64)')', 450 `ifdef(`SIZEDEP_'$1, 451 `MAKEPRIM_TO_F($1,$2,32,32)dnl 452 MAKEPRIM_TO_M($1,$2,32,32)dnl 453 MAKEPRIM_TO_F($1,$2,64,64)dnl 454 MAKEPRIM_TO_M($1,$2,64,64)', 455 `MAKE_TO_F($1,$2,32)dnl 456 MAKE_TO_F($1,$2,64)dnl 457 MAKE_TO_M($1,$2,32)dnl 458 MAKE_TO_M($1,$2,64)')') 459') 460 461define(`MAKE_TYPE_CONVERTERS', 462 `ifelse($#,1,`', 463 `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')') 464 465divert(0) 466 467/* 468 * Sections of type ELF_T_BYTE are never byteswapped, consequently a 469 * simple memcpy suffices for both directions of conversion. 470 */ 471 472static void 473libelf_cvt_BYTE_tox(char *dst, char *src, size_t count, int byteswap) 474{ 475 (void) byteswap; 476 if (dst != src) 477 (void) memcpy(dst, src, count); 478} 479 480/* 481 * Elf_Note structures comprise a fixed size header followed by variable 482 * length strings. The fixed size header needs to be byte swapped, but 483 * not the strings. 484 * 485 * Argument `count' denotes the total number of bytes to be converted. 486 */ 487static void 488libelf_cvt_NOTE_tom(char *dst, char *src, size_t count, int byteswap) 489{ 490 uint32_t namesz, descsz, type; 491 Elf_Note *en; 492 size_t sz; 493 494 if (dst == src && !byteswap) 495 return; 496 497 if (!byteswap) { 498 (void) memcpy(dst, src, count); 499 return; 500 } 501 502 while (count > sizeof(Elf_Note)) { 503 504 READ_WORD(src, namesz); 505 READ_WORD(src, descsz); 506 READ_WORD(src, type); 507 508 if (byteswap) { 509 SWAP_WORD(namesz); 510 SWAP_WORD(descsz); 511 SWAP_WORD(type); 512 } 513 514 en = (Elf_Note *) (uintptr_t) dst; 515 en->n_namesz = namesz; 516 en->n_descsz = descsz; 517 en->n_type = type; 518 519 dst += sizeof(Elf_Note); 520 521 ROUNDUP2(namesz, 4); 522 ROUNDUP2(descsz, 4); 523 524 sz = namesz + descsz; 525 526 if (count < sz) 527 sz = count; 528 529 (void) memcpy(dst, src, sz); 530 531 src += sz; 532 dst += sz; 533 count -= sz; 534 } 535} 536 537static void 538libelf_cvt_NOTE_tof(char *dst, char *src, size_t count, int byteswap) 539{ 540 uint32_t namesz, descsz, type; 541 Elf_Note *en; 542 size_t sz; 543 544 if (dst == src && !byteswap) 545 return; 546 547 if (!byteswap) { 548 (void) memcpy(dst, src, count); 549 return; 550 } 551 552 while (count > sizeof(Elf_Note)) { 553 554 en = (Elf_Note *) (uintptr_t) src; 555 namesz = en->n_namesz; 556 descsz = en->n_descsz; 557 type = en->n_type; 558 559 if (byteswap) { 560 SWAP_WORD(namesz); 561 SWAP_WORD(descsz); 562 SWAP_WORD(type); 563 } 564 565 566 WRITE_WORD(dst, namesz); 567 WRITE_WORD(dst, descsz); 568 WRITE_WORD(dst, type); 569 570 src += sizeof(Elf_Note); 571 572 ROUNDUP2(namesz, 4); 573 ROUNDUP2(descsz, 4); 574 575 sz = namesz + descsz; 576 577 if (count < sz) 578 sz = count; 579 580 (void) memcpy(dst, src, sz); 581 582 src += sz; 583 dst += sz; 584 count -= sz; 585 } 586} 587 588MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST) 589 590struct converters { 591 void (*tof32)(char *dst, char *src, size_t cnt, int byteswap); 592 void (*tom32)(char *dst, char *src, size_t cnt, int byteswap); 593 void (*tof64)(char *dst, char *src, size_t cnt, int byteswap); 594 void (*tom64)(char *dst, char *src, size_t cnt, int byteswap); 595}; 596 597divert(-1) 598define(`CONV', 599 `ifdef(`IGNORE_'$1$2, 600 `.$3$2 = NULL', 601 `ifdef(`BASE_'$1, 602 `ifdef(`IGNORE_'$1, 603 `.$3$2 = NULL', 604 `.$3$2 = libelf_cvt_$1_$3')', 605 `ifdef(`SIZEDEP_'$1, 606 `.$3$2 = libelf_cvt_$1$2_$3', 607 `.$3$2 = libelf_cvt$2_$1_$3')')')') 608 609define(`CONVERTER_NAME', 610 `[ELF_T_$1] = { 611 CONV($1,32,tof), CONV($1,32,tom), 612 CONV($1,64,tof), CONV($1,64,tom) },')') 613 614define(`CONVERTER_NAMES', 615 `ifelse($#,1,`', 616 `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')') 617 618undefine(`IGNORE_BYTE32') 619undefine(`IGNORE_BYTE64') 620divert(0) 621 622static struct converters cvt[ELF_T_NUM] = { 623CONVERTER_NAMES(ELF_TYPE_LIST) 624 625 /* 626 * Types that needs hand-coded converters follow. 627 */ 628 629 [ELF_T_BYTE] = { 630 .tof32 = libelf_cvt_BYTE_tox, 631 .tom32 = libelf_cvt_BYTE_tox, 632 .tof64 = libelf_cvt_BYTE_tox, 633 .tom64 = libelf_cvt_BYTE_tox 634 }, 635 [ELF_T_NOTE] = { 636 .tof32 = libelf_cvt_NOTE_tof, 637 .tom32 = libelf_cvt_NOTE_tom, 638 .tof64 = libelf_cvt_NOTE_tof, 639 .tom64 = libelf_cvt_NOTE_tom 640 } 641}; 642 643void (*_libelf_get_translator(Elf_Type t, int direction, int elfclass)) 644 (char *_dst, char *_src, size_t _cnt, int _byteswap) 645{ 646 assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); 647 assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY); 648 649 if (t >= ELF_T_NUM || 650 (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) || 651 (direction != ELF_TOFILE && direction != ELF_TOMEMORY)) 652 return (NULL); 653 654 return ((elfclass == ELFCLASS32) ? 655 (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) : 656 (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64)); 657} 658