125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Update data structures for changes. 225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Copyright (C) 2000-2010 Red Hat, Inc. 303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is part of elfutils. 425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Written by Ulrich Drepper <drepper@redhat.com>, 2000. 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 <endian.h> 3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libelf.h> 3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdbool.h> 3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <string.h> 3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/param.h> 4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "libelfP.h" 4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "elf-knowledge.h" 4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifndef LIBELFBITS 4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define LIBELFBITS 32 4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 5125b3c049e70834cf33790a28643ab058b507b35cBen ChengELFW(default_ehdr,LIBELFBITS) (Elf *elf, ElfW2(LIBELFBITS,Ehdr) *ehdr, 5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t shnum, int *change_bop) 5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Always write the magic bytes. */ 5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (memcmp (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0) 5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG); 5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY; 5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Always set the file class. */ 6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng update_if_changed (ehdr->e_ident[EI_CLASS], ELFW(ELFCLASS,LIBELFBITS), 6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ELFW(elf,LIBELFBITS).ehdr_flags); 6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Set the data encoding if necessary. */ 6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (ehdr->e_ident[EI_DATA] == ELFDATANONE)) 6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr->e_ident[EI_DATA] = 6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng BYTE_ORDER == BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB; 7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY; 7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (unlikely (ehdr->e_ident[EI_DATA] >= ELFDATANUM)) 7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_DATA_ENCODING); 7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng *change_bop = ((BYTE_ORDER == LITTLE_ENDIAN 7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ehdr->e_ident[EI_DATA] != ELFDATA2LSB) 8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng || (BYTE_ORDER == BIG_ENDIAN 8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ehdr->e_ident[EI_DATA] != ELFDATA2MSB)); 8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Unconditionally overwrite the ELF version. */ 8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng update_if_changed (ehdr->e_ident[EI_VERSION], EV_CURRENT, 8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ELFW(elf,LIBELFBITS).ehdr_flags); 8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (ehdr->e_version == EV_NONE) 8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng || unlikely (ehdr->e_version >= EV_NUM)) 8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_UNKNOWN_VERSION); 9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (shnum >= SHN_LORESERVE)) 9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng update_if_changed (ehdr->e_shnum, 0, 9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ELFW(elf,LIBELFBITS).ehdr_flags); 9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng update_if_changed (ehdr->e_shnum, shnum, 10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ELFW(elf,LIBELFBITS).ehdr_flags); 10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (ehdr->e_ehsize != elf_typesize (LIBELFBITS, ELF_T_EHDR, 1))) 10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr->e_ehsize = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1); 10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY; 10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 11325b3c049e70834cf33790a28643ab058b507b35cBen Chengoff_t 11425b3c049e70834cf33790a28643ab058b507b35cBen Chenginternal_function 11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng__elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum) 11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ElfW2(LIBELFBITS,Ehdr) *ehdr; 11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng int changed = 0; 11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng int ehdr_flags = 0; 12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr = __elfw2(LIBELFBITS,getehdr_wrlock) (elf); 12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Set the default values. */ 12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ELFW(default_ehdr,LIBELFBITS) (elf, ehdr, shnum, change_bop) != 0) 12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* At least the ELF header is there. */ 12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng off_t size = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1); 12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Set the program header position. */ 13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL 13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN 13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng || ehdr->e_type == ET_CORE)) 13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng (void) __elfw2(LIBELFBITS,getphdr_wrlock) (elf); 13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL) 13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Only executables, shared objects, and core files have a program 13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng header. */ 13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN 14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng && unlikely (ehdr->e_type != ET_CORE)) 14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_INVALID_PHDR); 14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t phnum; 14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (__elf_getphdrnum_rdlock (elf, &phnum) != 0)) 14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf->flags & ELF_F_LAYOUT) 15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The user is supposed to fill out e_phoff. Use it and 15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng e_phnum to determine the maximum extend. */ 15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng size = MAX ((size_t) size, 15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr->e_phoff 15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng + elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum)); 15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng update_if_changed (ehdr->e_phoff, 16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_typesize (LIBELFBITS, ELF_T_EHDR, 1), 16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr_flags); 16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We need no alignment here. */ 16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng size += elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum); 16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shnum > 0) 17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_ScnList *list; 17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool first = true; 17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (elf->state.ELFW(elf,LIBELFBITS).scns.cnt > 0); 17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shnum >= SHN_LORESERVE) 17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We have to fill in the number of sections in the header 17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng of the zeroth section. */ 18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *scn0 = &elf->state.ELFW(elf,LIBELFBITS).scns.data[0]; 18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng update_if_changed (scn0->shdr.ELFW(e,LIBELFBITS)->sh_size, 18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng shnum, scn0->shdr_flags); 18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Go over all sections and find out how large they are. */ 18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng list = &elf->state.ELFW(elf,LIBELFBITS).scns; 18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Load the section headers if necessary. This loads the 19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng headers for all sections. */ 19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (list->data[1].shdr.ELFW(e,LIBELFBITS) == NULL) 19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng (void) __elfw2(LIBELFBITS,getshdr_wrlock) (&list->data[1]); 19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng do 19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t cnt = first == true; cnt < list->cnt; ++cnt) 19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *scn = &list->data[cnt]; 19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS); 20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng off_t offset = 0; 20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (shdr != NULL); 20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ElfW2(LIBELFBITS,Word) sh_entsize = shdr->sh_entsize; 20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ElfW2(LIBELFBITS,Word) sh_align = shdr->sh_addralign ?: 1; 20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Set the sh_entsize value if we can reliably detect it. */ 20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (shdr->sh_type) 20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_SYMTAB: 21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1); 21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_RELA: 21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng sh_entsize = elf_typesize (LIBELFBITS, ELF_T_RELA, 1); 21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_GROUP: 21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Only relocatable files can contain section groups. */ 21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_type != ET_REL) 21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_GROUP_NOT_REL); 22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* FALLTHROUGH */ 22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_SYMTAB_SHNDX: 22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng sh_entsize = elf_typesize (32, ELF_T_WORD, 1); 22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_HASH: 22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sh_entsize = SH_ENTSIZE_HASH (ehdr); 22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_DYNAMIC: 23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng sh_entsize = elf_typesize (LIBELFBITS, ELF_T_DYN, 1); 23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_REL: 23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng sh_entsize = elf_typesize (LIBELFBITS, ELF_T_REL, 1); 23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_DYNSYM: 23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1); 23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_SUNW_move: 23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng sh_entsize = elf_typesize (LIBELFBITS, ELF_T_MOVE, 1); 24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case SHT_SUNW_syminfo: 24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYMINFO, 1); 24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If the section header contained the wrong entry size 24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng correct it and mark the header as modified. */ 25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng update_if_changed (shdr->sh_entsize, sh_entsize, 25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng scn->shdr_flags); 25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (scn->data_read == 0 25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng && __libelf_set_rawdata_wrlock (scn) != 0) 25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Something went wrong. The error value is already set. */ 25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Iterate over all data blocks. */ 25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (list->data[cnt].data_list_rear != NULL) 26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data_List *dl = &scn->data_list; 26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (dl != NULL) 26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = &dl->data.d; 26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dl == &scn->data_list && data->d_buf == NULL 26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng && scn->rawdata.d.d_buf != NULL) 26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng data = &scn->rawdata.d; 26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (data->d_version == EV_NONE) 27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng || unlikely (data->d_version >= EV_NUM)) 27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_UNKNOWN_VERSION); 27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (! powerof2 (data->d_align))) 27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_INVALID_ALIGN); 28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng sh_align = MAX (sh_align, data->d_align); 28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf->flags & ELF_F_LAYOUT) 28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The user specified the offset and the size. 28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng All we have to do is check whether this block 28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng fits in the size specified for the section. */ 29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely ((GElf_Word) (data->d_off 29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng + data->d_size) 29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng > shdr->sh_size)) 29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_SECTION_TOO_SMALL); 29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Determine the padding. */ 30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng offset = ((offset + data->d_align - 1) 30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng & ~(data->d_align - 1)); 30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng update_if_changed (data->d_off, offset, changed); 30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng offset += data->d_size; 30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Next data block. */ 31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng dl = dl->next; 31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Get the size of the section from the raw data. If 31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng none is available the value is zero. */ 31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng offset += scn->rawdata.d.d_size; 31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf->flags & ELF_F_LAYOUT) 31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng size = MAX ((GElf_Word) size, 32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng shdr->sh_offset 32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng + (shdr->sh_type != SHT_NOBITS 32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ? shdr->sh_size : 0)); 32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The alignment must be a power of two. This is a 32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng requirement from the ELF specification. Additionally 32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng we test for the alignment of the section being large 32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng enough for the largest alignment required by a data 32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng block. */ 33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (! powerof2 (shdr->sh_addralign)) 33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng || unlikely (shdr->sh_addralign < sh_align)) 33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_INVALID_ALIGN); 33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* How much alignment do we need for this section. */ 34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng update_if_changed (shdr->sh_addralign, sh_align, 34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng scn->shdr_flags); 34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng size = (size + sh_align - 1) & ~(sh_align - 1); 34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng int offset_changed = 0; 34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng update_if_changed (shdr->sh_offset, (GElf_Word) size, 34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng offset_changed); 34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng changed |= offset_changed; 34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (offset_changed && scn->data_list_rear == NULL) 35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The position of the section in the file 35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng changed. Create the section data list. */ 35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (__elf_getdata_rdlock (scn, NULL) == NULL) 35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* See whether the section size is correct. */ 35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng update_if_changed (shdr->sh_size, (GElf_Word) offset, 35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng changed); 36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_type != SHT_NOBITS) 36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng size += offset; 36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng scn->flags |= changed; 36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Check that the section size is actually a multiple of 36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng the entry size. */ 36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_entsize != 0 37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng && unlikely (shdr->sh_size % shdr->sh_entsize != 0) 37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (elf->flags & ELF_F_PERMISSIVE) == 0) 37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_INVALID_SHENTSIZE); 37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (list->next == NULL || list->cnt == list->max); 37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng first = false; 38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng while ((list = list->next) != NULL); 38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 38425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Store section information. */ 38525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf->flags & ELF_F_LAYOUT) 38625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 38725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The user is supposed to fill out e_shoff. Use it and 38825b3c049e70834cf33790a28643ab058b507b35cBen Cheng e_shnum (or sh_size of the dummy, first section header) 38925b3c049e70834cf33790a28643ab058b507b35cBen Cheng to determine the maximum extend. */ 39025b3c049e70834cf33790a28643ab058b507b35cBen Cheng size = MAX ((GElf_Word) size, 39125b3c049e70834cf33790a28643ab058b507b35cBen Cheng (ehdr->e_shoff 39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng + (elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum)))); 39325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 39425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 39525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 39625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Align for section header table. 39725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Yes, we use `sizeof' and not `__alignof__' since we do not 39925b3c049e70834cf33790a28643ab058b507b35cBen Cheng want to be surprised by architectures with less strict 40025b3c049e70834cf33790a28643ab058b507b35cBen Cheng alignment rules. */ 40125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define SHDR_ALIGN sizeof (ElfW2(LIBELFBITS,Off)) 40225b3c049e70834cf33790a28643ab058b507b35cBen Cheng size = (size + SHDR_ALIGN - 1) & ~(SHDR_ALIGN - 1); 40325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 40425b3c049e70834cf33790a28643ab058b507b35cBen Cheng update_if_changed (ehdr->e_shoff, (GElf_Word) size, elf->flags); 40525b3c049e70834cf33790a28643ab058b507b35cBen Cheng update_if_changed (ehdr->e_shentsize, 40625b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_typesize (LIBELFBITS, ELF_T_SHDR, 1), 40725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr_flags); 40825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Account for the section header size. */ 41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng size += elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum); 41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 41325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 41425b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ehdr_flags; 41525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 41625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return size; 41725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 418