Branch data Line data Source code
1 : : /* Return number of program headers in the ELF file. 2 : : Copyright (C) 2010, 2014, 2015, 2016 Red Hat, Inc. 3 : : This file is part of elfutils. 4 : : 5 : : This file is free software; you can redistribute it and/or modify 6 : : it under the terms of either 7 : : 8 : : * the GNU Lesser General Public License as published by the Free 9 : : Software Foundation; either version 3 of the License, or (at 10 : : your option) any later version 11 : : 12 : : or 13 : : 14 : : * the GNU General Public License as published by the Free 15 : : Software Foundation; either version 2 of the License, or (at 16 : : your option) any later version 17 : : 18 : : or both in parallel, as here. 19 : : 20 : : elfutils is distributed in the hope that it will be useful, but 21 : : WITHOUT ANY WARRANTY; without even the implied warranty of 22 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 : : General Public License for more details. 24 : : 25 : : You should have received copies of the GNU General Public License and 26 : : the GNU Lesser General Public License along with this program. If 27 : : not, see <http://www.gnu.org/licenses/>. */ 28 : : 29 : : #ifdef HAVE_CONFIG_H 30 : : # include <config.h> 31 : : #endif 32 : : 33 : : #include <assert.h> 34 : : #include <gelf.h> 35 : : #include <stddef.h> 36 : : 37 : : #include "libelfP.h" 38 : : 39 : : 40 : : int 41 : : internal_function 42 : 159702 : __elf_getphdrnum_rdlock (Elf *elf, size_t *dst) 43 : : { 44 [ - + ]: 159702 : if (unlikely (elf->state.elf64.ehdr == NULL)) 45 : : { 46 : : /* Maybe no ELF header was created yet. */ 47 : 0 : *dst = 0; 48 : 0 : __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR); 49 : 0 : return -1; 50 : : } 51 : : 52 : 319404 : *dst = (elf->class == ELFCLASS32 53 : 28630 : ? elf->state.elf32.ehdr->e_phnum 54 [ + + ]: 159702 : : elf->state.elf64.ehdr->e_phnum); 55 : : 56 [ + + ]: 159702 : if (*dst == PN_XNUM) 57 : : { 58 : 12 : const Elf_ScnList *const scns = (elf->class == ELFCLASS32 59 : : ? &elf->state.elf32.scns 60 : : : &elf->state.elf64.scns); 61 : : 62 : : /* If there are no section headers, perhaps this is really just 65536 63 : : written without PN_XNUM support. Either that or it's bad data. */ 64 : : 65 [ - + ]: 12 : if (elf->class == ELFCLASS32) 66 : : { 67 [ # # ]: 0 : if (likely (scns->cnt > 0)) 68 : : { 69 : 0 : Elf_Scn *scn = &elf->state.elf32.scns.data[0]; 70 [ # # ]: 0 : Elf32_Shdr *shdr = scn->shdr.e32 ?: __elf32_getshdr_rdlock (scn); 71 [ # # ]: 0 : if (shdr) 72 : 0 : *dst = shdr->sh_info; 73 : : } 74 : : } 75 : : else 76 : : { 77 [ - + ]: 12 : if (likely (scns->cnt > 0)) 78 : : { 79 : 12 : Elf_Scn *scn = &elf->state.elf64.scns.data[0]; 80 [ + + ]: 12 : Elf64_Shdr *shdr = scn->shdr.e64 ?: __elf64_getshdr_rdlock (scn); 81 [ - + ]: 2 : if (shdr) 82 : 12 : *dst = shdr->sh_info; 83 : : } 84 : : } 85 : : } 86 : : 87 : : return 0; 88 : : } 89 : : 90 : : int 91 : : internal_function 92 : 142904 : __elf_getphdrnum_chk_rdlock (Elf *elf, size_t *dst) 93 : : { 94 : 142904 : int result = __elf_getphdrnum_rdlock (elf, dst); 95 : : 96 : : /* If the phdrs haven't been created or read in yet then do some 97 : : sanity checking to make sure phnum and phoff are consistent. */ 98 [ + + ]: 142904 : if (elf->state.elf.phdr == NULL) 99 : : { 100 : 32248 : Elf64_Off off = (elf->class == ELFCLASS32 101 : 1904 : ? elf->state.elf32.ehdr->e_phoff 102 [ + + ]: 16124 : : elf->state.elf64.ehdr->e_phoff); 103 [ + + ]: 16124 : if (unlikely (off == 0)) 104 : : { 105 : 2328 : *dst = 0; 106 : 2328 : return result; 107 : : } 108 : : 109 [ - + ]: 13796 : if (unlikely (off >= elf->maximum_size)) 110 : : { 111 : 0 : __libelf_seterrno (ELF_E_INVALID_DATA); 112 : 0 : return -1; 113 : : } 114 : : 115 : : /* Check for too many sections. */ 116 : 27592 : size_t phdr_size = (elf->class == ELFCLASS32 117 [ + + ]: 13796 : ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr)); 118 [ - + ]: 13796 : if (unlikely (*dst > SIZE_MAX / phdr_size)) 119 : : { 120 : 0 : __libelf_seterrno (ELF_E_INVALID_DATA); 121 : 0 : return -1; 122 : : } 123 : : 124 : : /* Truncated file? Don't return more than can be indexed. */ 125 [ + - ]: 13796 : if (unlikely (elf->maximum_size - off < *dst * phdr_size)) 126 : 0 : *dst = (elf->maximum_size - off) / phdr_size; 127 : : } 128 : : 129 : : return result; 130 : : } 131 : : 132 : : int 133 : 18330 : elf_getphdrnum (Elf *elf, size_t *dst) 134 : : { 135 : 18330 : int result; 136 : : 137 [ - + ]: 18330 : if (elf == NULL) 138 : : return -1; 139 : : 140 [ - + ]: 18330 : if (unlikely (elf->kind != ELF_K_ELF)) 141 : : { 142 : 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE); 143 : 0 : return -1; 144 : : } 145 : : 146 : 18330 : rwlock_rdlock (elf->lock); 147 : 18330 : result = __elf_getphdrnum_chk_rdlock (elf, dst); 148 : 18330 : rwlock_unlock (elf->lock); 149 : : 150 : 18330 : return result; 151 : : }