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