1/* Return the next data element from the section after possibly converting it. 2 Copyright (C) 1998-2005, 2006, 2007, 2015 Red Hat, Inc. 3 This file is part of elfutils. 4 Written by Ulrich Drepper <drepper@redhat.com>, 1998. 5 6 This file is free software; you can redistribute it and/or modify 7 it under the terms of either 8 9 * the GNU Lesser General Public License as published by the Free 10 Software Foundation; either version 3 of the License, or (at 11 your option) any later version 12 13 or 14 15 * the GNU General Public License as published by the Free 16 Software Foundation; either version 2 of the License, or (at 17 your option) any later version 18 19 or both in parallel, as here. 20 21 elfutils is distributed in the hope that it will be useful, but 22 WITHOUT ANY WARRANTY; without even the implied warranty of 23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 General Public License for more details. 25 26 You should have received copies of the GNU General Public License and 27 the GNU Lesser General Public License along with this program. If 28 not, see <http://www.gnu.org/licenses/>. */ 29 30#ifdef HAVE_CONFIG_H 31# include <config.h> 32#endif 33 34#include <errno.h> 35#include <stddef.h> 36#include <string.h> 37#include <unistd.h> 38 39#include "libelfP.h" 40#include <system.h> 41#include "common.h" 42#include "elf-knowledge.h" 43 44 45#define TYPEIDX(Sh_Type) \ 46 (Sh_Type >= SHT_NULL && Sh_Type < SHT_NUM \ 47 ? Sh_Type \ 48 : (Sh_Type >= SHT_GNU_HASH && Sh_Type <= SHT_HISUNW \ 49 ? SHT_NUM + Sh_Type - SHT_GNU_HASH \ 50 : 0)) 51 52/* Associate section types with libelf types. */ 53static const Elf_Type shtype_map[EV_NUM - 1][TYPEIDX (SHT_HISUNW) + 1] = 54 { 55 [EV_CURRENT - 1] = 56 { 57 [SHT_SYMTAB] = ELF_T_SYM, 58 [SHT_RELA] = ELF_T_RELA, 59 [SHT_HASH] = ELF_T_WORD, 60 [SHT_DYNAMIC] = ELF_T_DYN, 61 [SHT_REL] = ELF_T_REL, 62 [SHT_DYNSYM] = ELF_T_SYM, 63 [SHT_INIT_ARRAY] = ELF_T_ADDR, 64 [SHT_FINI_ARRAY] = ELF_T_ADDR, 65 [SHT_PREINIT_ARRAY] = ELF_T_ADDR, 66 [SHT_GROUP] = ELF_T_WORD, 67 [SHT_SYMTAB_SHNDX] = ELF_T_WORD, 68 [SHT_NOTE] = ELF_T_NHDR, 69 [TYPEIDX (SHT_GNU_verdef)] = ELF_T_VDEF, 70 [TYPEIDX (SHT_GNU_verneed)] = ELF_T_VNEED, 71 [TYPEIDX (SHT_GNU_versym)] = ELF_T_HALF, 72 [TYPEIDX (SHT_SUNW_syminfo)] = ELF_T_SYMINFO, 73 [TYPEIDX (SHT_SUNW_move)] = ELF_T_MOVE, 74 [TYPEIDX (SHT_GNU_LIBLIST)] = ELF_T_LIB, 75 [TYPEIDX (SHT_GNU_HASH)] = ELF_T_GNUHASH, 76 } 77 }; 78 79#if !ALLOW_UNALIGNED 80/* Associate libelf types with their internal alignment requirements. */ 81const uint_fast8_t __libelf_type_aligns[EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM] = 82 { 83# define TYPE_ALIGNS(Bits) \ 84 { \ 85 [ELF_T_ADDR] = __alignof__ (ElfW2(Bits,Addr)), \ 86 [ELF_T_EHDR] = __alignof__ (ElfW2(Bits,Ehdr)), \ 87 [ELF_T_HALF] = __alignof__ (ElfW2(Bits,Half)), \ 88 [ELF_T_OFF] = __alignof__ (ElfW2(Bits,Off)), \ 89 [ELF_T_PHDR] = __alignof__ (ElfW2(Bits,Phdr)), \ 90 [ELF_T_SHDR] = __alignof__ (ElfW2(Bits,Shdr)), \ 91 [ELF_T_SWORD] = __alignof__ (ElfW2(Bits,Sword)), \ 92 [ELF_T_WORD] = __alignof__ (ElfW2(Bits,Word)), \ 93 [ELF_T_XWORD] = __alignof__ (ElfW2(Bits,Xword)), \ 94 [ELF_T_SXWORD] = __alignof__ (ElfW2(Bits,Sxword)), \ 95 [ELF_T_SYM] = __alignof__ (ElfW2(Bits,Sym)), \ 96 [ELF_T_SYMINFO] = __alignof__ (ElfW2(Bits,Syminfo)), \ 97 [ELF_T_REL] = __alignof__ (ElfW2(Bits,Rel)), \ 98 [ELF_T_RELA] = __alignof__ (ElfW2(Bits,Rela)), \ 99 [ELF_T_DYN] = __alignof__ (ElfW2(Bits,Dyn)), \ 100 [ELF_T_VDEF] = __alignof__ (ElfW2(Bits,Verdef)), \ 101 [ELF_T_VDAUX] = __alignof__ (ElfW2(Bits,Verdaux)), \ 102 [ELF_T_VNEED] = __alignof__ (ElfW2(Bits,Verneed)), \ 103 [ELF_T_VNAUX] = __alignof__ (ElfW2(Bits,Vernaux)), \ 104 [ELF_T_MOVE] = __alignof__ (ElfW2(Bits,Move)), \ 105 [ELF_T_LIB] = __alignof__ (ElfW2(Bits,Lib)), \ 106 [ELF_T_NHDR] = __alignof__ (ElfW2(Bits,Nhdr)), \ 107 [ELF_T_GNUHASH] = __alignof__ (Elf32_Word), \ 108 [ELF_T_AUXV] = __alignof__ (ElfW2(Bits,auxv_t)), \ 109 [ELF_T_CHDR] = __alignof__ (ElfW2(Bits,Chdr)), \ 110 } 111 [EV_CURRENT - 1] = 112 { 113 [ELFCLASS32 - 1] = TYPE_ALIGNS (32), 114 [ELFCLASS64 - 1] = TYPE_ALIGNS (64), 115 } 116# undef TYPE_ALIGNS 117 }; 118#endif 119 120 121Elf_Type 122internal_function 123__libelf_data_type (Elf *elf, int sh_type) 124{ 125 /* Some broken ELF ABI for 64-bit machines use the wrong hash table 126 entry size. See elf-knowledge.h for more information. */ 127 if (sh_type == SHT_HASH && elf->class == ELFCLASS64) 128 { 129 GElf_Ehdr ehdr_mem; 130 GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem); 131 return (SH_ENTSIZE_HASH (ehdr) == 4 ? ELF_T_WORD : ELF_T_XWORD); 132 } 133 else 134 return shtype_map[LIBELF_EV_IDX][TYPEIDX (sh_type)]; 135} 136 137/* Convert the data in the current section. */ 138static void 139convert_data (Elf_Scn *scn, int version __attribute__ ((unused)), int eclass, 140 int data, size_t size, Elf_Type type) 141{ 142 const size_t align = __libelf_type_align (eclass, type); 143 144 if (data == MY_ELFDATA) 145 { 146 if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0) 147 /* No need to copy, we can use the raw data. */ 148 scn->data_base = scn->rawdata_base; 149 else 150 { 151 scn->data_base = (char *) malloc (size); 152 if (scn->data_base == NULL) 153 { 154 __libelf_seterrno (ELF_E_NOMEM); 155 return; 156 } 157 158 /* The copy will be appropriately aligned for direct access. */ 159 memcpy (scn->data_base, scn->rawdata_base, size); 160 } 161 } 162 else 163 { 164 xfct_t fp; 165 166 scn->data_base = (char *) malloc (size); 167 if (scn->data_base == NULL) 168 { 169 __libelf_seterrno (ELF_E_NOMEM); 170 return; 171 } 172 173 /* Make sure the source is correctly aligned for the conversion 174 function to directly access the data elements. */ 175 char *rawdata_source; 176 if (ALLOW_UNALIGNED || 177 ((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0) 178 rawdata_source = scn->rawdata_base; 179 else 180 { 181 rawdata_source = (char *) malloc (size); 182 if (rawdata_source == NULL) 183 { 184 __libelf_seterrno (ELF_E_NOMEM); 185 return; 186 } 187 188 /* The copy will be appropriately aligned for direct access. */ 189 memcpy (rawdata_source, scn->rawdata_base, size); 190 } 191 192 /* Get the conversion function. */ 193#if EV_NUM != 2 194 fp = __elf_xfctstom[version - 1][__libelf_version - 1][eclass - 1][type]; 195#else 196 fp = __elf_xfctstom[0][0][eclass - 1][type]; 197#endif 198 199 fp (scn->data_base, rawdata_source, size, 0); 200 201 if (rawdata_source != scn->rawdata_base) 202 free (rawdata_source); 203 } 204 205 scn->data_list.data.d.d_buf = scn->data_base; 206 scn->data_list.data.d.d_size = size; 207 scn->data_list.data.d.d_type = type; 208 scn->data_list.data.d.d_off = scn->rawdata.d.d_off; 209 scn->data_list.data.d.d_align = scn->rawdata.d.d_align; 210 scn->data_list.data.d.d_version = scn->rawdata.d.d_version; 211 212 scn->data_list.data.s = scn; 213} 214 215 216/* Store the information for the raw data in the `rawdata' element. */ 217int 218internal_function 219__libelf_set_rawdata_wrlock (Elf_Scn *scn) 220{ 221 Elf64_Off offset; 222 Elf64_Xword size; 223 Elf64_Xword align; 224 Elf64_Xword flags; 225 int type; 226 Elf *elf = scn->elf; 227 228 if (elf->class == ELFCLASS32) 229 { 230 Elf32_Shdr *shdr 231 = scn->shdr.e32 ?: __elf32_getshdr_wrlock (scn); 232 233 if (shdr == NULL) 234 /* Something went terribly wrong. */ 235 return 1; 236 237 offset = shdr->sh_offset; 238 size = shdr->sh_size; 239 type = shdr->sh_type; 240 align = shdr->sh_addralign; 241 flags = shdr->sh_flags; 242 } 243 else 244 { 245 Elf64_Shdr *shdr 246 = scn->shdr.e64 ?: __elf64_getshdr_wrlock (scn); 247 248 if (shdr == NULL) 249 /* Something went terribly wrong. */ 250 return 1; 251 252 offset = shdr->sh_offset; 253 size = shdr->sh_size; 254 type = shdr->sh_type; 255 align = shdr->sh_addralign; 256 flags = shdr->sh_flags; 257 } 258 259 /* If the section has no data (for whatever reason), leave the `d_buf' 260 pointer NULL. */ 261 if (size != 0 && type != SHT_NOBITS) 262 { 263 /* First a test whether the section is valid at all. */ 264 size_t entsize; 265 266 /* Compressed data has a header, but then compressed data. */ 267 if ((flags & SHF_COMPRESSED) != 0) 268 entsize = 1; 269 else if (type == SHT_HASH) 270 { 271 GElf_Ehdr ehdr_mem; 272 GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem); 273 entsize = SH_ENTSIZE_HASH (ehdr); 274 } 275 else 276 { 277 Elf_Type t = shtype_map[LIBELF_EV_IDX][TYPEIDX (type)]; 278 if (t == ELF_T_VDEF || t == ELF_T_NHDR 279 || (t == ELF_T_GNUHASH && elf->class == ELFCLASS64)) 280 entsize = 1; 281 else 282 entsize = __libelf_type_sizes[LIBELF_EV_IDX][elf->class - 1][t]; 283 } 284 285 /* We assume it is an array of bytes if it is none of the structured 286 sections we know of. */ 287 if (entsize == 0) 288 entsize = 1; 289 290 if (unlikely (size % entsize != 0)) 291 { 292 __libelf_seterrno (ELF_E_INVALID_DATA); 293 return 1; 294 } 295 296 /* We can use the mapped or loaded data if available. */ 297 if (elf->map_address != NULL) 298 { 299 /* First see whether the information in the section header is 300 valid and it does not ask for too much. Check for unsigned 301 overflow. */ 302 if (unlikely (offset > elf->maximum_size 303 || elf->maximum_size - offset < size)) 304 { 305 /* Something is wrong. */ 306 __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER); 307 return 1; 308 } 309 310 scn->rawdata_base = scn->rawdata.d.d_buf 311 = (char *) elf->map_address + elf->start_offset + offset; 312 } 313 else if (likely (elf->fildes != -1)) 314 { 315 /* We have to read the data from the file. Allocate the needed 316 memory. */ 317 scn->rawdata_base = scn->rawdata.d.d_buf 318 = (char *) malloc (size); 319 if (scn->rawdata.d.d_buf == NULL) 320 { 321 __libelf_seterrno (ELF_E_NOMEM); 322 return 1; 323 } 324 325 ssize_t n = pread_retry (elf->fildes, scn->rawdata.d.d_buf, size, 326 elf->start_offset + offset); 327 if (unlikely ((size_t) n != size)) 328 { 329 /* Cannot read the data. */ 330 free (scn->rawdata.d.d_buf); 331 scn->rawdata_base = scn->rawdata.d.d_buf = NULL; 332 __libelf_seterrno (ELF_E_READ_ERROR); 333 return 1; 334 } 335 } 336 else 337 { 338 /* The file descriptor is already closed, we cannot get the data 339 anymore. */ 340 __libelf_seterrno (ELF_E_FD_DISABLED); 341 return 1; 342 } 343 } 344 345 scn->rawdata.d.d_size = size; 346 347 /* Compressed data always has type ELF_T_CHDR regardless of the 348 section type. */ 349 if ((flags & SHF_COMPRESSED) != 0) 350 scn->rawdata.d.d_type = ELF_T_CHDR; 351 else 352 scn->rawdata.d.d_type = __libelf_data_type (elf, type); 353 scn->rawdata.d.d_off = 0; 354 355 /* Make sure the alignment makes sense. d_align should be aligned both 356 in the section (trivially true since d_off is zero) and in the file. 357 Unfortunately we cannot be too strict because there are ELF files 358 out there that fail this requirement. We will try to fix those up 359 in elf_update when writing out the image. But for very large 360 alignment values this can bloat the image considerably. So here 361 just check and clamp the alignment value to not be bigger than the 362 actual offset of the data in the file. Given that there is always 363 at least an ehdr this will only trigger for alignment values > 64 364 which should be uncommon. */ 365 align = align ?: 1; 366 if (align > offset) 367 align = offset; 368 scn->rawdata.d.d_align = align; 369 if (elf->class == ELFCLASS32 370 || (offsetof (struct Elf, state.elf32.ehdr) 371 == offsetof (struct Elf, state.elf64.ehdr))) 372 scn->rawdata.d.d_version = 373 elf->state.elf32.ehdr->e_ident[EI_VERSION]; 374 else 375 scn->rawdata.d.d_version = 376 elf->state.elf64.ehdr->e_ident[EI_VERSION]; 377 378 scn->rawdata.s = scn; 379 380 scn->data_read = 1; 381 382 /* We actually read data from the file. At least we tried. */ 383 scn->flags |= ELF_F_FILEDATA; 384 385 return 0; 386} 387 388int 389internal_function 390__libelf_set_rawdata (Elf_Scn *scn) 391{ 392 int result; 393 394 if (scn == NULL) 395 return 1; 396 397 rwlock_wrlock (scn->elf->lock); 398 result = __libelf_set_rawdata_wrlock (scn); 399 rwlock_unlock (scn->elf->lock); 400 401 return result; 402} 403 404void 405internal_function 406__libelf_set_data_list_rdlock (Elf_Scn *scn, int wrlocked) 407{ 408 if (scn->rawdata.d.d_buf != NULL && scn->rawdata.d.d_size > 0) 409 { 410 Elf *elf = scn->elf; 411 412 /* Upgrade the lock to a write lock if necessary and check 413 nobody else already did the work. */ 414 if (!wrlocked) 415 { 416 rwlock_unlock (elf->lock); 417 rwlock_wrlock (elf->lock); 418 if (scn->data_list_rear != NULL) 419 return; 420 } 421 422 /* Convert according to the version and the type. */ 423 convert_data (scn, __libelf_version, elf->class, 424 (elf->class == ELFCLASS32 425 || (offsetof (struct Elf, state.elf32.ehdr) 426 == offsetof (struct Elf, state.elf64.ehdr)) 427 ? elf->state.elf32.ehdr->e_ident[EI_DATA] 428 : elf->state.elf64.ehdr->e_ident[EI_DATA]), 429 scn->rawdata.d.d_size, scn->rawdata.d.d_type); 430 } 431 else 432 { 433 /* This is an empty or NOBITS section. There is no buffer but 434 the size information etc is important. */ 435 scn->data_list.data.d = scn->rawdata.d; 436 scn->data_list.data.s = scn; 437 } 438 439 scn->data_list_rear = &scn->data_list; 440} 441 442Elf_Data * 443internal_function 444__elf_getdata_rdlock (Elf_Scn *scn, Elf_Data *data) 445{ 446 Elf_Data *result = NULL; 447 Elf *elf; 448 int locked = 0; 449 450 if (scn == NULL) 451 return NULL; 452 453 if (unlikely (scn->elf->kind != ELF_K_ELF)) 454 { 455 __libelf_seterrno (ELF_E_INVALID_HANDLE); 456 return NULL; 457 } 458 459 /* We will need this multiple times later on. */ 460 elf = scn->elf; 461 462 /* If `data' is not NULL this means we are not addressing the initial 463 data in the file. But this also means this data is already read 464 (since otherwise it is not possible to have a valid `data' pointer) 465 and all the data structures are initialized as well. In this case 466 we can simply walk the list of data records. */ 467 if (data != NULL) 468 { 469 Elf_Data_List *runp; 470 471 /* It is not possible that if DATA is not NULL the first entry is 472 returned. But this also means that there must be a first data 473 entry. */ 474 if (scn->data_list_rear == NULL 475 /* The section the reference data is for must match the section 476 parameter. */ 477 || unlikely (((Elf_Data_Scn *) data)->s != scn)) 478 { 479 __libelf_seterrno (ELF_E_DATA_MISMATCH); 480 goto out; 481 } 482 483 /* We start searching with the first entry. */ 484 runp = &scn->data_list; 485 486 while (1) 487 { 488 /* If `data' does not match any known record punt. */ 489 if (runp == NULL) 490 { 491 __libelf_seterrno (ELF_E_DATA_MISMATCH); 492 goto out; 493 } 494 495 if (&runp->data.d == data) 496 /* Found the entry. */ 497 break; 498 499 runp = runp->next; 500 } 501 502 /* Return the data for the next data record. */ 503 result = runp->next ? &runp->next->data.d : NULL; 504 goto out; 505 } 506 507 /* If the data for this section was not yet initialized do it now. */ 508 if (scn->data_read == 0) 509 { 510 /* We cannot acquire a write lock while we are holding a read 511 lock. Therefore give up the read lock and then get the write 512 lock. But this means that the data could meanwhile be 513 modified, therefore start the tests again. */ 514 rwlock_unlock (elf->lock); 515 rwlock_wrlock (elf->lock); 516 locked = 1; 517 518 /* Read the data from the file. There is always a file (or 519 memory region) associated with this descriptor since 520 otherwise the `data_read' flag would be set. */ 521 if (scn->data_read == 0 && __libelf_set_rawdata_wrlock (scn) != 0) 522 /* Something went wrong. The error value is already set. */ 523 goto out; 524 } 525 526 /* At this point we know the raw data is available. But it might be 527 empty in case the section has size zero (for whatever reason). 528 Now create the converted data in case this is necessary. */ 529 if (scn->data_list_rear == NULL) 530 __libelf_set_data_list_rdlock (scn, locked); 531 532 /* Return the first data element in the list. */ 533 result = &scn->data_list.data.d; 534 535 out: 536 return result; 537} 538 539Elf_Data * 540elf_getdata (Elf_Scn *scn, Elf_Data *data) 541{ 542 Elf_Data *result; 543 544 if (scn == NULL) 545 return NULL; 546 547 rwlock_rdlock (scn->elf->lock); 548 result = __elf_getdata_rdlock (scn, data); 549 rwlock_unlock (scn->elf->lock); 550 551 return result; 552} 553INTDEF(elf_getdata) 554