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 Red Hat elfutils. 4 Written by Ulrich Drepper <drepper (at) redhat.com>, 1998. 5 6 Red Hat elfutils is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by the 8 Free Software Foundation; version 2 of the License. 9 10 Red Hat elfutils is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License along 16 with Red Hat elfutils; if not, write to the Free Software Foundation, 17 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. 18 19 In addition, as a special exception, Red Hat, Inc. gives You the 20 additional right to link the code of Red Hat elfutils with code licensed 21 under any Open Source Initiative certified open source license 22 (http://www.opensource.org/licenses/index.php) which requires the 23 distribution of source code with any binary distribution and to 24 distribute linked combinations of the two. Non-GPL Code permitted under 25 this exception must only link to the code of Red Hat elfutils through 26 those well defined interfaces identified in the file named EXCEPTION 27 found in the source code files (the "Approved Interfaces"). The files 28 of Non-GPL Code may instantiate templates or use macros or inline 29 functions from the Approved Interfaces without causing the resulting 30 work to be covered by the GNU General Public License. Only Red Hat, 31 Inc. may make changes or additions to the list of Approved Interfaces. 32 Red Hat's grant of this exception is conditioned upon your not adding 33 any new exceptions. If you wish to add a new Approved Interface or 34 exception, please contact Red Hat. You must obey the GNU General Public 35 License in all respects for all of the Red Hat elfutils code and other 36 code used in conjunction with Red Hat elfutils except the Non-GPL Code 37 covered by this exception. If you modify this file, you may extend this 38 exception to your version of the file, but you are not obligated to do 39 so. If you do not wish to provide this exception without modification, 40 you must delete this exception statement from your version and license 41 this file solely under the GPL without exception. 42 43 Red Hat elfutils is an included package of the Open Invention Network. 44 An included package of the Open Invention Network is a package for which 45 Open Invention Network licensees cross-license their patents. No patent 46 license is granted, either expressly or impliedly, by designation as an 47 included package. Should you wish to participate in the Open Invention 48 Network licensing program, please visit www.openinventionnetwork.com 49 <http://www.openinventionnetwork.com>. */ 50 51 #ifdef HAVE_CONFIG_H 52 # include <config.h> 53 #endif 54 55 #include <errno.h> 56 #include <stddef.h> 57 #include <string.h> 58 #include <unistd.h> 59 60 #include "libelfP.h" 61 #include <system.h> 62 #include "common.h" 63 #include "elf-knowledge.h" 64 65 66 #define TYPEIDX(Sh_Type) \ 67 (Sh_Type >= SHT_NULL && Sh_Type < SHT_NUM \ 68 ? Sh_Type \ 69 : (Sh_Type >= SHT_GNU_HASH && Sh_Type <= SHT_HISUNW \ 70 ? SHT_NUM + Sh_Type - SHT_GNU_HASH \ 71 : 0)) 72 73 /* Associate section types with libelf types. */ 74 static const Elf_Type shtype_map[EV_NUM - 1][TYPEIDX (SHT_HISUNW) + 1] = 75 { 76 [EV_CURRENT - 1] = 77 { 78 [SHT_SYMTAB] = ELF_T_SYM, 79 [SHT_RELA] = ELF_T_RELA, 80 [SHT_HASH] = ELF_T_WORD, 81 [SHT_DYNAMIC] = ELF_T_DYN, 82 [SHT_REL] = ELF_T_REL, 83 [SHT_DYNSYM] = ELF_T_SYM, 84 [SHT_INIT_ARRAY] = ELF_T_ADDR, 85 [SHT_FINI_ARRAY] = ELF_T_ADDR, 86 [SHT_PREINIT_ARRAY] = ELF_T_ADDR, 87 [SHT_GROUP] = ELF_T_WORD, 88 [SHT_SYMTAB_SHNDX] = ELF_T_WORD, 89 [SHT_NOTE] = ELF_T_NHDR, 90 [TYPEIDX (SHT_GNU_verdef)] = ELF_T_VDEF, 91 [TYPEIDX (SHT_GNU_verneed)] = ELF_T_VNEED, 92 [TYPEIDX (SHT_GNU_versym)] = ELF_T_HALF, 93 [TYPEIDX (SHT_SUNW_syminfo)] = ELF_T_SYMINFO, 94 [TYPEIDX (SHT_SUNW_move)] = ELF_T_MOVE, 95 [TYPEIDX (SHT_GNU_LIBLIST)] = ELF_T_LIB, 96 [TYPEIDX (SHT_GNU_HASH)] = ELF_T_GNUHASH, 97 } 98 }; 99 100 #if !ALLOW_UNALIGNED 101 /* Associate libelf types with their internal alignment requirements. */ 102 const uint_fast8_t __libelf_type_aligns[EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM] = 103 { 104 # define TYPE_ALIGNS(Bits) \ 105 { \ 106 [ELF_T_ADDR] = __alignof__ (ElfW2(Bits,Addr)), \ 107 [ELF_T_HALF] = __alignof__ (ElfW2(Bits,Half)), \ 108 [ELF_T_WORD] = __alignof__ (ElfW2(Bits,Word)), \ 109 [ELF_T_SYM] = __alignof__ (ElfW2(Bits,Sym)), \ 110 [ELF_T_SYMINFO] = __alignof__ (ElfW2(Bits,Syminfo)), \ 111 [ELF_T_REL] = __alignof__ (ElfW2(Bits,Rel)), \ 112 [ELF_T_RELA] = __alignof__ (ElfW2(Bits,Rela)), \ 113 [ELF_T_DYN] = __alignof__ (ElfW2(Bits,Dyn)), \ 114 [ELF_T_VDEF] = __alignof__ (ElfW2(Bits,Verdef)), \ 115 [ELF_T_VDAUX] = __alignof__ (ElfW2(Bits,Verdaux)), \ 116 [ELF_T_VNEED] = __alignof__ (ElfW2(Bits,Verneed)), \ 117 [ELF_T_VNAUX] = __alignof__ (ElfW2(Bits,Vernaux)), \ 118 [ELF_T_MOVE] = __alignof__ (ElfW2(Bits,Move)), \ 119 [ELF_T_LIB] = __alignof__ (ElfW2(Bits,Lib)), \ 120 [ELF_T_NHDR] = __alignof__ (ElfW2(Bits,Nhdr)), \ 121 } 122 [EV_CURRENT - 1] = 123 { 124 [ELFCLASS32 - 1] = TYPE_ALIGNS (32), 125 [ELFCLASS64 - 1] = TYPE_ALIGNS (64), 126 } 127 # undef TYPE_ALIGNS 128 }; 129 #endif 130 131 132 /* Convert the data in the current section. */ 133 static void 134 convert_data (Elf_Scn *scn, int version __attribute__ ((unused)), int eclass, 135 int data, size_t size, Elf_Type type) 136 { 137 const size_t align = __libelf_type_align (eclass, type); 138 139 if (data == MY_ELFDATA) 140 { 141 if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0) 142 /* No need to copy, we can use the raw data. */ 143 scn->data_base = scn->rawdata_base; 144 else 145 { 146 scn->data_base = (char *) malloc (size); 147 if (scn->data_base == NULL) 148 { 149 __libelf_seterrno (ELF_E_NOMEM); 150 return; 151 } 152 153 /* The copy will be appropriately aligned for direct access. */ 154 memcpy (scn->data_base, scn->rawdata_base, size); 155 } 156 } 157 else 158 { 159 xfct_t fp; 160 161 scn->data_base = (char *) malloc (size); 162 if (scn->data_base == NULL) 163 { 164 __libelf_seterrno (ELF_E_NOMEM); 165 return; 166 } 167 168 /* Get the conversion function. */ 169 #if EV_NUM != 2 170 fp = __elf_xfctstom[version - 1][__libelf_version - 1][eclass - 1][type]; 171 #else 172 fp = __elf_xfctstom[0][0][eclass - 1][type]; 173 #endif 174 175 fp (scn->data_base, scn->rawdata_base, size, 0); 176 } 177 178 scn->data_list.data.d.d_buf = scn->data_base; 179 scn->data_list.data.d.d_size = size; 180 scn->data_list.data.d.d_type = type; 181 scn->data_list.data.d.d_off = scn->rawdata.d.d_off; 182 scn->data_list.data.d.d_align = scn->rawdata.d.d_align; 183 scn->data_list.data.d.d_version = scn->rawdata.d.d_version; 184 185 scn->data_list.data.s = scn; 186 } 187 188 189 /* Store the information for the raw data in the `rawdata' element. */ 190 int 191 internal_function 192 __libelf_set_rawdata_wrlock (Elf_Scn *scn) 193 { 194 size_t offset; 195 size_t size; 196 size_t align; 197 int type; 198 Elf *elf = scn->elf; 199 200 if (elf->class == ELFCLASS32) 201 { 202 Elf32_Shdr *shdr 203 = scn->shdr.e32 ?: __elf32_getshdr_wrlock (scn); 204 205 if (shdr == NULL) 206 /* Something went terribly wrong. */ 207 return 1; 208 209 offset = shdr->sh_offset; 210 size = shdr->sh_size; 211 type = shdr->sh_type; 212 align = shdr->sh_addralign; 213 } 214 else 215 { 216 Elf64_Shdr *shdr 217 = scn->shdr.e64 ?: __elf64_getshdr_wrlock (scn); 218 219 if (shdr == NULL) 220 /* Something went terribly wrong. */ 221 return 1; 222 223 offset = shdr->sh_offset; 224 size = shdr->sh_size; 225 type = shdr->sh_type; 226 align = shdr->sh_addralign; 227 } 228 229 /* If the section has no data (for whatever reason), leave the `d_buf' 230 pointer NULL. */ 231 if (size != 0 && type != SHT_NOBITS) 232 { 233 /* First a test whether the section is valid at all. */ 234 size_t entsize; 235 236 if (type == SHT_HASH) 237 { 238 GElf_Ehdr ehdr_mem; 239 GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem); 240 entsize = SH_ENTSIZE_HASH (ehdr); 241 } 242 else 243 { 244 Elf_Type t = shtype_map[LIBELF_EV_IDX][TYPEIDX (type)]; 245 if (t == ELF_T_VDEF || t == ELF_T_NHDR 246 || (t == ELF_T_GNUHASH && elf->class == ELFCLASS64)) 247 entsize = 1; 248 else 249 entsize = __libelf_type_sizes[LIBELF_EV_IDX][elf->class - 1][t]; 250 } 251 252 /* We assume it is an array of bytes if it is none of the structured 253 sections we know of. */ 254 if (entsize == 0) 255 entsize = 1; 256 257 if (unlikely (size % entsize != 0)) 258 { 259 __libelf_seterrno (ELF_E_INVALID_DATA); 260 return 1; 261 } 262 263 /* We can use the mapped or loaded data if available. */ 264 if (elf->map_address != NULL) 265 { 266 /* First see whether the information in the section header is 267 valid and it does not ask for too much. */ 268 if (unlikely (offset + size > elf->maximum_size)) 269 { 270 /* Something is wrong. */ 271 __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER); 272 return 1; 273 } 274 275 scn->rawdata_base = scn->rawdata.d.d_buf 276 = (char *) elf->map_address + elf->start_offset + offset; 277 } 278 else if (likely (elf->fildes != -1)) 279 { 280 /* We have to read the data from the file. Allocate the needed 281 memory. */ 282 scn->rawdata_base = scn->rawdata.d.d_buf 283 = (char *) malloc (size); 284 if (scn->rawdata.d.d_buf == NULL) 285 { 286 __libelf_seterrno (ELF_E_NOMEM); 287 return 1; 288 } 289 290 ssize_t n = pread_retry (elf->fildes, scn->rawdata.d.d_buf, size, 291 elf->start_offset + offset); 292 if (unlikely ((size_t) n != size)) 293 { 294 /* Cannot read the data. */ 295 free (scn->rawdata.d.d_buf); 296 scn->rawdata_base = scn->rawdata.d.d_buf = NULL; 297 __libelf_seterrno (ELF_E_READ_ERROR); 298 return 1; 299 } 300 } 301 else 302 { 303 /* The file descriptor is already closed, we cannot get the data 304 anymore. */ 305 __libelf_seterrno (ELF_E_FD_DISABLED); 306 return 1; 307 } 308 } 309 310 scn->rawdata.d.d_size = size; 311 /* Some broken ELF ABI for 64-bit machines use the wrong hash table 312 entry size. See elf-knowledge.h for more information. */ 313 if (type == SHT_HASH && elf->class == ELFCLASS64) 314 { 315 GElf_Ehdr ehdr_mem; 316 GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem); 317 scn->rawdata.d.d_type 318 = (SH_ENTSIZE_HASH (ehdr) == 4 ? ELF_T_WORD : ELF_T_XWORD); 319 } 320 else 321 scn->rawdata.d.d_type = shtype_map[LIBELF_EV_IDX][TYPEIDX (type)]; 322 scn->rawdata.d.d_off = 0; 323 scn->rawdata.d.d_align = align; 324 if (elf->class == ELFCLASS32 325 || (offsetof (struct Elf, state.elf32.ehdr) 326 == offsetof (struct Elf, state.elf64.ehdr))) 327 scn->rawdata.d.d_version = 328 elf->state.elf32.ehdr->e_ident[EI_VERSION]; 329 else 330 scn->rawdata.d.d_version = 331 elf->state.elf64.ehdr->e_ident[EI_VERSION]; 332 333 scn->rawdata.s = scn; 334 335 scn->data_read = 1; 336 337 /* We actually read data from the file. At least we tried. */ 338 scn->flags |= ELF_F_FILEDATA; 339 340 return 0; 341 } 342 343 int 344 internal_function 345 __libelf_set_rawdata (Elf_Scn *scn) 346 { 347 int result; 348 349 if (scn == NULL) 350 return 1; 351 352 rwlock_wrlock (scn->elf->lock); 353 result = __libelf_set_rawdata_wrlock (scn); 354 rwlock_unlock (scn->elf->lock); 355 356 return result; 357 } 358 359 Elf_Data * 360 internal_function 361 __elf_getdata_rdlock (scn, data) 362 Elf_Scn *scn; 363 Elf_Data *data; 364 { 365 Elf_Data *result = NULL; 366 Elf *elf; 367 int locked = 0; 368 369 if (scn == NULL) 370 return NULL; 371 372 if (unlikely (scn->elf->kind != ELF_K_ELF)) 373 { 374 __libelf_seterrno (ELF_E_INVALID_HANDLE); 375 return NULL; 376 } 377 378 /* We will need this multiple times later on. */ 379 elf = scn->elf; 380 381 /* If `data' is not NULL this means we are not addressing the initial 382 data in the file. But this also means this data is already read 383 (since otherwise it is not possible to have a valid `data' pointer) 384 and all the data structures are initialized as well. In this case 385 we can simply walk the list of data records. */ 386 if (data != NULL) 387 { 388 Elf_Data_List *runp; 389 390 /* It is not possible that if DATA is not NULL the first entry is 391 returned. But this also means that there must be a first data 392 entry. */ 393 if (scn->data_list_rear == NULL 394 /* The section the reference data is for must match the section 395 parameter. */ 396 || unlikely (((Elf_Data_Scn *) data)->s != scn)) 397 { 398 __libelf_seterrno (ELF_E_DATA_MISMATCH); 399 goto out; 400 } 401 402 /* We start searching with the first entry. */ 403 runp = &scn->data_list; 404 405 while (1) 406 { 407 /* If `data' does not match any known record punt. */ 408 if (runp == NULL) 409 { 410 __libelf_seterrno (ELF_E_DATA_MISMATCH); 411 goto out; 412 } 413 414 if (&runp->data.d == data) 415 /* Found the entry. */ 416 break; 417 418 runp = runp->next; 419 } 420 421 /* Return the data for the next data record. */ 422 result = runp->next ? &runp->next->data.d : NULL; 423 goto out; 424 } 425 426 /* If the data for this section was not yet initialized do it now. */ 427 if (scn->data_read == 0) 428 { 429 /* We cannot acquire a write lock while we are holding a read 430 lock. Therefore give up the read lock and then get the write 431 lock. But this means that the data could meanwhile be 432 modified, therefore start the tests again. */ 433 rwlock_unlock (elf->lock); 434 rwlock_wrlock (elf->lock); 435 locked = 1; 436 437 /* Read the data from the file. There is always a file (or 438 memory region) associated with this descriptor since 439 otherwise the `data_read' flag would be set. */ 440 if (scn->data_read == 0 && __libelf_set_rawdata_wrlock (scn) != 0) 441 /* Something went wrong. The error value is already set. */ 442 goto out; 443 } 444 445 /* At this point we know the raw data is available. But it might be 446 empty in case the section has size zero (for whatever reason). 447 Now create the converted data in case this is necessary. */ 448 if (scn->data_list_rear == NULL) 449 { 450 if (scn->rawdata.d.d_buf != NULL && scn->rawdata.d.d_size > 0) 451 { 452 if (!locked) 453 { 454 rwlock_unlock (elf->lock); 455 rwlock_wrlock (elf->lock); 456 if (scn->data_list_rear != NULL) 457 goto pass; 458 } 459 460 /* Convert according to the version and the type. */ 461 convert_data (scn, __libelf_version, elf->class, 462 (elf->class == ELFCLASS32 463 || (offsetof (struct Elf, state.elf32.ehdr) 464 == offsetof (struct Elf, state.elf64.ehdr)) 465 ? elf->state.elf32.ehdr->e_ident[EI_DATA] 466 : elf->state.elf64.ehdr->e_ident[EI_DATA]), 467 scn->rawdata.d.d_size, scn->rawdata.d.d_type); 468 } 469 else 470 /* This is an empty or NOBITS section. There is no buffer but 471 the size information etc is important. */ 472 scn->data_list.data.d = scn->rawdata.d; 473 474 scn->data_list_rear = &scn->data_list; 475 } 476 477 /* If no data is present we cannot return any. */ 478 if (scn->data_list_rear != NULL) 479 pass: 480 /* Return the first data element in the list. */ 481 result = &scn->data_list.data.d; 482 483 out: 484 return result; 485 } 486 487 Elf_Data * 488 elf_getdata (scn, data) 489 Elf_Scn *scn; 490 Elf_Data *data; 491 { 492 Elf_Data *result; 493 494 if (scn == NULL) 495 return NULL; 496 497 rwlock_rdlock (scn->elf->lock); 498 result = __elf_getdata_rdlock (scn, data); 499 rwlock_unlock (scn->elf->lock); 500 501 return result; 502 } 503 INTDEF(elf_getdata) 504