1/*- 2 * Copyright (c) 2006-2008 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/cdefs.h> 28__FBSDID("$FreeBSD: releng/10.2/lib/libelf/libelf_convert.m4 219126 2011-03-01 11:47:51Z brucec $"); 29 30#include <sys/types.h> 31#include <sys/elf32.h> 32#include <sys/elf64.h> 33 34#include <assert.h> 35#include <libelf.h> 36#include <osreldate.h> 37#include <string.h> 38 39#include "_libelf.h" 40 41/* WARNING: GENERATED FROM __file__. */ 42 43/* 44 * Macros to swap various integral quantities. 45 */ 46 47#define SWAP_HALF(X) do { \ 48 uint16_t _x = (uint16_t) (X); \ 49 uint16_t _t = _x & 0xFF; \ 50 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 51 (X) = _t; \ 52 } while (0) 53#define SWAP_WORD(X) do { \ 54 uint32_t _x = (uint32_t) (X); \ 55 uint32_t _t = _x & 0xFF; \ 56 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 57 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 58 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 59 (X) = _t; \ 60 } while (0) 61#define SWAP_ADDR32(X) SWAP_WORD(X) 62#define SWAP_OFF32(X) SWAP_WORD(X) 63#define SWAP_SWORD(X) SWAP_WORD(X) 64#define SWAP_WORD64(X) do { \ 65 uint64_t _x = (uint64_t) (X); \ 66 uint64_t _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 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 71 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 72 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 73 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ 74 (X) = _t; \ 75 } while (0) 76#define SWAP_ADDR64(X) SWAP_WORD64(X) 77#define SWAP_LWORD(X) SWAP_WORD64(X) 78#define SWAP_OFF64(X) SWAP_WORD64(X) 79#define SWAP_SXWORD(X) SWAP_WORD64(X) 80#define SWAP_XWORD(X) SWAP_WORD64(X) 81 82/* 83 * Write out various integral values. The destination pointer could 84 * be unaligned. Values are written out in native byte order. The 85 * destination pointer is incremented after the write. 86 */ 87#define WRITE_BYTE(P,X) do { \ 88 char *const _p = (char *) (P); \ 89 _p[0] = (char) (X); \ 90 (P) = _p + 1; \ 91 } while (0) 92#define WRITE_HALF(P,X) do { \ 93 uint16_t _t = (X); \ 94 char *const _p = (char *) (P); \ 95 const char *const _q = (char *) &_t; \ 96 _p[0] = _q[0]; \ 97 _p[1] = _q[1]; \ 98 (P) = _p + 2; \ 99 } while (0) 100#define WRITE_WORD(P,X) do { \ 101 uint32_t _t = (X); \ 102 char *const _p = (char *) (P); \ 103 const char *const _q = (char *) &_t; \ 104 _p[0] = _q[0]; \ 105 _p[1] = _q[1]; \ 106 _p[2] = _q[2]; \ 107 _p[3] = _q[3]; \ 108 (P) = _p + 4; \ 109 } while (0) 110#define WRITE_ADDR32(P,X) WRITE_WORD(P,X) 111#define WRITE_OFF32(P,X) WRITE_WORD(P,X) 112#define WRITE_SWORD(P,X) WRITE_WORD(P,X) 113#define WRITE_WORD64(P,X) do { \ 114 uint64_t _t = (X); \ 115 char *const _p = (char *) (P); \ 116 const char *const _q = (char *) &_t; \ 117 _p[0] = _q[0]; \ 118 _p[1] = _q[1]; \ 119 _p[2] = _q[2]; \ 120 _p[3] = _q[3]; \ 121 _p[4] = _q[4]; \ 122 _p[5] = _q[5]; \ 123 _p[6] = _q[6]; \ 124 _p[7] = _q[7]; \ 125 (P) = _p + 8; \ 126 } while (0) 127#define WRITE_ADDR64(P,X) WRITE_WORD64(P,X) 128#define WRITE_LWORD(P,X) WRITE_WORD64(P,X) 129#define WRITE_OFF64(P,X) WRITE_WORD64(P,X) 130#define WRITE_SXWORD(P,X) WRITE_WORD64(P,X) 131#define WRITE_XWORD(P,X) WRITE_WORD64(P,X) 132#define WRITE_IDENT(P,X) do { \ 133 (void) memcpy((P), (X), sizeof((X))); \ 134 (P) = (P) + EI_NIDENT; \ 135 } while (0) 136 137/* 138 * Read in various integral values. The source pointer could be 139 * unaligned. Values are read in native byte order. The source 140 * pointer is incremented appropriately. 141 */ 142 143#define READ_BYTE(P,X) do { \ 144 const char *const _p = \ 145 (const char *) (P); \ 146 (X) = _p[0]; \ 147 (P) = (P) + 1; \ 148 } while (0) 149#define READ_HALF(P,X) do { \ 150 uint16_t _t; \ 151 char *const _q = (char *) &_t; \ 152 const char *const _p = \ 153 (const char *) (P); \ 154 _q[0] = _p[0]; \ 155 _q[1] = _p[1]; \ 156 (P) = (P) + 2; \ 157 (X) = _t; \ 158 } while (0) 159#define READ_WORD(P,X) do { \ 160 uint32_t _t; \ 161 char *const _q = (char *) &_t; \ 162 const char *const _p = \ 163 (const char *) (P); \ 164 _q[0] = _p[0]; \ 165 _q[1] = _p[1]; \ 166 _q[2] = _p[2]; \ 167 _q[3] = _p[3]; \ 168 (P) = (P) + 4; \ 169 (X) = _t; \ 170 } while (0) 171#define READ_ADDR32(P,X) READ_WORD(P,X) 172#define READ_OFF32(P,X) READ_WORD(P,X) 173#define READ_SWORD(P,X) READ_WORD(P,X) 174#define READ_WORD64(P,X) do { \ 175 uint64_t _t; \ 176 char *const _q = (char *) &_t; \ 177 const char *const _p = \ 178 (const char *) (P); \ 179 _q[0] = _p[0]; \ 180 _q[1] = _p[1]; \ 181 _q[2] = _p[2]; \ 182 _q[3] = _p[3]; \ 183 _q[4] = _p[4]; \ 184 _q[5] = _p[5]; \ 185 _q[6] = _p[6]; \ 186 _q[7] = _p[7]; \ 187 (P) = (P) + 8; \ 188 (X) = _t; \ 189 } while (0) 190#define READ_ADDR64(P,X) READ_WORD64(P,X) 191#define READ_LWORD(P,X) READ_WORD64(P,X) 192#define READ_OFF64(P,X) READ_WORD64(P,X) 193#define READ_SXWORD(P,X) READ_WORD64(P,X) 194#define READ_XWORD(P,X) READ_WORD64(P,X) 195#define READ_IDENT(P,X) do { \ 196 (void) memcpy((X), (P), sizeof((X))); \ 197 (P) = (P) + EI_NIDENT; \ 198 } while (0) 199 200#define ROUNDUP2(V,N) (V) = ((((V) + (N) - 1)) & ~((N) - 1)) 201 202divert(-1) 203 204/* 205 * Generate conversion routines for converting between in-memory and 206 * file representations of Elf data structures. 207 * 208 * `In-memory' representations of an Elf data structure use natural 209 * alignments and native byte ordering. This allows arithmetic and 210 * casting to work as expected. On the other hand the `file' 211 * representation of an ELF data structure could be packed tighter 212 * than its `in-memory' representation, and could be of a differing 213 * byte order. An additional complication is that `ar' only pads data 214 * to even addresses and so ELF archive member data being read from 215 * inside an `ar' archive could end up at misaligned memory addresses. 216 * 217 * Consequently, casting the `char *' pointers that point to memory 218 * representations (i.e., source pointers for the *_tof() functions 219 * and the destination pointers for the *_tom() functions), is safe, 220 * as these pointers should be correctly aligned for the memory type 221 * already. However, pointers to file representations have to be 222 * treated as being potentially unaligned and no casting can be done. 223 */ 224 225include(SRCDIR`/elf_types.m4') 226 227/* 228 * `IGNORE'_* flags turn off generation of template code. 229 */ 230 231define(`IGNORE', 232 `define(IGNORE_$1`'32, 1) 233 define(IGNORE_$1`'64, 1)') 234 235IGNORE(MOVEP) 236IGNORE(NOTE) 237IGNORE(GNUHASH) 238 239define(IGNORE_BYTE, 1) /* 'lator, leave 'em bytes alone */ 240define(IGNORE_GNUHASH, 1) 241define(IGNORE_NOTE, 1) 242define(IGNORE_SXWORD32, 1) 243define(IGNORE_XWORD32, 1) 244 245/* 246 * `BASE'_XXX flags cause class agnostic template functions 247 * to be generated. 248 */ 249 250define(`BASE_BYTE', 1) 251define(`BASE_HALF', 1) 252define(`BASE_NOTE', 1) 253define(`BASE_WORD', 1) 254define(`BASE_LWORD', 1) 255define(`BASE_SWORD', 1) 256define(`BASE_XWORD', 1) 257define(`BASE_SXWORD', 1) 258 259/* 260 * `SIZEDEP'_XXX flags cause 32/64 bit variants to be generated 261 * for each primitive type. 262 */ 263 264define(`SIZEDEP_ADDR', 1) 265define(`SIZEDEP_OFF', 1) 266 267/* 268 * `Primitive' ELF types are those that are an alias for an integral 269 * type. They have no internal structure. These can be copied using 270 * a `memcpy()', and byteswapped in straightforward way. 271 * 272 * Macro use: 273 * `$1': Name of the ELF type. 274 * `$2': C structure name suffix 275 * `$3': ELF class specifier for symbols, one of [`', `32', `64'] 276 * `$4': ELF class specifier for types, one of [`32', `64'] 277 */ 278define(`MAKEPRIM_TO_F',` 279static int 280libelf_cvt_$1$3_tof(char *dst, size_t dsz, char *src, size_t count, 281 int byteswap) 282{ 283 Elf$4_$2 t, *s = (Elf$4_$2 *) (uintptr_t) src; 284 size_t c; 285 286 (void) dsz; 287 288 if (!byteswap) { 289 (void) memcpy(dst, src, count * sizeof(*s)); 290 return (1); 291 } 292 293 for (c = 0; c < count; c++) { 294 t = *s++; 295 SWAP_$1$3(t); 296 WRITE_$1$3(dst,t); 297 } 298 299 return (1); 300} 301') 302 303define(`MAKEPRIM_TO_M',` 304static int 305libelf_cvt_$1$3_tom(char *dst, size_t dsz, char *src, size_t count, 306 int byteswap) 307{ 308 Elf$4_$2 t, *d = (Elf$4_$2 *) (uintptr_t) dst; 309 size_t c; 310 311 if (dsz < count * sizeof(Elf$4_$2)) 312 return (0); 313 314 if (!byteswap) { 315 (void) memcpy(dst, src, count * sizeof(*d)); 316 return (1); 317 } 318 319 for (c = 0; c < count; c++) { 320 READ_$1$3(src,t); 321 SWAP_$1$3(t); 322 *d++ = t; 323 } 324 325 return (1); 326} 327') 328 329define(`SWAP_FIELD', 330 `ifdef(`IGNORE_'$2,`', 331 `ifelse(BASE_$2,1, 332 `SWAP_$2(t.$1); 333 ', 334 `ifelse($2,BYTE,`', 335 `ifelse($2,IDENT,`', 336 `SWAP_$2'SZ()`(t.$1); 337 ')')')')') 338define(`SWAP_MEMBERS', 339 `ifelse($#,1,`/**/', 340 `SWAP_FIELD($1)SWAP_MEMBERS(shift($@))')') 341 342define(`SWAP_STRUCT', 343 `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */ 344 SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') 345 346define(`WRITE_FIELD', 347 `ifelse(BASE_$2,1, 348 `WRITE_$2(dst,t.$1); 349 ', 350 `ifelse($2,IDENT, 351 `WRITE_$2(dst,t.$1); 352 ', 353 `WRITE_$2'SZ()`(dst,t.$1); 354 ')')') 355define(`WRITE_MEMBERS', 356 `ifelse($#,1,`/**/', 357 `WRITE_FIELD($1)WRITE_MEMBERS(shift($@))')') 358 359define(`WRITE_STRUCT', 360 `pushdef(`SZ',$2)/* Write an Elf$2_$1 */ 361 WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') 362 363define(`READ_FIELD', 364 `ifelse(BASE_$2,1, 365 `READ_$2(s,t.$1); 366 ', 367 `ifelse($2,IDENT, 368 `READ_$2(s,t.$1); 369 ', 370 `READ_$2'SZ()`(s,t.$1); 371 ')')') 372 373define(`READ_MEMBERS', 374 `ifelse($#,1,`/**/', 375 `READ_FIELD($1)READ_MEMBERS(shift($@))')') 376 377define(`READ_STRUCT', 378 `pushdef(`SZ',$2)/* Read an Elf$2_$1 */ 379 READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') 380 381/* 382 * Converters for non-integral ELF data structures. 383 * 384 * When converting data to file representation, the source pointer 385 * will be naturally aligned for a data structure's in-memory 386 * representation. When converting data to memory, the destination 387 * pointer will be similarly aligned. 388 * 389 * For in-place conversions, when converting to file representations, 390 * the source buffer is large enough to hold `file' data. When 391 * converting from file to memory, we need to be careful to work 392 * `backwards', to avoid overwriting unconverted data. 393 * 394 * Macro use: 395 * `$1': Name of the ELF type. 396 * `$2': C structure name suffix. 397 * `$3': ELF class specifier, one of [`', `32', `64'] 398 */ 399 400define(`MAKE_TO_F', 401 `ifdef(`IGNORE_'$1$3,`',` 402static int 403libelf_cvt$3_$1_tof(char *dst, size_t dsz, char *src, size_t count, 404 int byteswap) 405{ 406 Elf$3_$2 t, *s; 407 size_t c; 408 409 (void) dsz; 410 411 s = (Elf$3_$2 *) (uintptr_t) src; 412 for (c = 0; c < count; c++) { 413 t = *s++; 414 if (byteswap) { 415 SWAP_STRUCT($2,$3) 416 } 417 WRITE_STRUCT($2,$3) 418 } 419 420 return (1); 421} 422')') 423 424define(`MAKE_TO_M', 425 `ifdef(`IGNORE_'$1$3,`',` 426static int 427libelf_cvt$3_$1_tom(char *dst, size_t dsz, char *src, size_t count, 428 int byteswap) 429{ 430 Elf$3_$2 t, *d; 431 char *s,*s0; 432 size_t fsz; 433 434 fsz = elf$3_fsize(ELF_T_$1, (size_t) 1, EV_CURRENT); 435 d = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1); 436 s0 = (char *) src + (count - 1) * fsz; 437 438 if (dsz < count * sizeof(Elf$3_$2)) 439 return (0); 440 441 while (count--) { 442 s = s0; 443 READ_STRUCT($2,$3) 444 if (byteswap) { 445 SWAP_STRUCT($2,$3) 446 } 447 *d-- = t; s0 -= fsz; 448 } 449 450 return (1); 451} 452')') 453 454/* 455 * Make type convertor functions from the type definition 456 * of the ELF type: 457 * - if the type is a base (i.e., `primitive') type: 458 * - if it is marked as to be ignored (i.e., `IGNORE_'TYPE) 459 * is defined, we skip the code generation step. 460 * - if the type is declared as `SIZEDEP', then 32 and 64 bit 461 * variants of the conversion functions are generated. 462 * - otherwise a 32 bit variant is generated. 463 * - if the type is a structure type, we generate 32 and 64 bit 464 * variants of the conversion functions. 465 */ 466 467define(`MAKE_TYPE_CONVERTER', 468 `#if __FreeBSD_version >= $3 /* $1 */ 469ifdef(`BASE'_$1, 470 `ifdef(`IGNORE_'$1,`', 471 `MAKEPRIM_TO_F($1,$2,`',64) 472 MAKEPRIM_TO_M($1,$2,`',64)')', 473 `ifdef(`SIZEDEP_'$1, 474 `MAKEPRIM_TO_F($1,$2,32,32)dnl 475 MAKEPRIM_TO_M($1,$2,32,32)dnl 476 MAKEPRIM_TO_F($1,$2,64,64)dnl 477 MAKEPRIM_TO_M($1,$2,64,64)', 478 `MAKE_TO_F($1,$2,32)dnl 479 MAKE_TO_F($1,$2,64)dnl 480 MAKE_TO_M($1,$2,32)dnl 481 MAKE_TO_M($1,$2,64)')') 482#endif /* $1 */ 483') 484 485define(`MAKE_TYPE_CONVERTERS', 486 `ifelse($#,1,`', 487 `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')') 488 489divert(0) 490 491/* 492 * Sections of type ELF_T_BYTE are never byteswapped, consequently a 493 * simple memcpy suffices for both directions of conversion. 494 */ 495 496static int 497libelf_cvt_BYTE_tox(char *dst, size_t dsz, char *src, size_t count, 498 int byteswap) 499{ 500 (void) byteswap; 501 if (dsz < count) 502 return (0); 503 if (dst != src) 504 (void) memcpy(dst, src, count); 505 return (1); 506} 507 508MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST) 509 510#if __FreeBSD_version >= 800062 511/* 512 * Sections of type ELF_T_GNUHASH start with a header containing 4 32-bit 513 * words. Bloom filter data comes next, followed by hash buckets and the 514 * hash chain. 515 * 516 * Bloom filter words are 64 bit wide on ELFCLASS64 objects and are 32 bit 517 * wide on ELFCLASS32 objects. The other objects in this section are 32 518 * bits wide. 519 * 520 * Argument `srcsz' denotes the number of bytes to be converted. In the 521 * 32-bit case we need to translate `srcsz' to a count of 32-bit words. 522 */ 523 524static int 525libelf_cvt32_GNUHASH_tom(char *dst, size_t dsz, char *src, size_t srcsz, 526 int byteswap) 527{ 528 return (libelf_cvt_WORD_tom(dst, dsz, src, srcsz / sizeof(uint32_t), 529 byteswap)); 530} 531 532static int 533libelf_cvt32_GNUHASH_tof(char *dst, size_t dsz, char *src, size_t srcsz, 534 int byteswap) 535{ 536 return (libelf_cvt_WORD_tof(dst, dsz, src, srcsz / sizeof(uint32_t), 537 byteswap)); 538} 539 540static int 541libelf_cvt64_GNUHASH_tom(char *dst, size_t dsz, char *src, size_t srcsz, 542 int byteswap) 543{ 544 size_t sz; 545 uint64_t t64, *bloom64; 546 Elf_GNU_Hash_Header *gh; 547 uint32_t n, nbuckets, nchains, maskwords, shift2, symndx, t32; 548 uint32_t *buckets, *chains; 549 550 sz = 4 * sizeof(uint32_t); /* File header is 4 words long. */ 551 if (dsz < sizeof(Elf_GNU_Hash_Header) || srcsz < sz) 552 return (0); 553 554 /* Read in the section header and byteswap if needed. */ 555 READ_WORD(src, nbuckets); 556 READ_WORD(src, symndx); 557 READ_WORD(src, maskwords); 558 READ_WORD(src, shift2); 559 560 srcsz -= sz; 561 562 if (byteswap) { 563 SWAP_WORD(nbuckets); 564 SWAP_WORD(symndx); 565 SWAP_WORD(maskwords); 566 SWAP_WORD(shift2); 567 } 568 569 /* Check source buffer and destination buffer sizes. */ 570 sz = nbuckets * sizeof(uint32_t) + maskwords * sizeof(uint64_t); 571 if (srcsz < sz || dsz < sz + sizeof(Elf_GNU_Hash_Header)) 572 return (0); 573 574 gh = (Elf_GNU_Hash_Header *) (uintptr_t) dst; 575 gh->gh_nbuckets = nbuckets; 576 gh->gh_symndx = symndx; 577 gh->gh_maskwords = maskwords; 578 gh->gh_shift2 = shift2; 579 580 dsz -= sizeof(Elf_GNU_Hash_Header); 581 dst += sizeof(Elf_GNU_Hash_Header); 582 583 bloom64 = (uint64_t *) (uintptr_t) dst; 584 585 /* Copy bloom filter data. */ 586 for (n = 0; n < maskwords; n++) { 587 READ_XWORD(src, t64); 588 if (byteswap) 589 SWAP_XWORD(t64); 590 bloom64[n] = t64; 591 } 592 593 /* The hash buckets follows the bloom filter. */ 594 dst += maskwords * sizeof(uint64_t); 595 buckets = (uint32_t *) (uintptr_t) dst; 596 597 for (n = 0; n < nbuckets; n++) { 598 READ_WORD(src, t32); 599 if (byteswap) 600 SWAP_WORD(t32); 601 buckets[n] = t32; 602 } 603 604 dst += nbuckets * sizeof(uint32_t); 605 606 /* The hash chain follows the hash buckets. */ 607 dsz -= sz; 608 srcsz -= sz; 609 610 if (dsz < srcsz) /* Destination lacks space. */ 611 return (0); 612 613 nchains = srcsz / sizeof(uint32_t); 614 chains = (uint32_t *) (uintptr_t) dst; 615 616 for (n = 0; n < nchains; n++) { 617 READ_WORD(src, t32); 618 if (byteswap) 619 SWAP_WORD(t32); 620 *chains++ = t32; 621 } 622 623 return (1); 624} 625 626static int 627libelf_cvt64_GNUHASH_tof(char *dst, size_t dsz, char *src, size_t srcsz, 628 int byteswap) 629{ 630 uint32_t *s32; 631 size_t sz, hdrsz; 632 uint64_t *s64, t64; 633 Elf_GNU_Hash_Header *gh; 634 uint32_t maskwords, n, nbuckets, nchains, t0, t1, t2, t3, t32; 635 636 hdrsz = 4 * sizeof(uint32_t); /* Header is 4x32 bits. */ 637 if (dsz < hdrsz || srcsz < sizeof(Elf_GNU_Hash_Header)) 638 return (0); 639 640 gh = (Elf_GNU_Hash_Header *) (uintptr_t) src; 641 642 t0 = nbuckets = gh->gh_nbuckets; 643 t1 = gh->gh_symndx; 644 t2 = maskwords = gh->gh_maskwords; 645 t3 = gh->gh_shift2; 646 647 src += sizeof(Elf_GNU_Hash_Header); 648 srcsz -= sizeof(Elf_GNU_Hash_Header); 649 dsz -= hdrsz; 650 651 sz = gh->gh_nbuckets * sizeof(uint32_t) + gh->gh_maskwords * 652 sizeof(uint64_t); 653 654 if (srcsz < sz || dsz < sz) 655 return (0); 656 657 /* Write out the header. */ 658 if (byteswap) { 659 SWAP_WORD(t0); 660 SWAP_WORD(t1); 661 SWAP_WORD(t2); 662 SWAP_WORD(t3); 663 } 664 665 WRITE_WORD(dst, t0); 666 WRITE_WORD(dst, t1); 667 WRITE_WORD(dst, t2); 668 WRITE_WORD(dst, t3); 669 670 /* Copy the bloom filter and the hash table. */ 671 s64 = (uint64_t *) (uintptr_t) src; 672 for (n = 0; n < maskwords; n++) { 673 t64 = *s64++; 674 if (byteswap) 675 SWAP_XWORD(t64); 676 WRITE_WORD64(dst, t64); 677 } 678 679 s32 = (uint32_t *) s64; 680 for (n = 0; n < nbuckets; n++) { 681 t32 = *s32++; 682 if (byteswap) 683 SWAP_WORD(t32); 684 WRITE_WORD(dst, t32); 685 } 686 687 srcsz -= sz; 688 dsz -= sz; 689 690 /* Copy out the hash chains. */ 691 if (dsz < srcsz) 692 return (0); 693 694 nchains = srcsz / sizeof(uint32_t); 695 for (n = 0; n < nchains; n++) { 696 t32 = *s32++; 697 if (byteswap) 698 SWAP_WORD(t32); 699 WRITE_WORD(dst, t32); 700 } 701 702 return (1); 703} 704#endif 705 706/* 707 * Elf_Note structures comprise a fixed size header followed by variable 708 * length strings. The fixed size header needs to be byte swapped, but 709 * not the strings. 710 * 711 * Argument `count' denotes the total number of bytes to be converted. 712 * The destination buffer needs to be at least `count' bytes in size. 713 */ 714static int 715libelf_cvt_NOTE_tom(char *dst, size_t dsz, char *src, size_t count, 716 int byteswap) 717{ 718 uint32_t namesz, descsz, type; 719 Elf_Note *en; 720 size_t sz, hdrsz; 721 722 if (dsz < count) /* Destination buffer is too small. */ 723 return (0); 724 725 hdrsz = 3 * sizeof(uint32_t); 726 if (count < hdrsz) /* Source too small. */ 727 return (0); 728 729 if (!byteswap) { 730 (void) memcpy(dst, src, count); 731 return (1); 732 } 733 734 /* Process all notes in the section. */ 735 while (count > hdrsz) { 736 /* Read the note header. */ 737 READ_WORD(src, namesz); 738 READ_WORD(src, descsz); 739 READ_WORD(src, type); 740 741 /* Translate. */ 742 SWAP_WORD(namesz); 743 SWAP_WORD(descsz); 744 SWAP_WORD(type); 745 746 /* Copy out the translated note header. */ 747 en = (Elf_Note *) (uintptr_t) dst; 748 en->n_namesz = namesz; 749 en->n_descsz = descsz; 750 en->n_type = type; 751 752 dsz -= sizeof(Elf_Note); 753 dst += sizeof(Elf_Note); 754 count -= hdrsz; 755 756 ROUNDUP2(namesz, 4); 757 ROUNDUP2(descsz, 4); 758 759 sz = namesz + descsz; 760 761 if (count < sz || dsz < sz) /* Buffers are too small. */ 762 return (0); 763 764 (void) memcpy(dst, src, sz); 765 766 src += sz; 767 dst += sz; 768 769 count -= sz; 770 dsz -= sz; 771 } 772 773 return (1); 774} 775 776static int 777libelf_cvt_NOTE_tof(char *dst, size_t dsz, char *src, size_t count, 778 int byteswap) 779{ 780 uint32_t namesz, descsz, type; 781 Elf_Note *en; 782 size_t sz; 783 784 if (dsz < count) 785 return (0); 786 787 if (!byteswap) { 788 (void) memcpy(dst, src, count); 789 return (1); 790 } 791 792 while (count > sizeof(Elf_Note)) { 793 794 en = (Elf_Note *) (uintptr_t) src; 795 namesz = en->n_namesz; 796 descsz = en->n_descsz; 797 type = en->n_type; 798 799 SWAP_WORD(namesz); 800 SWAP_WORD(descsz); 801 SWAP_WORD(type); 802 803 WRITE_WORD(dst, namesz); 804 WRITE_WORD(dst, descsz); 805 WRITE_WORD(dst, type); 806 807 src += sizeof(Elf_Note); 808 809 ROUNDUP2(namesz, 4); 810 ROUNDUP2(descsz, 4); 811 812 sz = namesz + descsz; 813 814 if (count < sz) 815 sz = count; 816 817 (void) memcpy(dst, src, sz); 818 819 src += sz; 820 dst += sz; 821 count -= sz; 822 } 823 824 return (1); 825} 826 827struct converters { 828 int (*tof32)(char *dst, size_t dsz, char *src, size_t cnt, 829 int byteswap); 830 int (*tom32)(char *dst, size_t dsz, char *src, size_t cnt, 831 int byteswap); 832 int (*tof64)(char *dst, size_t dsz, char *src, size_t cnt, 833 int byteswap); 834 int (*tom64)(char *dst, size_t dsz, char *src, size_t cnt, 835 int byteswap); 836}; 837 838divert(-1) 839define(`CONV', 840 `ifdef(`IGNORE_'$1$2, 841 `.$3$2 = NULL', 842 `ifdef(`BASE_'$1, 843 `.$3$2 = libelf_cvt_$1_$3', 844 `ifdef(`SIZEDEP_'$1, 845 `.$3$2 = libelf_cvt_$1$2_$3', 846 `.$3$2 = libelf_cvt$2_$1_$3')')')') 847 848define(`CONVERTER_NAME', 849 `ifdef(`IGNORE_'$1,`', 850 `#if __FreeBSD_version >= $3 851 [ELF_T_$1] = { 852 CONV($1,32,tof), CONV($1,32,tom), 853 CONV($1,64,tof), CONV($1,64,tom) }, 854#endif 855')') 856 857define(`CONVERTER_NAMES', 858 `ifelse($#,1,`', 859 `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')') 860 861undefine(`IGNORE_BYTE32', `IGNORE_BYTE64') 862divert(0) 863 864static struct converters cvt[ELF_T_NUM] = { 865CONVERTER_NAMES(ELF_TYPE_LIST) 866 867 /* 868 * Types that needs hand-coded converters follow. 869 */ 870 871 [ELF_T_BYTE] = { 872 .tof32 = libelf_cvt_BYTE_tox, 873 .tom32 = libelf_cvt_BYTE_tox, 874 .tof64 = libelf_cvt_BYTE_tox, 875 .tom64 = libelf_cvt_BYTE_tox 876 }, 877 878#if __FreeBSD_version >= 800062 879 [ELF_T_GNUHASH] = { 880 .tof32 = libelf_cvt32_GNUHASH_tof, 881 .tom32 = libelf_cvt32_GNUHASH_tom, 882 .tof64 = libelf_cvt64_GNUHASH_tof, 883 .tom64 = libelf_cvt64_GNUHASH_tom 884 }, 885#endif 886 887 [ELF_T_NOTE] = { 888 .tof32 = libelf_cvt_NOTE_tof, 889 .tom32 = libelf_cvt_NOTE_tom, 890 .tof64 = libelf_cvt_NOTE_tof, 891 .tom64 = libelf_cvt_NOTE_tom 892 } 893}; 894 895int (*_libelf_get_translator(Elf_Type t, int direction, int elfclass)) 896 (char *_dst, size_t dsz, char *_src, size_t _cnt, int _byteswap) 897{ 898 assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); 899 assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY); 900 901 if (t >= ELF_T_NUM || 902 (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) || 903 (direction != ELF_TOFILE && direction != ELF_TOMEMORY)) 904 return (NULL); 905 906 return ((elfclass == ELFCLASS32) ? 907 (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) : 908 (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64)); 909} 910