1 /* Return the next data element from the section after possibly converting it. 2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. 3 Written by Ulrich Drepper <drepper (at) redhat.com>, 1998. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation, version 2. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program; if not, write to the Free Software Foundation, 16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 17 18 #ifdef HAVE_CONFIG_H 19 # include <config.h> 20 #endif 21 22 #include <stddef.h> 23 #include <string.h> 24 #include <unistd.h> 25 26 #include "libelfP.h" 27 #include "common.h" 28 #include "elf-knowledge.h" 29 30 31 #if _STRING_ARCH_unaligned 32 # define ALLOW_ALIGNED 1 33 #else 34 # define ALLOW_ALIGNED 0 35 #endif 36 37 38 #define TYPEIDX(Sh_Type) \ 39 (Sh_Type >= SHT_NULL && Sh_Type < SHT_NUM \ 40 ? Sh_Type \ 41 : (Sh_Type >= SHT_GNU_LIBLIST && Sh_Type <= SHT_HISUNW \ 42 ? SHT_NUM + Sh_Type - SHT_GNU_LIBLIST \ 43 : 0)) 44 45 static const struct 46 { 47 Elf_Type type; 48 size_t size; 49 #if ALLOW_ALIGNED 50 # define AL(val) 51 #else 52 size_t align; 53 # define AL(val), val 54 #endif 55 } shtype_map[EV_NUM - 1][ELFCLASSNUM - 1][TYPEIDX (SHT_HISUNW) + 1] = 56 { 57 [EV_CURRENT - 1] = 58 { 59 [ELFCLASS32 - 1] = 60 { 61 /* Associate section types with libelf types, their sizes and 62 alignment. SHT_GNU_verdef is special since the section does 63 not contain entries of only one size. */ 64 #define DEFINE(Bits) \ 65 [SHT_SYMTAB] = { ELF_T_SYM, sizeof (ElfW2(Bits,Sym)) \ 66 AL (__alignof__ (ElfW2(Bits,Sym))) }, \ 67 [SHT_RELA] = { ELF_T_RELA, sizeof (ElfW2(Bits,Rela)) \ 68 AL (__alignof__ (ElfW2(Bits,Rela))) }, \ 69 [SHT_HASH] = { ELF_T_WORD, sizeof (ElfW2(Bits,Word)) \ 70 AL (__alignof__ (ElfW2(Bits,Word))) }, \ 71 [SHT_DYNAMIC] = { ELF_T_DYN, sizeof (ElfW2(Bits,Dyn)) \ 72 AL (__alignof__ (ElfW2(Bits,Dyn))) }, \ 73 [SHT_REL] = { ELF_T_REL, sizeof (ElfW2(Bits,Rel)) \ 74 AL (__alignof__ (ElfW2(Bits,Rel))) }, \ 75 [SHT_DYNSYM] = { ELF_T_SYM, sizeof (ElfW2(Bits,Sym)) \ 76 AL (__alignof__ (ElfW2(Bits,Sym))) }, \ 77 [SHT_INIT_ARRAY] = { ELF_T_ADDR, sizeof (ElfW2(Bits,Addr)) \ 78 AL (__alignof__ (ElfW2(Bits,Addr))) }, \ 79 [SHT_FINI_ARRAY] = { ELF_T_ADDR, sizeof (ElfW2(Bits,Addr)) \ 80 AL (__alignof__ (ElfW2(Bits,Addr))) }, \ 81 [SHT_PREINIT_ARRAY] = { ELF_T_ADDR, sizeof (ElfW2(Bits,Addr)) \ 82 AL (__alignof__ (ElfW2(Bits,Addr))) }, \ 83 [SHT_GROUP] = { ELF_T_WORD, sizeof (Elf32_Word) \ 84 AL (__alignof__ (Elf32_Word)) }, \ 85 [SHT_SYMTAB_SHNDX] = { ELF_T_WORD, sizeof (Elf32_Word) \ 86 AL (__alignof__ (Elf32_Word)) }, \ 87 [TYPEIDX (SHT_GNU_verdef)] = { ELF_T_VDEF, 1 AL (1) }, \ 88 [TYPEIDX (SHT_GNU_verneed)] = { ELF_T_VNEED, \ 89 sizeof (ElfW2(Bits,Verneed)) \ 90 AL (__alignof__ (ElfW2(Bits,Verneed)))},\ 91 [TYPEIDX (SHT_GNU_versym)] = { ELF_T_HALF, sizeof (ElfW2(Bits,Versym)) \ 92 AL (__alignof__ (ElfW2(Bits,Versym))) }, \ 93 [TYPEIDX (SHT_SUNW_syminfo)] = { ELF_T_SYMINFO, \ 94 sizeof (ElfW2(Bits,Syminfo)) \ 95 AL(__alignof__ (ElfW2(Bits,Syminfo)))},\ 96 [TYPEIDX (SHT_SUNW_move)] = { ELF_T_MOVE, sizeof (ElfW2(Bits,Move)) \ 97 AL (__alignof__ (ElfW2(Bits,Move))) }, \ 98 [TYPEIDX (SHT_GNU_LIBLIST)] = { ELF_T_LIB, sizeof (ElfW2(Bits,Lib)) \ 99 AL (__alignof__ (ElfW2(Bits,Lib))) } 100 DEFINE (32) 101 }, 102 [ELFCLASS64 - 1] = 103 { 104 DEFINE (64) 105 } 106 } 107 }; 108 109 110 /* Convert the data in the current section. */ 111 static void 112 convert_data (Elf_Scn *scn, int version, int eclass, int data, 113 size_t size, size_t type) 114 { 115 #if ALLOW_ALIGNED 116 /* No need to compute the alignment requirement of the host. */ 117 const size_t align = 1; 118 #else 119 # if EV_NUM != 2 120 size_t align = shtype_map[__libelf_version - 1][eclass - 1][type].align; 121 # else 122 size_t align = shtype_map[0][eclass - 1][type].align; 123 # endif 124 #endif 125 126 if (data == MY_ELFDATA) 127 { 128 if (ALLOW_ALIGNED 129 || (((size_t) ((char *) scn->rawdata_base)) & (align - 1)) == 0) 130 /* No need to copy, we can use the raw data. */ 131 scn->data_base = scn->rawdata_base; 132 else 133 { 134 scn->data_base = (char *) malloc (size); 135 if (scn->data_base == NULL) 136 { 137 __libelf_seterrno (ELF_E_NOMEM); 138 return; 139 } 140 141 /* The copy will be appropriately aligned for direct access. */ 142 memcpy (scn->data_base, scn->rawdata_base, size); 143 } 144 } 145 else 146 { 147 xfct_t fp; 148 149 scn->data_base = (char *) malloc (size); 150 if (scn->data_base == NULL) 151 { 152 __libelf_seterrno (ELF_E_NOMEM); 153 return; 154 } 155 156 /* Get the conversion function. */ 157 #if EV_NUM != 2 158 fp = __elf_xfctstom[version - 1][__libelf_version - 1][eclass - 1][type]; 159 #else 160 fp = __elf_xfctstom[0][0][eclass - 1][type]; 161 #endif 162 163 fp (scn->data_base, scn->rawdata_base, size, 0); 164 } 165 166 scn->data_list.data.d.d_buf = scn->data_base; 167 scn->data_list.data.d.d_size = size; 168 scn->data_list.data.d.d_type = type; 169 scn->data_list.data.d.d_off = scn->rawdata.d.d_off; 170 scn->data_list.data.d.d_align = scn->rawdata.d.d_align; 171 scn->data_list.data.d.d_version = scn->rawdata.d.d_version; 172 173 scn->data_list.data.s = scn; 174 } 175 176 177 /* Store the information for the raw data in the `rawdata' element. */ 178 int 179 internal_function_def 180 __libelf_set_rawdata (Elf_Scn *scn) 181 { 182 size_t offset; 183 size_t size; 184 size_t align; 185 int type; 186 Elf *elf = scn->elf; 187 188 if (elf->class == ELFCLASS32) 189 { 190 Elf32_Shdr *shdr = scn->shdr.e32 ?: INTUSE(elf32_getshdr) (scn); 191 192 if (shdr == NULL) 193 /* Something went terribly wrong. */ 194 return 1; 195 196 offset = shdr->sh_offset; 197 size = shdr->sh_size; 198 type = shdr->sh_type; 199 align = shdr->sh_addralign; 200 } 201 else 202 { 203 Elf64_Shdr *shdr = scn->shdr.e64 ?: INTUSE(elf64_getshdr) (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 215 /* If the section has no data (for whatever reason), leave the `d_buf' 216 pointer NULL. */ 217 if (size != 0 && type != SHT_NOBITS) 218 { 219 /* First a test whether the section is valid at all. */ 220 size_t entsize; 221 222 if (type == SHT_HASH) 223 { 224 GElf_Ehdr ehdr_mem; 225 226 entsize = SH_ENTSIZE_HASH (gelf_getehdr (elf, &ehdr_mem)); 227 } 228 else 229 { 230 #if EV_NUM != 2 231 entsize = shtype_map[__libelf_version - 1][elf->class - 1][TYPEIDX (type)].size; 232 #else 233 entsize = shtype_map[0][elf->class - 1][TYPEIDX (type)].size; 234 #endif 235 } 236 237 /* We assume it is an array of bytes if it is none of the structured 238 sections we know of. */ 239 if (entsize == 0) 240 entsize = 1; 241 242 if (size % entsize != 0) 243 { 244 __libelf_seterrno (ELF_E_INVALID_DATA); 245 return 1; 246 } 247 248 /* We can use the mapped or loaded data if available. */ 249 if (elf->map_address != NULL) 250 { 251 /* First see whether the information in the section header is 252 valid and it does not ask for too much. */ 253 if (offset + size > elf->maximum_size) 254 { 255 /* Something is wrong. */ 256 __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER); 257 return 1; 258 } 259 260 scn->rawdata_base = scn->rawdata.d.d_buf 261 = (char *) elf->map_address + elf->start_offset + offset; 262 } 263 else if (elf->fildes != -1) 264 { 265 /* We have to read the data from the file. Allocate the needed 266 memory. */ 267 scn->rawdata_base = scn->rawdata.d.d_buf 268 = (char *) malloc (size); 269 if (scn->rawdata.d.d_buf == NULL) 270 { 271 __libelf_seterrno (ELF_E_NOMEM); 272 return 1; 273 } 274 275 if ((size_t) pread (elf->fildes, scn->rawdata.d.d_buf, size, 276 elf->start_offset + offset) != size) 277 { 278 /* Cannot read the data. */ 279 free (scn->rawdata.d.d_buf); 280 scn->rawdata_base = scn->rawdata.d.d_buf = NULL; 281 __libelf_seterrno (ELF_E_READ_ERROR); 282 return 1; 283 } 284 } 285 else 286 { 287 /* The file descriptor is already closed, we cannot get the data 288 anymore. */ 289 __libelf_seterrno (ELF_E_FD_DISABLED); 290 return 1; 291 } 292 } 293 294 scn->rawdata.d.d_size = size; 295 /* Some broken ELF ABI for 64-bit machines use the wrong hash table 296 entry size. See elf-knowledge.h for more information. */ 297 if (type == SHT_HASH && elf->class == ELFCLASS64) 298 { 299 GElf_Ehdr ehdr_mem; 300 301 scn->rawdata.d.d_type = (SH_ENTSIZE_HASH (gelf_getehdr (elf, &ehdr_mem)) 302 == 4 ? ELF_T_WORD : ELF_T_XWORD); 303 } 304 else 305 { 306 #if EV_NUM != 2 307 scn->rawdata.d.d_type = 308 shtype_map[__libelf_version - 1][elf->class - 1][TYPEIDX (type)].type; 309 #else 310 scn->rawdata.d.d_type = 311 shtype_map[0][elf->class - 1][TYPEIDX (type)].type; 312 #endif 313 } 314 scn->rawdata.d.d_off = 0; 315 scn->rawdata.d.d_align = align; 316 if (elf->class == ELFCLASS32 317 || (offsetof (struct Elf, state.elf32.ehdr) 318 == offsetof (struct Elf, state.elf64.ehdr))) 319 scn->rawdata.d.d_version = 320 elf->state.elf32.ehdr->e_ident[EI_VERSION]; 321 else 322 scn->rawdata.d.d_version = 323 elf->state.elf64.ehdr->e_ident[EI_VERSION]; 324 325 scn->rawdata.s = scn; 326 327 scn->data_read = 1; 328 329 /* We actually read data from the file. At least we tried. */ 330 scn->flags |= ELF_F_FILEDATA; 331 332 return 0; 333 } 334 335 336 Elf_Data * 337 elf_getdata (scn, data) 338 Elf_Scn *scn; 339 Elf_Data *data; 340 { 341 Elf_Data *result = NULL; 342 Elf *elf; 343 344 if (scn == NULL) 345 return NULL; 346 347 if (unlikely (scn->elf->kind != ELF_K_ELF)) 348 { 349 __libelf_seterrno (ELF_E_INVALID_HANDLE); 350 return NULL; 351 } 352 353 /* We will need this multiple times later on. */ 354 elf = scn->elf; 355 356 rwlock_rdlock (elf->lock); 357 358 /* If `data' is not NULL this means we are not addressing the initial 359 data in the file. But this also means this data is already read 360 (since otherwise it is not possible to have a valid `data' pointer) 361 and all the data structures are initialized as well. In this case 362 we can simply walk the list of data records. */ 363 if (data != NULL) 364 { 365 Elf_Data_List *runp; 366 367 /* It is not possible that if DATA is not NULL the first entry is 368 returned. But this also means that there must be a first data 369 entry. */ 370 if (scn->data_list_rear == NULL 371 /* The section the reference data is for must match the section 372 parameter. */ 373 || unlikely (((Elf_Data_Scn *) data)->s != scn)) 374 { 375 __libelf_seterrno (ELF_E_DATA_MISMATCH); 376 goto out; 377 } 378 379 /* We start searching with the first entry. */ 380 runp = &scn->data_list; 381 382 while (1) 383 { 384 /* If `data' does not match any known record punt. */ 385 if (runp == NULL) 386 { 387 __libelf_seterrno (ELF_E_DATA_MISMATCH); 388 goto out; 389 } 390 391 if (&runp->data.d == data) 392 /* Found the entry. */ 393 break; 394 395 runp = runp->next; 396 } 397 398 /* Return the data for the next data record. */ 399 result = runp->next ? &runp->next->data.d : NULL; 400 goto out; 401 } 402 403 /* If the data for this section was not yet initialized do it now. */ 404 if (scn->data_read == 0) 405 { 406 /* We cannot acquire a write lock while we are holding a read 407 lock. Therefore give up the read lock and then get the write 408 lock. But this means that the data could meanwhile be 409 modified, therefore start the tests again. */ 410 rwlock_unlock (elf->lock); 411 rwlock_wrlock (elf->lock); 412 413 /* Read the data from the file. There is always a file (or 414 memory region) associated with this descriptor since 415 otherwise the `data_read' flag would be set. */ 416 if (scn->data_read == 0 && __libelf_set_rawdata (scn) != 0) 417 /* Something went wrong. The error value is already set. */ 418 goto out; 419 } 420 421 /* At this point we know the raw data is available. But it might be 422 empty in case the section has size zero (for whatever reason). 423 Now create the converted data in case this is necessary. */ 424 if (scn->data_list_rear == NULL) 425 { 426 if (scn->rawdata.d.d_buf != NULL && scn->rawdata.d.d_size > 0) 427 /* Convert according to the version and the type. */ 428 convert_data (scn, __libelf_version, elf->class, 429 (elf->class == ELFCLASS32 430 || (offsetof (struct Elf, state.elf32.ehdr) 431 == offsetof (struct Elf, state.elf64.ehdr)) 432 ? elf->state.elf32.ehdr->e_ident[EI_DATA] 433 : elf->state.elf64.ehdr->e_ident[EI_DATA]), 434 scn->rawdata.d.d_size, 435 scn->rawdata.d.d_type); 436 else 437 /* This is an empty or NOBITS section. There is no buffer but 438 the size information etc is important. */ 439 scn->data_list.data.d = scn->rawdata.d; 440 441 scn->data_list_rear = &scn->data_list; 442 } 443 444 /* If no data is present we cannot return any. */ 445 if (scn->data_list_rear != NULL) 446 /* Return the first data element in the list. */ 447 result = &scn->data_list.data.d; 448 449 out: 450 rwlock_unlock (elf->lock); 451 452 return result; 453 } 454 INTDEF(elf_getdata) 455