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