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