1/* Return the next data element from the section after possibly converting it. 2 Copyright (C) 1998-2005, 2006, 2007 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_HALF] = __alignof__ (ElfW2(Bits,Half)), \ 87 [ELF_T_WORD] = __alignof__ (ElfW2(Bits,Word)), \ 88 [ELF_T_SYM] = __alignof__ (ElfW2(Bits,Sym)), \ 89 [ELF_T_SYMINFO] = __alignof__ (ElfW2(Bits,Syminfo)), \ 90 [ELF_T_REL] = __alignof__ (ElfW2(Bits,Rel)), \ 91 [ELF_T_RELA] = __alignof__ (ElfW2(Bits,Rela)), \ 92 [ELF_T_DYN] = __alignof__ (ElfW2(Bits,Dyn)), \ 93 [ELF_T_VDEF] = __alignof__ (ElfW2(Bits,Verdef)), \ 94 [ELF_T_VDAUX] = __alignof__ (ElfW2(Bits,Verdaux)), \ 95 [ELF_T_VNEED] = __alignof__ (ElfW2(Bits,Verneed)), \ 96 [ELF_T_VNAUX] = __alignof__ (ElfW2(Bits,Vernaux)), \ 97 [ELF_T_MOVE] = __alignof__ (ElfW2(Bits,Move)), \ 98 [ELF_T_LIB] = __alignof__ (ElfW2(Bits,Lib)), \ 99 [ELF_T_NHDR] = __alignof__ (ElfW2(Bits,Nhdr)), \ 100 } 101 [EV_CURRENT - 1] = 102 { 103 [ELFCLASS32 - 1] = TYPE_ALIGNS (32), 104 [ELFCLASS64 - 1] = TYPE_ALIGNS (64), 105 } 106# undef TYPE_ALIGNS 107 }; 108#endif 109 110 111/* Convert the data in the current section. */ 112static void 113convert_data (Elf_Scn *scn, int version __attribute__ ((unused)), int eclass, 114 int data, size_t size, Elf_Type type) 115{ 116 const size_t align = __libelf_type_align (eclass, type); 117 118 if (data == MY_ELFDATA) 119 { 120 if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0) 121 /* No need to copy, we can use the raw data. */ 122 scn->data_base = scn->rawdata_base; 123 else 124 { 125 scn->data_base = (char *) malloc (size); 126 if (scn->data_base == NULL) 127 { 128 __libelf_seterrno (ELF_E_NOMEM); 129 return; 130 } 131 132 /* The copy will be appropriately aligned for direct access. */ 133 memcpy (scn->data_base, scn->rawdata_base, size); 134 } 135 } 136 else 137 { 138 xfct_t fp; 139 140 scn->data_base = (char *) malloc (size); 141 if (scn->data_base == NULL) 142 { 143 __libelf_seterrno (ELF_E_NOMEM); 144 return; 145 } 146 147 /* Get the conversion function. */ 148#if EV_NUM != 2 149 fp = __elf_xfctstom[version - 1][__libelf_version - 1][eclass - 1][type]; 150#else 151 fp = __elf_xfctstom[0][0][eclass - 1][type]; 152#endif 153 154 fp (scn->data_base, scn->rawdata_base, size, 0); 155 } 156 157 scn->data_list.data.d.d_buf = scn->data_base; 158 scn->data_list.data.d.d_size = size; 159 scn->data_list.data.d.d_type = type; 160 scn->data_list.data.d.d_off = scn->rawdata.d.d_off; 161 scn->data_list.data.d.d_align = scn->rawdata.d.d_align; 162 scn->data_list.data.d.d_version = scn->rawdata.d.d_version; 163 164 scn->data_list.data.s = scn; 165} 166 167 168/* Store the information for the raw data in the `rawdata' element. */ 169int 170internal_function 171__libelf_set_rawdata_wrlock (Elf_Scn *scn) 172{ 173 Elf64_Off offset; 174 Elf64_Xword size; 175 Elf64_Xword align; 176 int type; 177 Elf *elf = scn->elf; 178 179 if (elf->class == ELFCLASS32) 180 { 181 Elf32_Shdr *shdr 182 = scn->shdr.e32 ?: __elf32_getshdr_wrlock (scn); 183 184 if (shdr == NULL) 185 /* Something went terribly wrong. */ 186 return 1; 187 188 offset = shdr->sh_offset; 189 size = shdr->sh_size; 190 type = shdr->sh_type; 191 align = shdr->sh_addralign; 192 } 193 else 194 { 195 Elf64_Shdr *shdr 196 = scn->shdr.e64 ?: __elf64_getshdr_wrlock (scn); 197 198 if (shdr == NULL) 199 /* Something went terribly wrong. */ 200 return 1; 201 202 offset = shdr->sh_offset; 203 size = shdr->sh_size; 204 type = shdr->sh_type; 205 align = shdr->sh_addralign; 206 } 207 208 /* If the section has no data (for whatever reason), leave the `d_buf' 209 pointer NULL. */ 210 if (size != 0 && type != SHT_NOBITS) 211 { 212 /* First a test whether the section is valid at all. */ 213 size_t entsize; 214 215 if (type == SHT_HASH) 216 { 217 GElf_Ehdr ehdr_mem; 218 GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem); 219 entsize = SH_ENTSIZE_HASH (ehdr); 220 } 221 else 222 { 223 Elf_Type t = shtype_map[LIBELF_EV_IDX][TYPEIDX (type)]; 224 if (t == ELF_T_VDEF || t == ELF_T_NHDR 225 || (t == ELF_T_GNUHASH && elf->class == ELFCLASS64)) 226 entsize = 1; 227 else 228 entsize = __libelf_type_sizes[LIBELF_EV_IDX][elf->class - 1][t]; 229 } 230 231 /* We assume it is an array of bytes if it is none of the structured 232 sections we know of. */ 233 if (entsize == 0) 234 entsize = 1; 235 236 if (unlikely (size % entsize != 0)) 237 { 238 __libelf_seterrno (ELF_E_INVALID_DATA); 239 return 1; 240 } 241 242 /* We can use the mapped or loaded data if available. */ 243 if (elf->map_address != NULL) 244 { 245 /* First see whether the information in the section header is 246 valid and it does not ask for too much. Check for unsigned 247 overflow. */ 248 if (unlikely (offset > elf->maximum_size 249 || elf->maximum_size - offset < size)) 250 { 251 /* Something is wrong. */ 252 __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER); 253 return 1; 254 } 255 256 scn->rawdata_base = scn->rawdata.d.d_buf 257 = (char *) elf->map_address + elf->start_offset + offset; 258 } 259 else if (likely (elf->fildes != -1)) 260 { 261 /* We have to read the data from the file. Allocate the needed 262 memory. */ 263 scn->rawdata_base = scn->rawdata.d.d_buf 264 = (char *) malloc (size); 265 if (scn->rawdata.d.d_buf == NULL) 266 { 267 __libelf_seterrno (ELF_E_NOMEM); 268 return 1; 269 } 270 271 ssize_t n = pread_retry (elf->fildes, scn->rawdata.d.d_buf, size, 272 elf->start_offset + offset); 273 if (unlikely ((size_t) n != size)) 274 { 275 /* Cannot read the data. */ 276 free (scn->rawdata.d.d_buf); 277 scn->rawdata_base = scn->rawdata.d.d_buf = NULL; 278 __libelf_seterrno (ELF_E_READ_ERROR); 279 return 1; 280 } 281 } 282 else 283 { 284 /* The file descriptor is already closed, we cannot get the data 285 anymore. */ 286 __libelf_seterrno (ELF_E_FD_DISABLED); 287 return 1; 288 } 289 } 290 291 scn->rawdata.d.d_size = size; 292 /* Some broken ELF ABI for 64-bit machines use the wrong hash table 293 entry size. See elf-knowledge.h for more information. */ 294 if (type == SHT_HASH && elf->class == ELFCLASS64) 295 { 296 GElf_Ehdr ehdr_mem; 297 GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem); 298 scn->rawdata.d.d_type 299 = (SH_ENTSIZE_HASH (ehdr) == 4 ? ELF_T_WORD : ELF_T_XWORD); 300 } 301 else 302 scn->rawdata.d.d_type = shtype_map[LIBELF_EV_IDX][TYPEIDX (type)]; 303 scn->rawdata.d.d_off = 0; 304 scn->rawdata.d.d_align = align; 305 if (elf->class == ELFCLASS32 306 || (offsetof (struct Elf, state.elf32.ehdr) 307 == offsetof (struct Elf, state.elf64.ehdr))) 308 scn->rawdata.d.d_version = 309 elf->state.elf32.ehdr->e_ident[EI_VERSION]; 310 else 311 scn->rawdata.d.d_version = 312 elf->state.elf64.ehdr->e_ident[EI_VERSION]; 313 314 scn->rawdata.s = scn; 315 316 scn->data_read = 1; 317 318 /* We actually read data from the file. At least we tried. */ 319 scn->flags |= ELF_F_FILEDATA; 320 321 return 0; 322} 323 324int 325internal_function 326__libelf_set_rawdata (Elf_Scn *scn) 327{ 328 int result; 329 330 if (scn == NULL) 331 return 1; 332 333 rwlock_wrlock (scn->elf->lock); 334 result = __libelf_set_rawdata_wrlock (scn); 335 rwlock_unlock (scn->elf->lock); 336 337 return result; 338} 339 340Elf_Data * 341internal_function 342__elf_getdata_rdlock (scn, data) 343 Elf_Scn *scn; 344 Elf_Data *data; 345{ 346 Elf_Data *result = NULL; 347 Elf *elf; 348 int locked = 0; 349 350 if (scn == NULL) 351 return NULL; 352 353 if (unlikely (scn->elf->kind != ELF_K_ELF)) 354 { 355 __libelf_seterrno (ELF_E_INVALID_HANDLE); 356 return NULL; 357 } 358 359 /* We will need this multiple times later on. */ 360 elf = scn->elf; 361 362 /* If `data' is not NULL this means we are not addressing the initial 363 data in the file. But this also means this data is already read 364 (since otherwise it is not possible to have a valid `data' pointer) 365 and all the data structures are initialized as well. In this case 366 we can simply walk the list of data records. */ 367 if (data != NULL) 368 { 369 Elf_Data_List *runp; 370 371 /* It is not possible that if DATA is not NULL the first entry is 372 returned. But this also means that there must be a first data 373 entry. */ 374 if (scn->data_list_rear == NULL 375 /* The section the reference data is for must match the section 376 parameter. */ 377 || unlikely (((Elf_Data_Scn *) data)->s != scn)) 378 { 379 __libelf_seterrno (ELF_E_DATA_MISMATCH); 380 goto out; 381 } 382 383 /* We start searching with the first entry. */ 384 runp = &scn->data_list; 385 386 while (1) 387 { 388 /* If `data' does not match any known record punt. */ 389 if (runp == NULL) 390 { 391 __libelf_seterrno (ELF_E_DATA_MISMATCH); 392 goto out; 393 } 394 395 if (&runp->data.d == data) 396 /* Found the entry. */ 397 break; 398 399 runp = runp->next; 400 } 401 402 /* Return the data for the next data record. */ 403 result = runp->next ? &runp->next->data.d : NULL; 404 goto out; 405 } 406 407 /* If the data for this section was not yet initialized do it now. */ 408 if (scn->data_read == 0) 409 { 410 /* We cannot acquire a write lock while we are holding a read 411 lock. Therefore give up the read lock and then get the write 412 lock. But this means that the data could meanwhile be 413 modified, therefore start the tests again. */ 414 rwlock_unlock (elf->lock); 415 rwlock_wrlock (elf->lock); 416 locked = 1; 417 418 /* Read the data from the file. There is always a file (or 419 memory region) associated with this descriptor since 420 otherwise the `data_read' flag would be set. */ 421 if (scn->data_read == 0 && __libelf_set_rawdata_wrlock (scn) != 0) 422 /* Something went wrong. The error value is already set. */ 423 goto out; 424 } 425 426 /* At this point we know the raw data is available. But it might be 427 empty in case the section has size zero (for whatever reason). 428 Now create the converted data in case this is necessary. */ 429 if (scn->data_list_rear == NULL) 430 { 431 if (scn->rawdata.d.d_buf != NULL && scn->rawdata.d.d_size > 0) 432 { 433 if (!locked) 434 { 435 rwlock_unlock (elf->lock); 436 rwlock_wrlock (elf->lock); 437 if (scn->data_list_rear != NULL) 438 goto pass; 439 } 440 441 /* Convert according to the version and the type. */ 442 convert_data (scn, __libelf_version, elf->class, 443 (elf->class == ELFCLASS32 444 || (offsetof (struct Elf, state.elf32.ehdr) 445 == offsetof (struct Elf, state.elf64.ehdr)) 446 ? elf->state.elf32.ehdr->e_ident[EI_DATA] 447 : elf->state.elf64.ehdr->e_ident[EI_DATA]), 448 scn->rawdata.d.d_size, scn->rawdata.d.d_type); 449 } 450 else 451 { 452 /* This is an empty or NOBITS section. There is no buffer but 453 the size information etc is important. */ 454 scn->data_list.data.d = scn->rawdata.d; 455 scn->data_list.data.s = scn; 456 } 457 458 scn->data_list_rear = &scn->data_list; 459 } 460 461 /* If no data is present we cannot return any. */ 462 if (scn->data_list_rear != NULL) 463 pass: 464 /* Return the first data element in the list. */ 465 result = &scn->data_list.data.d; 466 467 out: 468 return result; 469} 470 471Elf_Data * 472elf_getdata (scn, data) 473 Elf_Scn *scn; 474 Elf_Data *data; 475{ 476 Elf_Data *result; 477 478 if (scn == NULL) 479 return NULL; 480 481 rwlock_rdlock (scn->elf->lock); 482 result = __elf_getdata_rdlock (scn, data); 483 rwlock_unlock (scn->elf->lock); 484 485 return result; 486} 487INTDEF(elf_getdata) 488