16fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath/* Return number of program headers in the ELF file. 21ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaard Copyright (C) 2010, 2014, 2015 Red Hat, Inc. 3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard This file is part of elfutils. 46fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath 5de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard This file is free software; you can redistribute it and/or modify 6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard it under the terms of either 76fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath 8de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * the GNU Lesser General Public License as published by the Free 9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard Software Foundation; either version 3 of the License, or (at 10de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard your option) any later version 11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard 12de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard or 13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard 14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * the GNU General Public License as published by the Free 15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard Software Foundation; either version 2 of the License, or (at 16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard your option) any later version 17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard 18de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard or both in parallel, as here. 19de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard 20de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard elfutils is distributed in the hope that it will be useful, but 216fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath WITHOUT ANY WARRANTY; without even the implied warranty of 226fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 236fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath General Public License for more details. 246fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath 25de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard You should have received copies of the GNU General Public License and 26de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard the GNU Lesser General Public License along with this program. If 27de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard not, see <http://www.gnu.org/licenses/>. */ 286fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath 296fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath#ifdef HAVE_CONFIG_H 306fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath# include <config.h> 316fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath#endif 326fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath 336fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath#include <assert.h> 346fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath#include <gelf.h> 356fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath#include <stddef.h> 366fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath 376fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath#include "libelfP.h" 386fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath 396fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath 406fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrathint 41d8698e55cbe95e56c3a4cbd67c320048ea4f087aMark Wielaardinternal_function 421ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaard__elf_getphdrnum_rdlock (Elf *elf, size_t *dst) 436fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath{ 446fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath if (unlikely (elf->state.elf64.ehdr == NULL)) 456fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath { 466fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath /* Maybe no ELF header was created yet. */ 476fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR); 486fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath return -1; 496fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath } 506fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath 516fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath *dst = (elf->class == ELFCLASS32 526fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath ? elf->state.elf32.ehdr->e_phnum 536fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath : elf->state.elf64.ehdr->e_phnum); 546fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath 556fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath if (*dst == PN_XNUM) 566fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath { 576fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath const Elf_ScnList *const scns = (elf->class == ELFCLASS32 586fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath ? &elf->state.elf32.scns 596fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath : &elf->state.elf64.scns); 606fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath 616fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath /* If there are no section headers, perhaps this is really just 65536 626fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath written without PN_XNUM support. Either that or it's bad data. */ 636fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath 64436275edd015ab6a6f8e164ee2292f74f03d2413Mark Wielaard if (elf->class == ELFCLASS32) 65436275edd015ab6a6f8e164ee2292f74f03d2413Mark Wielaard { 66436275edd015ab6a6f8e164ee2292f74f03d2413Mark Wielaard if (likely (scns->cnt > 0 67436275edd015ab6a6f8e164ee2292f74f03d2413Mark Wielaard && elf->state.elf32.scns.data[0].shdr.e32 != NULL)) 68436275edd015ab6a6f8e164ee2292f74f03d2413Mark Wielaard *dst = scns->data[0].shdr.e32->sh_info; 69436275edd015ab6a6f8e164ee2292f74f03d2413Mark Wielaard } 70436275edd015ab6a6f8e164ee2292f74f03d2413Mark Wielaard else 71436275edd015ab6a6f8e164ee2292f74f03d2413Mark Wielaard { 72436275edd015ab6a6f8e164ee2292f74f03d2413Mark Wielaard if (likely (scns->cnt > 0 73436275edd015ab6a6f8e164ee2292f74f03d2413Mark Wielaard && elf->state.elf64.scns.data[0].shdr.e64 != NULL)) 74436275edd015ab6a6f8e164ee2292f74f03d2413Mark Wielaard *dst = scns->data[0].shdr.e64->sh_info; 75436275edd015ab6a6f8e164ee2292f74f03d2413Mark Wielaard } 766fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath } 776fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath 786fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath return 0; 796fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath} 806fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath 816fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrathint 82d8698e55cbe95e56c3a4cbd67c320048ea4f087aMark Wielaardinternal_function 831ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaard__elf_getphdrnum_chk_rdlock (Elf *elf, size_t *dst) 846fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath{ 85cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard int result = __elf_getphdrnum_rdlock (elf, dst); 862deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard 872deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard /* Do some sanity checking to make sure phnum and phoff are consistent. */ 882deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard Elf64_Off off = (elf->class == ELFCLASS32 892deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard ? elf->state.elf32.ehdr->e_phoff 902deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard : elf->state.elf64.ehdr->e_phoff); 912deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard if (unlikely (off == 0)) 922deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard { 932deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard *dst = 0; 94cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard return result; 952deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard } 962deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard 972deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard if (unlikely (off >= elf->maximum_size)) 982deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard { 992deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard __libelf_seterrno (ELF_E_INVALID_DATA); 100cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard return -1; 1012deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard } 1022deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard 1032deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard /* Check for too many sections. */ 1042deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard size_t phdr_size = (elf->class == ELFCLASS32 1052deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr)); 1062deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard if (unlikely (*dst > SIZE_MAX / phdr_size)) 1072deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard { 1082deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard __libelf_seterrno (ELF_E_INVALID_DATA); 109cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard return -1; 1102deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard } 1112deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard 1122deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard /* Truncated file? Don't return more than can be indexed. */ 1132deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard if (unlikely (elf->maximum_size - off < *dst * phdr_size)) 1142deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard *dst = (elf->maximum_size - off) / phdr_size; 1152deeb7c51020df07d752107cdc6822d70ae1da4eMark Wielaard 116cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard return result; 117cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard} 118cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard 119cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaardint 1201ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaardelf_getphdrnum (Elf *elf, size_t *dst) 121cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard{ 122cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard int result; 123cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard 124cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard if (elf == NULL) 125cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard return -1; 126cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard 127cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard if (unlikely (elf->kind != ELF_K_ELF)) 128cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard { 129cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard __libelf_seterrno (ELF_E_INVALID_HANDLE); 130cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard return -1; 131cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard } 132cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard 133cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard rwlock_rdlock (elf->lock); 134cc62e378c292daaded19f1fe03681d63b7437ea0Mark Wielaard result = __elf_getphdrnum_chk_rdlock (elf, dst); 1356fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath rwlock_unlock (elf->lock); 1366fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath 1376fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath return result; 1386fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath} 139