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