125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Create descriptor for processing file. 203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Copyright (C) 1998-2010, 2012, 2014 Red Hat, Inc. 303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is part of elfutils. 425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Written by Ulrich Drepper <drepper@redhat.com>, 1998. 525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is free software; you can redistribute it and/or modify 703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes it under the terms of either 825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes * the GNU Lesser General Public License as published by the Free 1003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Software Foundation; either version 3 of the License, or (at 1103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes your option) any later version 1203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes or 1403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes * the GNU General Public License as published by the Free 1603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Software Foundation; either version 2 of the License, or (at 1703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes your option) any later version 1803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes or both in parallel, as here. 2003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 2103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elfutils is distributed in the hope that it will be useful, but 2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng WITHOUT ANY WARRANTY; without even the implied warranty of 2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng General Public License for more details. 2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 2603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes You should have received copies of the GNU General Public License and 2703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes the GNU Lesser General Public License along with this program. If 2803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes not, see <http://www.gnu.org/licenses/>. */ 2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef HAVE_CONFIG_H 3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng# include <config.h> 3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <assert.h> 3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <ctype.h> 3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <errno.h> 3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <fcntl.h> 3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdbool.h> 3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stddef.h> 4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <string.h> 4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <unistd.h> 4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/mman.h> 4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/param.h> 4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/stat.h> 4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <system.h> 4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "libelfP.h" 4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "common.h" 4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Create descriptor for archive in memory. */ 5225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic inline Elf * 5325b3c049e70834cf33790a28643ab058b507b35cBen Chengfile_read_ar (int fildes, void *map_address, off_t offset, size_t maxsize, 5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Cmd cmd, Elf *parent) 5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *elf; 5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Create a descriptor. */ 5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent, 6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ELF_K_AR, 0); 6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf != NULL) 6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We don't read all the symbol tables in advance. All this will 6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng happen on demand. */ 6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ar.offset = offset + SARMAG; 6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ar.elf_ar_hdr.ar_rawname = elf->state.ar.raw_name; 6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return elf; 7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic size_t 7525b3c049e70834cf33790a28643ab058b507b35cBen Chengget_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset, 7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t maxsize) 7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t result; 7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng union 8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Ehdr *e32; 8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf64_Ehdr *e64; 8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *p; 8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } ehdr; 8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng union 8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Ehdr e32; 8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf64_Ehdr e64; 8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } ehdr_mem; 9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool is32 = e_ident[EI_CLASS] == ELFCLASS32; 9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Make the ELF header available. */ 9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (e_ident[EI_DATA] == MY_ELFDATA 9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (ALLOW_UNALIGNED 9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng || (((size_t) e_ident 9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng & ((is32 ? __alignof__ (Elf32_Ehdr) : __alignof__ (Elf64_Ehdr)) 9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng - 1)) == 0))) 9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr.p = e_ident; 9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We already read the ELF header. We have to copy the header 10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng since we possibly modify the data here and the caller 10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng expects the memory it passes in to be preserved. */ 10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr.p = &ehdr_mem; 10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (is32) 10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ALLOW_UNALIGNED) 10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr_mem.e32.e_shnum = ((Elf32_Ehdr *) e_ident)->e_shnum; 11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr_mem.e32.e_shoff = ((Elf32_Ehdr *) e_ident)->e_shoff; 11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (&ehdr_mem, e_ident, sizeof (Elf32_Ehdr)); 11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (e_ident[EI_DATA] != MY_ELFDATA) 11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (ehdr_mem.e32.e_shnum); 11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (ehdr_mem.e32.e_shoff); 12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ALLOW_UNALIGNED) 12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr_mem.e64.e_shnum = ((Elf64_Ehdr *) e_ident)->e_shnum; 12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr_mem.e64.e_shoff = ((Elf64_Ehdr *) e_ident)->e_shoff; 12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (&ehdr_mem, e_ident, sizeof (Elf64_Ehdr)); 13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (e_ident[EI_DATA] != MY_ELFDATA) 13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (ehdr_mem.e64.e_shnum); 13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (ehdr_mem.e64.e_shoff); 13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (is32) 14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Get the number of sections from the ELF header. */ 14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng result = ehdr.e32->e_shnum; 14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (result == 0) && ehdr.e32->e_shoff != 0) 14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 14703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (unlikely (ehdr.e32->e_shoff >= maxsize) 14803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes || unlikely (maxsize - ehdr.e32->e_shoff < sizeof (Elf32_Shdr))) 14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Cannot read the first section header. */ 15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA 15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (ALLOW_UNALIGNED 15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng || (((size_t) ((char *) map_address + offset)) 15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng & (__alignof__ (Elf32_Ehdr) - 1)) == 0)) 15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We can directly access the memory. */ 15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng result = ((Elf32_Shdr *) ((char *) map_address + ehdr.e32->e_shoff 15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng + offset))->sh_size; 15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word size; 16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (likely (map_address != NULL)) 16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* gcc will optimize the memcpy to a simple memory 16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng access while taking care of alignment issues. */ 16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (&size, &((Elf32_Shdr *) ((char *) map_address 16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng + ehdr.e32->e_shoff 16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng + offset))->sh_size, 16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof (Elf32_Word)); 17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (pread_retry (fildes, &size, sizeof (Elf32_Word), 17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng offset + ehdr.e32->e_shoff 17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng + offsetof (Elf32_Shdr, sh_size)) 17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng != sizeof (Elf32_Word))) 17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (size_t) -1l; 17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (e_ident[EI_DATA] != MY_ELFDATA) 17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (size); 17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng result = size; 18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If the section headers were truncated, pretend none were there. */ 18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr.e32->e_shoff > maxsize 18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng || maxsize - ehdr.e32->e_shoff < sizeof (Elf32_Shdr) * result) 18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng result = 0; 18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Get the number of sections from the ELF header. */ 19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng result = ehdr.e64->e_shnum; 19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (result == 0) && ehdr.e64->e_shoff != 0) 19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 19603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (unlikely (ehdr.e64->e_shoff >= maxsize) 19703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes || unlikely (ehdr.e64->e_shoff + sizeof (Elf64_Shdr) > maxsize)) 19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Cannot read the first section header. */ 19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf64_Xword size; 20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA 20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (ALLOW_UNALIGNED 20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng || (((size_t) ((char *) map_address + offset)) 20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng & (__alignof__ (Elf64_Ehdr) - 1)) == 0)) 20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We can directly access the memory. */ 20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng size = ((Elf64_Shdr *) ((char *) map_address + ehdr.e64->e_shoff 20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng + offset))->sh_size; 20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (likely (map_address != NULL)) 21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* gcc will optimize the memcpy to a simple memory 21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng access while taking care of alignment issues. */ 21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (&size, &((Elf64_Shdr *) ((char *) map_address 21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng + ehdr.e64->e_shoff 21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng + offset))->sh_size, 21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof (Elf64_Xword)); 21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (pread_retry (fildes, &size, sizeof (Elf64_Word), 22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng offset + ehdr.e64->e_shoff 22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng + offsetof (Elf64_Shdr, sh_size)) 22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng != sizeof (Elf64_Xword))) 22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (size_t) -1l; 22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (e_ident[EI_DATA] != MY_ELFDATA) 22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (size); 22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (size > ~((GElf_Word) 0)) 23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Invalid value, it is too large. */ 23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (size_t) -1l; 23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng result = size; 23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If the section headers were truncated, pretend none were there. */ 23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr.e64->e_shoff > maxsize 23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng || maxsize - ehdr.e64->e_shoff < sizeof (Elf64_Shdr) * result) 23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng result = 0; 24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return result; 24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Create descriptor for ELF file in memory. */ 24725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Elf * 24825b3c049e70834cf33790a28643ab058b507b35cBen Chengfile_read_elf (int fildes, void *map_address, unsigned char *e_ident, 24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng off_t offset, size_t maxsize, Elf_Cmd cmd, Elf *parent) 25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Verify the binary is of the class we can handle. */ 25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely ((e_ident[EI_CLASS] != ELFCLASS32 25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && e_ident[EI_CLASS] != ELFCLASS64) 25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We also can only handle two encodings. */ 25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng || (e_ident[EI_DATA] != ELFDATA2LSB 25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng && e_ident[EI_DATA] != ELFDATA2MSB))) 25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Cannot handle this. */ 25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_INVALID_FILE); 26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Determine the number of sections. */ 26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t scncnt = get_shnum (map_address, e_ident, fildes, offset, maxsize); 26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (scncnt == (size_t) -1l) 26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Could not determine the number of sections. */ 26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Check for too many sections. */ 27003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (e_ident[EI_CLASS] == ELFCLASS32) 27103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 27203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf32_Shdr))) 27303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return NULL; 27403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 27503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf64_Shdr))) 27603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return NULL; 27703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We can now allocate the memory. Even if there are no section headers, 27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng we allocate space for a zeroth section in case we need it later. */ 28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng const size_t scnmax = (scncnt ?: (cmd == ELF_C_RDWR || cmd == ELF_C_RDWR_MMAP) 28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ? 1 : 0); 28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent, 28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ELF_K_ELF, scnmax * sizeof (Elf_Scn)); 28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf == NULL) 28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Not enough memory. */ 28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert ((unsigned int) scncnt == scncnt); 28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (offsetof (struct Elf, state.elf32.scns) 29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng == offsetof (struct Elf, state.elf64.scns)); 29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf32.scns.cnt = scncnt; 29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf32.scns.max = scnmax; 29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Some more or less arbitrary value. */ 29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf.scnincr = 10; 29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Make the class easily available. */ 29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->class = e_ident[EI_CLASS]; 29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (e_ident[EI_CLASS] == ELFCLASS32) 30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This pointer might not be directly usable if the alignment is 30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng not sufficient for the architecture. */ 30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Ehdr *ehdr = (Elf32_Ehdr *) ((char *) map_address + offset); 30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This is a 32-bit binary. */ 30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA 30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (ALLOW_UNALIGNED 30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng || ((((uintptr_t) ehdr) & (__alignof__ (Elf32_Ehdr) - 1)) == 0 31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ((uintptr_t) ((char *) ehdr + ehdr->e_shoff) 31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng & (__alignof__ (Elf32_Shdr) - 1)) == 0 31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ((uintptr_t) ((char *) ehdr + ehdr->e_phoff) 31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng & (__alignof__ (Elf32_Phdr) - 1)) == 0))) 31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We can use the mmapped memory. */ 31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf32.ehdr = ehdr; 31703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 31803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (unlikely (ehdr->e_shoff >= maxsize) 31903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes || unlikely (maxsize - ehdr->e_shoff 32003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes < scncnt * sizeof (Elf32_Shdr))) 32103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 32203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes free_and_out: 32303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes free (elf); 32403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes __libelf_seterrno (ELF_E_INVALID_FILE); 32503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return NULL; 32603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf32.shdr 32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng = (Elf32_Shdr *) ((char *) ehdr + ehdr->e_shoff); 32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Don't precache the phdr pointer here. 33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf32_getphdr will validate it against the size when asked. */ 33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t cnt = 0; cnt < scncnt; ++cnt) 33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf32.scns.data[cnt].index = cnt; 33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf32.scns.data[cnt].elf = elf; 33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf32.scns.data[cnt].shdr.e32 = 33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng &elf->state.elf32.shdr[cnt]; 33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (likely (elf->state.elf32.shdr[cnt].sh_offset < maxsize) 34003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes && likely (elf->state.elf32.shdr[cnt].sh_size 34103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes <= maxsize - elf->state.elf32.shdr[cnt].sh_offset)) 34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf32.scns.data[cnt].rawdata_base = 34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf32.scns.data[cnt].data_base = 34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ((char *) map_address + offset 34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng + elf->state.elf32.shdr[cnt].sh_offset); 34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns; 34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If this is a section with an extended index add a 34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng reference in the section which uses the extended 35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng index. */ 35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf->state.elf32.shdr[cnt].sh_type == SHT_SYMTAB_SHNDX 35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng && elf->state.elf32.shdr[cnt].sh_link < scncnt) 35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf32.scns.data[elf->state.elf32.shdr[cnt].sh_link].shndx_index 35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng = cnt; 35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Set the own shndx_index field in case it has not yet 35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng been set. */ 35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf->state.elf32.scns.data[cnt].shndx_index == 0) 35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf32.scns.data[cnt].shndx_index = -1; 36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Copy the ELF header. */ 36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf32.ehdr = memcpy (&elf->state.elf32.ehdr_mem, e_ident, 36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof (Elf32_Ehdr)); 36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (e_ident[EI_DATA] != MY_ELFDATA) 36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf32.ehdr_mem.e_type); 37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf32.ehdr_mem.e_machine); 37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf32.ehdr_mem.e_version); 37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf32.ehdr_mem.e_entry); 37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf32.ehdr_mem.e_phoff); 37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf32.ehdr_mem.e_shoff); 37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf32.ehdr_mem.e_flags); 37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf32.ehdr_mem.e_ehsize); 37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf32.ehdr_mem.e_phentsize); 37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf32.ehdr_mem.e_phnum); 38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf32.ehdr_mem.e_shentsize); 38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf32.ehdr_mem.e_shnum); 38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf32.ehdr_mem.e_shstrndx); 38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 38425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 38525b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t cnt = 0; cnt < scncnt; ++cnt) 38625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 38725b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf32.scns.data[cnt].index = cnt; 38825b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf32.scns.data[cnt].elf = elf; 38925b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns; 39025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 39125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 39325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* So far only one block with sections. */ 39425b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf32.scns_last = &elf->state.elf32.scns; 39525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 39625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 39725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This pointer might not be directly usable if the alignment is 39925b3c049e70834cf33790a28643ab058b507b35cBen Cheng not sufficient for the architecture. */ 40025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf64_Ehdr *ehdr = (Elf64_Ehdr *) ((char *) map_address + offset); 40125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 40225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This is a 64-bit binary. */ 40325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA 40425b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (ALLOW_UNALIGNED 40525b3c049e70834cf33790a28643ab058b507b35cBen Cheng || ((((uintptr_t) ehdr) & (__alignof__ (Elf64_Ehdr) - 1)) == 0 40625b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ((uintptr_t) ((char *) ehdr + ehdr->e_shoff) 40725b3c049e70834cf33790a28643ab058b507b35cBen Cheng & (__alignof__ (Elf64_Shdr) - 1)) == 0 40825b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ((uintptr_t) ((char *) ehdr + ehdr->e_phoff) 40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng & (__alignof__ (Elf64_Phdr) - 1)) == 0))) 41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We can use the mmapped memory. */ 41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf64.ehdr = ehdr; 41303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 41403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (unlikely (ehdr->e_shoff >= maxsize) 41503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes || unlikely (maxsize - ehdr->e_shoff 41603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes < scncnt * sizeof (Elf64_Shdr))) 41703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes goto free_and_out; 41825b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf64.shdr 41925b3c049e70834cf33790a28643ab058b507b35cBen Cheng = (Elf64_Shdr *) ((char *) ehdr + ehdr->e_shoff); 42025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 42125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Don't precache the phdr pointer here. 42225b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf64_getphdr will validate it against the size when asked. */ 42325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 42425b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t cnt = 0; cnt < scncnt; ++cnt) 42525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 42625b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf64.scns.data[cnt].index = cnt; 42725b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf64.scns.data[cnt].elf = elf; 42825b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf64.scns.data[cnt].shdr.e64 = 42925b3c049e70834cf33790a28643ab058b507b35cBen Cheng &elf->state.elf64.shdr[cnt]; 43025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (likely (elf->state.elf64.shdr[cnt].sh_offset < maxsize) 43103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes && likely (elf->state.elf64.shdr[cnt].sh_size 43203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes <= maxsize - elf->state.elf64.shdr[cnt].sh_offset)) 43325b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf64.scns.data[cnt].rawdata_base = 43425b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf64.scns.data[cnt].data_base = 43525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ((char *) map_address + offset 43625b3c049e70834cf33790a28643ab058b507b35cBen Cheng + elf->state.elf64.shdr[cnt].sh_offset); 43725b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns; 43825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 43925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If this is a section with an extended index add a 44025b3c049e70834cf33790a28643ab058b507b35cBen Cheng reference in the section which uses the extended 44125b3c049e70834cf33790a28643ab058b507b35cBen Cheng index. */ 44225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf->state.elf64.shdr[cnt].sh_type == SHT_SYMTAB_SHNDX 44325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && elf->state.elf64.shdr[cnt].sh_link < scncnt) 44425b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf64.scns.data[elf->state.elf64.shdr[cnt].sh_link].shndx_index 44525b3c049e70834cf33790a28643ab058b507b35cBen Cheng = cnt; 44625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 44725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Set the own shndx_index field in case it has not yet 44825b3c049e70834cf33790a28643ab058b507b35cBen Cheng been set. */ 44925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf->state.elf64.scns.data[cnt].shndx_index == 0) 45025b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf64.scns.data[cnt].shndx_index = -1; 45125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 45225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 45325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 45425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 45525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Copy the ELF header. */ 45625b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf64.ehdr = memcpy (&elf->state.elf64.ehdr_mem, e_ident, 45725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof (Elf64_Ehdr)); 45825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 45925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (e_ident[EI_DATA] != MY_ELFDATA) 46025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 46125b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf64.ehdr_mem.e_type); 46225b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf64.ehdr_mem.e_machine); 46325b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf64.ehdr_mem.e_version); 46425b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf64.ehdr_mem.e_entry); 46525b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf64.ehdr_mem.e_phoff); 46625b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf64.ehdr_mem.e_shoff); 46725b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf64.ehdr_mem.e_flags); 46825b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf64.ehdr_mem.e_ehsize); 46925b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf64.ehdr_mem.e_phentsize); 47025b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf64.ehdr_mem.e_phnum); 47125b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf64.ehdr_mem.e_shentsize); 47225b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf64.ehdr_mem.e_shnum); 47325b3c049e70834cf33790a28643ab058b507b35cBen Cheng CONVERT (elf->state.elf64.ehdr_mem.e_shstrndx); 47425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 47525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 47625b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t cnt = 0; cnt < scncnt; ++cnt) 47725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 47825b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf64.scns.data[cnt].index = cnt; 47925b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf64.scns.data[cnt].elf = elf; 48025b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns; 48125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 48225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 48325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 48425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* So far only one block with sections. */ 48525b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.elf64.scns_last = &elf->state.elf64.scns; 48625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 48725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 48825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return elf; 48925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 49025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 49125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 49225b3c049e70834cf33790a28643ab058b507b35cBen ChengElf * 49325b3c049e70834cf33790a28643ab058b507b35cBen Chenginternal_function 49425b3c049e70834cf33790a28643ab058b507b35cBen Cheng__libelf_read_mmaped_file (int fildes, void *map_address, off_t offset, 49525b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t maxsize, Elf_Cmd cmd, Elf *parent) 49625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 49725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We have to find out what kind of file this is. We handle ELF 49825b3c049e70834cf33790a28643ab058b507b35cBen Cheng files and archives. To find out what we have we must look at the 49925b3c049e70834cf33790a28643ab058b507b35cBen Cheng header. The header for an ELF file is EI_NIDENT bytes in size, 50025b3c049e70834cf33790a28643ab058b507b35cBen Cheng the header for an archive file SARMAG bytes long. */ 50125b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned char *e_ident = (unsigned char *) map_address + offset; 50225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 50325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* See what kind of object we have here. */ 50425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Kind kind = determine_kind (e_ident, maxsize); 50525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 50625b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (kind) 50725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 50825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELF_K_ELF: 50925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return file_read_elf (fildes, map_address, e_ident, offset, maxsize, 51025b3c049e70834cf33790a28643ab058b507b35cBen Cheng cmd, parent); 51125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 51225b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELF_K_AR: 51325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return file_read_ar (fildes, map_address, offset, maxsize, cmd, parent); 51425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 51525b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 51625b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 51725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 51825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 51925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This case is easy. Since we cannot do anything with this file 52025b3c049e70834cf33790a28643ab058b507b35cBen Cheng create a dummy descriptor. */ 52125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return allocate_elf (fildes, map_address, offset, maxsize, cmd, parent, 52225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ELF_K_NONE, 0); 52325b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 52425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 52525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 52625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Elf * 52725b3c049e70834cf33790a28643ab058b507b35cBen Chengread_unmmaped_file (int fildes, off_t offset, size_t maxsize, Elf_Cmd cmd, 52825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *parent) 52925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 53025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We have to find out what kind of file this is. We handle ELF 53125b3c049e70834cf33790a28643ab058b507b35cBen Cheng files and archives. To find out what we have we must read the 53225b3c049e70834cf33790a28643ab058b507b35cBen Cheng header. The identification header for an ELF file is EI_NIDENT 53325b3c049e70834cf33790a28643ab058b507b35cBen Cheng bytes in size, but we read the whole ELF header since we will 53425b3c049e70834cf33790a28643ab058b507b35cBen Cheng need it anyway later. For archives the header in SARMAG bytes 53525b3c049e70834cf33790a28643ab058b507b35cBen Cheng long. Read the maximum of these numbers. 53625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 53725b3c049e70834cf33790a28643ab058b507b35cBen Cheng XXX We have to change this for the extended `ar' format some day. 53825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 53925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Use a union to ensure alignment. We might later access the 54025b3c049e70834cf33790a28643ab058b507b35cBen Cheng memory as a ElfXX_Ehdr. */ 54125b3c049e70834cf33790a28643ab058b507b35cBen Cheng union 54225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 54325b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf64_Ehdr ehdr; 54425b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned char header[MAX (sizeof (Elf64_Ehdr), SARMAG)]; 54525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } mem; 54625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 54725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Read the head of the file. */ 54825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ssize_t nread = pread_retry (fildes, mem.header, 54925b3c049e70834cf33790a28643ab058b507b35cBen Cheng MIN (MAX (sizeof (Elf64_Ehdr), SARMAG), 55025b3c049e70834cf33790a28643ab058b507b35cBen Cheng maxsize), 55125b3c049e70834cf33790a28643ab058b507b35cBen Cheng offset); 55225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (nread == -1)) 55303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 55403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* We cannot even read the head of the file. Maybe FILDES is associated 55503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes with an unseekable device. This is nothing we can handle. */ 55603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes __libelf_seterrno (ELF_E_INVALID_FILE); 55703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return NULL; 55803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 55925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 56025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* See what kind of object we have here. */ 56125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Kind kind = determine_kind (mem.header, nread); 56225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 56325b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (kind) 56425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 56525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELF_K_AR: 56625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return file_read_ar (fildes, NULL, offset, maxsize, cmd, parent); 56725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 56825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELF_K_ELF: 56925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Make sure at least the ELF header is contained in the file. */ 57025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) nread >= (mem.header[EI_CLASS] == ELFCLASS32 57125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr))) 57225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return file_read_elf (fildes, NULL, mem.header, offset, maxsize, cmd, 57325b3c049e70834cf33790a28643ab058b507b35cBen Cheng parent); 57425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* FALLTHROUGH */ 57525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 57625b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 57725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 57825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 57925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 58025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This case is easy. Since we cannot do anything with this file 58125b3c049e70834cf33790a28643ab058b507b35cBen Cheng create a dummy descriptor. */ 58225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return allocate_elf (fildes, NULL, offset, maxsize, cmd, parent, 58325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ELF_K_NONE, 0); 58425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 58525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 58625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 58725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Open a file for reading. If possible we will try to mmap() the file. */ 58825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct Elf * 58925b3c049e70834cf33790a28643ab058b507b35cBen Chengread_file (int fildes, off_t offset, size_t maxsize, 59025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Cmd cmd, Elf *parent) 59125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 59225b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *map_address = NULL; 59325b3c049e70834cf33790a28643ab058b507b35cBen Cheng int use_mmap = (cmd == ELF_C_READ_MMAP || cmd == ELF_C_RDWR_MMAP 59425b3c049e70834cf33790a28643ab058b507b35cBen Cheng || cmd == ELF_C_WRITE_MMAP 59525b3c049e70834cf33790a28643ab058b507b35cBen Cheng || cmd == ELF_C_READ_MMAP_PRIVATE); 59625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 59725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (use_mmap) 59825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 59925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (parent == NULL) 60025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 60125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (maxsize == ~((size_t) 0)) 60225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 60325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We don't know in the moment how large the file is. 60425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Determine it now. */ 60525b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct stat st; 60625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 60725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fstat (fildes, &st) == 0 60825b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (sizeof (size_t) >= sizeof (st.st_size) 60925b3c049e70834cf33790a28643ab058b507b35cBen Cheng || st.st_size <= ~((size_t) 0))) 61025b3c049e70834cf33790a28643ab058b507b35cBen Cheng maxsize = (size_t) st.st_size; 61125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 61225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 61325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We try to map the file ourself. */ 61425b3c049e70834cf33790a28643ab058b507b35cBen Cheng map_address = mmap (NULL, maxsize, (cmd == ELF_C_READ_MMAP 61525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ? PROT_READ 61625b3c049e70834cf33790a28643ab058b507b35cBen Cheng : PROT_READ|PROT_WRITE), 61725b3c049e70834cf33790a28643ab058b507b35cBen Cheng cmd == ELF_C_READ_MMAP_PRIVATE 61825b3c049e70834cf33790a28643ab058b507b35cBen Cheng || cmd == ELF_C_READ_MMAP 61925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ? MAP_PRIVATE : MAP_SHARED, 62025b3c049e70834cf33790a28643ab058b507b35cBen Cheng fildes, offset); 62125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 62225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (map_address == MAP_FAILED) 62325b3c049e70834cf33790a28643ab058b507b35cBen Cheng map_address = NULL; 62425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 62525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 62625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 62725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The parent is already loaded. Use it. */ 62825b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (maxsize != ~((size_t) 0)); 62925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 63025b3c049e70834cf33790a28643ab058b507b35cBen Cheng map_address = parent->map_address; 63125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 63225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 63325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 63425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If we have the file in memory optimize the access. */ 63525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (map_address != NULL) 63625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 63725b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (map_address != MAP_FAILED); 63825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 63925b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct Elf *result = __libelf_read_mmaped_file (fildes, map_address, 64025b3c049e70834cf33790a28643ab058b507b35cBen Cheng offset, maxsize, cmd, 64125b3c049e70834cf33790a28643ab058b507b35cBen Cheng parent); 64225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 64325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If something went wrong during the initialization unmap the 64425b3c049e70834cf33790a28643ab058b507b35cBen Cheng memory if we mmaped here. */ 64525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (result == NULL 64625b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (parent == NULL 64725b3c049e70834cf33790a28643ab058b507b35cBen Cheng || parent->map_address != map_address)) 64825b3c049e70834cf33790a28643ab058b507b35cBen Cheng munmap (map_address, maxsize); 64925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (parent == NULL) 65025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Remember that we mmap()ed the memory. */ 65125b3c049e70834cf33790a28643ab058b507b35cBen Cheng result->flags |= ELF_F_MMAPPED; 65225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 65325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return result; 65425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 65525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 65625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Otherwise we have to do it the hard way. We read as much as necessary 65725b3c049e70834cf33790a28643ab058b507b35cBen Cheng from the file whenever we need information which is not available. */ 65825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return read_unmmaped_file (fildes, offset, maxsize, cmd, parent); 65925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 66025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 66125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 66225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Find the entry with the long names for the content of this archive. */ 66325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char * 66425b3c049e70834cf33790a28643ab058b507b35cBen Chengread_long_names (Elf *elf) 66525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 66625b3c049e70834cf33790a28643ab058b507b35cBen Cheng off_t offset = SARMAG; /* This is the first entry. */ 66725b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct ar_hdr hdrm; 66825b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct ar_hdr *hdr; 66925b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *newp; 67025b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t len; 67125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 67225b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (1) 67325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 67425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf->map_address != NULL) 67525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 67603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if ((size_t) offset > elf->maximum_size 67703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes || elf->maximum_size - offset < sizeof (struct ar_hdr)) 67825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 67925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 68025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The data is mapped. */ 68125b3c049e70834cf33790a28643ab058b507b35cBen Cheng hdr = (struct ar_hdr *) (elf->map_address + offset); 68225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 68325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 68425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 68525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Read the header from the file. */ 68625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (pread_retry (elf->fildes, &hdrm, sizeof (hdrm), 68725b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->start_offset + offset) 68825b3c049e70834cf33790a28643ab058b507b35cBen Cheng != sizeof (hdrm))) 68925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 69025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 69125b3c049e70834cf33790a28643ab058b507b35cBen Cheng hdr = &hdrm; 69225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 69325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 69425b3c049e70834cf33790a28643ab058b507b35cBen Cheng len = atol (hdr->ar_size); 69525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 69625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (memcmp (hdr->ar_name, "// ", 16) == 0) 69725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 69825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 69925b3c049e70834cf33790a28643ab058b507b35cBen Cheng offset += sizeof (struct ar_hdr) + ((len + 1) & ~1l); 70025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 70125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 70225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Due to the stupid format of the long name table entry (which are not 70325b3c049e70834cf33790a28643ab058b507b35cBen Cheng NUL terminted) we have to provide an appropriate representation anyhow. 70425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Therefore we always make a copy which has the appropriate form. */ 70525b3c049e70834cf33790a28643ab058b507b35cBen Cheng newp = (char *) malloc (len); 70625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (newp != NULL) 70725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 70825b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *runp; 70925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 71025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf->map_address != NULL) 71103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 71203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (len > elf->maximum_size - offset - sizeof (struct ar_hdr)) 71303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes goto too_much; 71403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Simply copy it over. */ 71503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elf->state.ar.long_names = (char *) memcpy (newp, 71603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elf->map_address + offset 71703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes + sizeof (struct ar_hdr), 71803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes len); 71903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 72025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 72125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 72225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely ((size_t) pread_retry (elf->fildes, newp, len, 72325b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->start_offset + offset 72425b3c049e70834cf33790a28643ab058b507b35cBen Cheng + sizeof (struct ar_hdr)) 72525b3c049e70834cf33790a28643ab058b507b35cBen Cheng != len)) 72625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 72703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes too_much: 72825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We were not able to read all data. */ 72925b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (newp); 73025b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ar.long_names = NULL; 73125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 73225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 73325b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ar.long_names = newp; 73425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 73525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 73625b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ar.long_names_len = len; 73725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 73825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Now NUL-terminate the strings. */ 73925b3c049e70834cf33790a28643ab058b507b35cBen Cheng runp = newp; 74025b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (1) 74125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 74203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes char *startp = runp; 74325b3c049e70834cf33790a28643ab058b507b35cBen Cheng runp = (char *) memchr (runp, '/', newp + len - runp); 74425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (runp == NULL) 74503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 74603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* This was the last entry. Clear any left overs. */ 74703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes memset (startp, '\0', newp + len - startp); 74803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 74903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 75025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 75125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* NUL-terminate the string. */ 75225b3c049e70834cf33790a28643ab058b507b35cBen Cheng *runp = '\0'; 75325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 75425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Skip the NUL byte and the \012. */ 75525b3c049e70834cf33790a28643ab058b507b35cBen Cheng runp += 2; 75625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 75725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* A sanity check. Somebody might have generated invalid 75825b3c049e70834cf33790a28643ab058b507b35cBen Cheng archive. */ 75925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (runp >= newp + len) 76025b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 76125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 76225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 76325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 76425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return newp; 76525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 76625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 76725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 76825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Read the next archive header. */ 76925b3c049e70834cf33790a28643ab058b507b35cBen Chengint 77025b3c049e70834cf33790a28643ab058b507b35cBen Chenginternal_function 77125b3c049e70834cf33790a28643ab058b507b35cBen Cheng__libelf_next_arhdr_wrlock (elf) 77225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *elf; 77325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 77425b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct ar_hdr *ar_hdr; 77525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Arhdr *elf_ar_hdr; 77625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 77725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf->map_address != NULL) 77825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 77925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* See whether this entry is in the file. */ 78003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (unlikely ((size_t) elf->state.ar.offset 78103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes > elf->start_offset + elf->maximum_size 78203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes || (elf->start_offset + elf->maximum_size 78303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes - elf->state.ar.offset) < sizeof (struct ar_hdr))) 78425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 78525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This record is not anymore in the file. */ 78625b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_RANGE); 78725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 78825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 78925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ar_hdr = (struct ar_hdr *) (elf->map_address + elf->state.ar.offset); 79025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 79125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 79225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 79325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ar_hdr = &elf->state.ar.ar_hdr; 79425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 79525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (pread_retry (elf->fildes, ar_hdr, sizeof (struct ar_hdr), 79625b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ar.offset) 79725b3c049e70834cf33790a28643ab058b507b35cBen Cheng != sizeof (struct ar_hdr))) 79825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 79925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Something went wrong while reading the file. */ 80025b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_RANGE); 80125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 80225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 80325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 80425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 80525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* One little consistency check. */ 80625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (memcmp (ar_hdr->ar_fmag, ARFMAG, 2) != 0)) 80725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 80825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This is no valid archive. */ 80925b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_ARCHIVE_FMAG); 81025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 81125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 81225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 81325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Copy the raw name over to a NUL terminated buffer. */ 81403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *((char *) mempcpy (elf->state.ar.raw_name, ar_hdr->ar_name, 16)) = '\0'; 81525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 81625b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_ar_hdr = &elf->state.ar.elf_ar_hdr; 81725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 81825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Now convert the `struct ar_hdr' into `Elf_Arhdr'. 81925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Determine whether this is a special entry. */ 82025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ar_hdr->ar_name[0] == '/') 82125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 82225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ar_hdr->ar_name[1] == ' ' 82325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && memcmp (ar_hdr->ar_name, "/ ", 16) == 0) 82425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This is the index. */ 82525b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/", 2); 82603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else if (ar_hdr->ar_name[1] == 'S' 82703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes && memcmp (ar_hdr->ar_name, "/SYM64/ ", 16) == 0) 82803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* 64-bit index. */ 82903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/SYM64/", 8); 83025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (ar_hdr->ar_name[1] == '/' 83125b3c049e70834cf33790a28643ab058b507b35cBen Cheng && memcmp (ar_hdr->ar_name, "// ", 16) == 0) 83225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This is the array with the long names. */ 83325b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "//", 3); 83425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (likely (isdigit (ar_hdr->ar_name[1]))) 83525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 83625b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t offset; 83725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 83825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This is a long name. First we have to read the long name 83925b3c049e70834cf33790a28643ab058b507b35cBen Cheng table, if this hasn't happened already. */ 84025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (elf->state.ar.long_names == NULL 84125b3c049e70834cf33790a28643ab058b507b35cBen Cheng && read_long_names (elf) == NULL)) 84225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 84325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* No long name table although it is reference. The archive is 84425b3c049e70834cf33790a28643ab058b507b35cBen Cheng broken. */ 84525b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_INVALID_ARCHIVE); 84625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 84725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 84825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 84925b3c049e70834cf33790a28643ab058b507b35cBen Cheng offset = atol (ar_hdr->ar_name + 1); 85025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (offset >= elf->state.ar.long_names_len)) 85125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 85225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The index in the long name table is larger than the table. */ 85325b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_INVALID_ARCHIVE); 85425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 85525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 85625b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_ar_hdr->ar_name = elf->state.ar.long_names + offset; 85725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 85825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 85925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 86025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This is none of the known special entries. */ 86125b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_INVALID_ARCHIVE); 86225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 86325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 86425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 86525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 86625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 86725b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *endp; 86825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 86925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* It is a normal entry. Copy over the name. */ 87025b3c049e70834cf33790a28643ab058b507b35cBen Cheng endp = (char *) memccpy (elf->state.ar.ar_name, ar_hdr->ar_name, 87125b3c049e70834cf33790a28643ab058b507b35cBen Cheng '/', 16); 87225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (endp != NULL) 87325b3c049e70834cf33790a28643ab058b507b35cBen Cheng endp[-1] = '\0'; 87425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 87525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 87625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* In the old BSD style of archive, there is no / terminator. 87725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Instead, there is space padding at the end of the name. */ 87825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t i = 15; 87925b3c049e70834cf33790a28643ab058b507b35cBen Cheng do 88025b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ar.ar_name[i] = '\0'; 88125b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (i > 0 && elf->state.ar.ar_name[--i] == ' '); 88225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 88325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 88425b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_ar_hdr->ar_name = elf->state.ar.ar_name; 88525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 88625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 88725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (ar_hdr->ar_size[0] == ' ')) 88825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Something is really wrong. We cannot live without a size for 88925b3c049e70834cf33790a28643ab058b507b35cBen Cheng the member since it will not be possible to find the next 89025b3c049e70834cf33790a28643ab058b507b35cBen Cheng archive member. */ 89125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 89225b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_INVALID_ARCHIVE); 89325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 89425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 89525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 89625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Since there are no specialized functions to convert ASCII to 89725b3c049e70834cf33790a28643ab058b507b35cBen Cheng time_t, uid_t, gid_t, mode_t, and off_t we use either atol or 89825b3c049e70834cf33790a28643ab058b507b35cBen Cheng atoll depending on the size of the types. We are also prepared 89925b3c049e70834cf33790a28643ab058b507b35cBen Cheng for the case where the whole field in the `struct ar_hdr' is 90025b3c049e70834cf33790a28643ab058b507b35cBen Cheng filled in which case we cannot simply use atol/l but instead have 90125b3c049e70834cf33790a28643ab058b507b35cBen Cheng to create a temporary copy. */ 90225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 90325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define INT_FIELD(FIELD) \ 90425b3c049e70834cf33790a28643ab058b507b35cBen Cheng do \ 90525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { \ 90625b3c049e70834cf33790a28643ab058b507b35cBen Cheng char buf[sizeof (ar_hdr->FIELD) + 1]; \ 90725b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *string = ar_hdr->FIELD; \ 90825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ar_hdr->FIELD[sizeof (ar_hdr->FIELD) - 1] != ' ') \ 90925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { \ 91003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *((char *) mempcpy (buf, ar_hdr->FIELD, sizeof (ar_hdr->FIELD))) \ 91125b3c049e70834cf33790a28643ab058b507b35cBen Cheng = '\0'; \ 91225b3c049e70834cf33790a28643ab058b507b35cBen Cheng string = buf; \ 91325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } \ 91425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sizeof (elf_ar_hdr->FIELD) <= sizeof (long int)) \ 91525b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atol (string); \ 91625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else \ 91725b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atoll (string); \ 91825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } \ 91925b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (0) 92025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 92125b3c049e70834cf33790a28643ab058b507b35cBen Cheng INT_FIELD (ar_date); 92225b3c049e70834cf33790a28643ab058b507b35cBen Cheng INT_FIELD (ar_uid); 92325b3c049e70834cf33790a28643ab058b507b35cBen Cheng INT_FIELD (ar_gid); 92425b3c049e70834cf33790a28643ab058b507b35cBen Cheng INT_FIELD (ar_mode); 92525b3c049e70834cf33790a28643ab058b507b35cBen Cheng INT_FIELD (ar_size); 92625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 92703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Truncated file? */ 92803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes size_t maxsize; 92903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes maxsize = elf->maximum_size - elf->state.ar.offset - sizeof (struct ar_hdr); 93003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if ((size_t) elf_ar_hdr->ar_size > maxsize) 93103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elf_ar_hdr->ar_size = maxsize; 93203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 93325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 93425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 93525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 93625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 93725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* We were asked to return a clone of an existing descriptor. This 93825b3c049e70834cf33790a28643ab058b507b35cBen Cheng function must be called with the lock on the parent descriptor 93925b3c049e70834cf33790a28643ab058b507b35cBen Cheng being held. */ 94025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Elf * 94125b3c049e70834cf33790a28643ab058b507b35cBen Chengdup_elf (int fildes, Elf_Cmd cmd, Elf *ref) 94225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 94325b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct Elf *result; 94425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 94525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fildes == -1) 94625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Allow the user to pass -1 as the file descriptor for the new file. */ 94725b3c049e70834cf33790a28643ab058b507b35cBen Cheng fildes = ref->fildes; 94825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The file descriptor better should be the same. If it was disconnected 94925b3c049e70834cf33790a28643ab058b507b35cBen Cheng already (using `elf_cntl') we do not test it. */ 95025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (unlikely (ref->fildes != -1 && fildes != ref->fildes)) 95125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 95225b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_FD_MISMATCH); 95325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 95425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 95525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 95625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The mode must allow reading. I.e., a descriptor creating with a 95725b3c049e70834cf33790a28643ab058b507b35cBen Cheng command different then ELF_C_READ, ELF_C_WRITE and ELF_C_RDWR is 95825b3c049e70834cf33790a28643ab058b507b35cBen Cheng not allowed. */ 95925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (ref->cmd != ELF_C_READ && ref->cmd != ELF_C_READ_MMAP 96025b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ref->cmd != ELF_C_WRITE && ref->cmd != ELF_C_WRITE_MMAP 96125b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP 96225b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ref->cmd != ELF_C_READ_MMAP_PRIVATE)) 96325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 96425b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_INVALID_OP); 96525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 96625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 96725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 96825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Now it is time to distinguish between reading normal files and 96925b3c049e70834cf33790a28643ab058b507b35cBen Cheng archives. Normal files can easily be handled be incrementing the 97025b3c049e70834cf33790a28643ab058b507b35cBen Cheng reference counter and return the same descriptor. */ 97125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ref->kind != ELF_K_AR) 97225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 97325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ++ref->ref_count; 97425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return ref; 97525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 97625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 97725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This is an archive. We must create a descriptor for the archive 97825b3c049e70834cf33790a28643ab058b507b35cBen Cheng member the internal pointer of the archive file desriptor is 97925b3c049e70834cf33790a28643ab058b507b35cBen Cheng pointing to. First read the header of the next member if this 98025b3c049e70834cf33790a28643ab058b507b35cBen Cheng has not happened already. */ 98125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ref->state.ar.elf_ar_hdr.ar_name == NULL 98225b3c049e70834cf33790a28643ab058b507b35cBen Cheng && __libelf_next_arhdr_wrlock (ref) != 0) 98325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Something went wrong. Maybe there is no member left. */ 98425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 98525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 98625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We have all the information we need about the next archive member. 98725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Now create a descriptor for it. */ 98825b3c049e70834cf33790a28643ab058b507b35cBen Cheng result = read_file (fildes, ref->state.ar.offset + sizeof (struct ar_hdr), 98925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ref->state.ar.elf_ar_hdr.ar_size, cmd, ref); 99025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 99125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Enlist this new descriptor in the list of children. */ 99225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (result != NULL) 99325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 99425b3c049e70834cf33790a28643ab058b507b35cBen Cheng result->next = ref->state.ar.children; 99525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ref->state.ar.children = result; 99625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 99725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 99825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return result; 99925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 100025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 100125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 100225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Return desriptor for empty file ready for writing. */ 100325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct Elf * 100425b3c049e70834cf33790a28643ab058b507b35cBen Chengwrite_file (int fd, Elf_Cmd cmd) 100525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 100625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We simply create an empty `Elf' structure. */ 100725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define NSCNSALLOC 10 100825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *result = allocate_elf (fd, NULL, 0, 0, cmd, NULL, ELF_K_ELF, 100925b3c049e70834cf33790a28643ab058b507b35cBen Cheng NSCNSALLOC * sizeof (Elf_Scn)); 101025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 101125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (result != NULL) 101225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 101325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We have to write to the file in any case. */ 101425b3c049e70834cf33790a28643ab058b507b35cBen Cheng result->flags = ELF_F_DIRTY; 101525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 101625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Some more or less arbitrary value. */ 101725b3c049e70834cf33790a28643ab058b507b35cBen Cheng result->state.elf.scnincr = NSCNSALLOC; 101825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 101925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We have allocated room for some sections. */ 102025b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (offsetof (struct Elf, state.elf32.scns) 102125b3c049e70834cf33790a28643ab058b507b35cBen Cheng == offsetof (struct Elf, state.elf64.scns)); 102225b3c049e70834cf33790a28643ab058b507b35cBen Cheng result->state.elf.scns_last = &result->state.elf32.scns; 102325b3c049e70834cf33790a28643ab058b507b35cBen Cheng result->state.elf32.scns.max = NSCNSALLOC; 102425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 102525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 102625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return result; 102725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 102825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 102925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 103025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Return a descriptor for the file belonging to FILDES. */ 103125b3c049e70834cf33790a28643ab058b507b35cBen ChengElf * 103225b3c049e70834cf33790a28643ab058b507b35cBen Chengelf_begin (fildes, cmd, ref) 103325b3c049e70834cf33790a28643ab058b507b35cBen Cheng int fildes; 103425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Cmd cmd; 103525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *ref; 103625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 103725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *retval; 103825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 103925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (! __libelf_version_initialized)) 104025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 104125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Version wasn't set so far. */ 104225b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_NO_VERSION); 104325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 104425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 104525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 104625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ref != NULL) 104725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Make sure the descriptor is not suddenly going away. */ 104825b3c049e70834cf33790a28643ab058b507b35cBen Cheng rwlock_rdlock (ref->lock); 104925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (unlikely (fcntl (fildes, F_GETFL) == -1 && errno == EBADF)) 105025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 105125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We cannot do anything productive without a file descriptor. */ 105225b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_INVALID_FILE); 105325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 105425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 105525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 105625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *lock_dup_elf () 105725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 105825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We need wrlock to dup an archive. */ 105925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ref->kind == ELF_K_AR) 106025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 106125b3c049e70834cf33790a28643ab058b507b35cBen Cheng rwlock_unlock (ref->lock); 106225b3c049e70834cf33790a28643ab058b507b35cBen Cheng rwlock_wrlock (ref->lock); 106325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 106425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 106525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Duplicate the descriptor. */ 106625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return dup_elf (fildes, cmd, ref); 106725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 106825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 106925b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (cmd) 107025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 107125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELF_C_NULL: 107225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We simply return a NULL pointer. */ 107325b3c049e70834cf33790a28643ab058b507b35cBen Cheng retval = NULL; 107425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 107525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 107625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELF_C_READ_MMAP_PRIVATE: 107725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If we have a reference it must also be opened this way. */ 107825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (ref != NULL && ref->cmd != ELF_C_READ_MMAP_PRIVATE)) 107925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 108025b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_INVALID_CMD); 108125b3c049e70834cf33790a28643ab058b507b35cBen Cheng retval = NULL; 108225b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 108325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 108425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* FALLTHROUGH */ 108525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 108625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELF_C_READ: 108725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELF_C_READ_MMAP: 108825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ref != NULL) 108925b3c049e70834cf33790a28643ab058b507b35cBen Cheng retval = lock_dup_elf (); 109025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 109125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Create descriptor for existing file. */ 109225b3c049e70834cf33790a28643ab058b507b35cBen Cheng retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL); 109325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 109425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 109525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELF_C_RDWR: 109625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELF_C_RDWR_MMAP: 109725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If we have a REF object it must also be opened using this 109825b3c049e70834cf33790a28643ab058b507b35cBen Cheng command. */ 109925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ref != NULL) 110025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 110125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP 110225b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ref->cmd != ELF_C_WRITE 110325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ref->cmd != ELF_C_WRITE_MMAP)) 110425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 110525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This is not ok. REF must also be opened for writing. */ 110625b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_INVALID_CMD); 110725b3c049e70834cf33790a28643ab058b507b35cBen Cheng retval = NULL; 110825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 110925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 111025b3c049e70834cf33790a28643ab058b507b35cBen Cheng retval = lock_dup_elf (); 111125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 111225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 111325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Create descriptor for existing file. */ 111425b3c049e70834cf33790a28643ab058b507b35cBen Cheng retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL); 111525b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 111625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 111725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELF_C_WRITE: 111825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELF_C_WRITE_MMAP: 111925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We ignore REF and prepare a descriptor to write a new file. */ 112025b3c049e70834cf33790a28643ab058b507b35cBen Cheng retval = write_file (fildes, cmd); 112125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 112225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 112325b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 112425b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_INVALID_CMD); 112525b3c049e70834cf33790a28643ab058b507b35cBen Cheng retval = NULL; 112625b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 112725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 112825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 112925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Release the lock. */ 113025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ref != NULL) 113125b3c049e70834cf33790a28643ab058b507b35cBen Cheng rwlock_unlock (ref->lock); 113225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 113325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return retval; 113425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 113525b3c049e70834cf33790a28643ab058b507b35cBen ChengINTDEF(elf_begin) 1136