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