125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Write changed data structures. 225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Copyright (C) 2000-2010 Red Hat, Inc. 325b3c049e70834cf33790a28643ab058b507b35cBen Cheng This file is part of Red Hat elfutils. 425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Written by Ulrich Drepper <drepper@redhat.com>, 2000. 525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Red Hat elfutils is free software; you can redistribute it and/or modify 725b3c049e70834cf33790a28643ab058b507b35cBen Cheng it under the terms of the GNU General Public License as published by the 825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Free Software Foundation; version 2 of the License. 925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Red Hat elfutils is distributed in the hope that it will be useful, but 1125b3c049e70834cf33790a28643ab058b507b35cBen Cheng WITHOUT ANY WARRANTY; without even the implied warranty of 1225b3c049e70834cf33790a28643ab058b507b35cBen Cheng MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1325b3c049e70834cf33790a28643ab058b507b35cBen Cheng General Public License for more details. 1425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1525b3c049e70834cf33790a28643ab058b507b35cBen Cheng You should have received a copy of the GNU General Public License along 1625b3c049e70834cf33790a28643ab058b507b35cBen Cheng with Red Hat elfutils; if not, write to the Free Software Foundation, 1725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. 1825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1925b3c049e70834cf33790a28643ab058b507b35cBen Cheng In addition, as a special exception, Red Hat, Inc. gives You the 2025b3c049e70834cf33790a28643ab058b507b35cBen Cheng additional right to link the code of Red Hat elfutils with code licensed 2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng under any Open Source Initiative certified open source license 2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng (http://www.opensource.org/licenses/index.php) which requires the 2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng distribution of source code with any binary distribution and to 2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng distribute linked combinations of the two. Non-GPL Code permitted under 2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng this exception must only link to the code of Red Hat elfutils through 2625b3c049e70834cf33790a28643ab058b507b35cBen Cheng those well defined interfaces identified in the file named EXCEPTION 2725b3c049e70834cf33790a28643ab058b507b35cBen Cheng found in the source code files (the "Approved Interfaces"). The files 2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng of Non-GPL Code may instantiate templates or use macros or inline 2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng functions from the Approved Interfaces without causing the resulting 3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng work to be covered by the GNU General Public License. Only Red Hat, 3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Inc. may make changes or additions to the list of Approved Interfaces. 3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Red Hat's grant of this exception is conditioned upon your not adding 3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng any new exceptions. If you wish to add a new Approved Interface or 3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng exception, please contact Red Hat. You must obey the GNU General Public 3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng License in all respects for all of the Red Hat elfutils code and other 3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng code used in conjunction with Red Hat elfutils except the Non-GPL Code 3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng covered by this exception. If you modify this file, you may extend this 3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng exception to your version of the file, but you are not obligated to do 3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng so. If you do not wish to provide this exception without modification, 4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng you must delete this exception statement from your version and license 4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng this file solely under the GPL without exception. 4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng Red Hat elfutils is an included package of the Open Invention Network. 4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng An included package of the Open Invention Network is a package for which 4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Open Invention Network licensees cross-license their patents. No patent 4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng license is granted, either expressly or impliedly, by designation as an 4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng included package. Should you wish to participate in the Open Invention 4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Network licensing program, please visit www.openinventionnetwork.com 4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng <http://www.openinventionnetwork.com>. */ 5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef HAVE_CONFIG_H 5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng# include <config.h> 5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <assert.h> 5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <errno.h> 5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libelf.h> 5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdbool.h> 5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdlib.h> 6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <string.h> 6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <unistd.h> 6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/mman.h> 6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/param.h> 6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <system.h> 6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "libelfP.h" 6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifndef LIBELFBITS 7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define LIBELFBITS 32 7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 7525b3c049e70834cf33790a28643ab058b507b35cBen Chengcompare_sections (const void *a, const void *b) 7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng const Elf_Scn **scna = (const Elf_Scn **) a; 7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng const Elf_Scn **scnb = (const Elf_Scn **) b; 7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_offset 8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng < (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_offset) 8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_offset 8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng > (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_offset) 8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_size 8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng < (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_size) 9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_size 9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng > (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_size) 9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((*scna)->index < (*scnb)->index) 9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((*scna)->index > (*scnb)->index) 10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Insert the sections in the list into the provided array and sort 10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng them according to their start offsets. For sections with equal 10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng start offsets, the size is used; for sections with equal start 10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng offsets and sizes, the section index is used. Sorting by size 11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ensures that zero-length sections are processed first, which 11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng is what we want since they do not advance our file writing position. */ 11225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void 11325b3c049e70834cf33790a28643ab058b507b35cBen Chengsort_sections (Elf_Scn **scns, Elf_ScnList *list) 11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn **scnp = scns; 11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng do 11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t cnt = 0; cnt < list->cnt; ++cnt) 11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng *scnp++ = &list->data[cnt]; 11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng while ((list = list->next) != NULL); 12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng qsort (scns, scnp - scns, sizeof (*scns), compare_sections); 12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12525b3c049e70834cf33790a28643ab058b507b35cBen Chengint 12625b3c049e70834cf33790a28643ab058b507b35cBen Chenginternal_function 12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng__elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum) 12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool previous_scn_changed = false; 13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We need the ELF header several times. */ 13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr; 13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Write out the ELF header. */ 13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((elf->state.ELFW(elf,LIBELFBITS).ehdr_flags | elf->flags) & ELF_F_DIRTY) 13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If the type sizes should be different at some time we have to 13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng rewrite this code. */ 13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (sizeof (ElfW2(LIBELFBITS,Ehdr)) 14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng == elf_typesize (LIBELFBITS, ELF_T_EHDR, 1)); 14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (change_bo)) 14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Today there is only one version of the ELF header. */ 14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if EV_NUM != 2 14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng xfct_t fctp; 14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR]; 14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng# undef fctp 15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR] 15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Do the real work. */ 15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng (*fctp) ((char *) elf->map_address + elf->start_offset, ehdr, 15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof (ElfW2(LIBELFBITS,Ehdr)), 1); 15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (elf->map_address + elf->start_offset, ehdr, 15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof (ElfW2(LIBELFBITS,Ehdr))); 16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ELFW(elf,LIBELFBITS).ehdr_flags &= ~ELF_F_DIRTY; 16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We start writing sections after the ELF header only if there is 16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng no program header. */ 16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng previous_scn_changed = elf->state.ELFW(elf,LIBELFBITS).phdr == NULL; 16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t phnum; 16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (__elf_getphdrnum_rdlock (elf, &phnum) != 0)) 17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Write out the program header table. */ 17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL 17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ((elf->state.ELFW(elf,LIBELFBITS).phdr_flags | elf->flags) 17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng & ELF_F_DIRTY)) 17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If the type sizes should be different at some time we have to 17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng rewrite this code. */ 17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (sizeof (ElfW2(LIBELFBITS,Phdr)) 18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng == elf_typesize (LIBELFBITS, ELF_T_PHDR, 1)); 18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Maybe the user wants a gap between the ELF header and the program 18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng header. */ 18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_phoff > ehdr->e_ehsize) 18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng memset (elf->map_address + elf->start_offset + ehdr->e_ehsize, 18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_fill_byte, ehdr->e_phoff - ehdr->e_ehsize); 18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (change_bo)) 18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Today there is only one version of the ELF header. */ 19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if EV_NUM != 2 19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng xfct_t fctp; 19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR]; 19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng# undef fctp 19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR] 19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Do the real work. */ 20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng (*fctp) (elf->map_address + elf->start_offset + ehdr->e_phoff, 20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ELFW(elf,LIBELFBITS).phdr, 20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum, 1); 20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (elf->map_address + elf->start_offset + ehdr->e_phoff, 20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ELFW(elf,LIBELFBITS).phdr, 20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum); 20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ELFW(elf,LIBELFBITS).phdr_flags &= ~ELF_F_DIRTY; 21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We modified the program header. Maybe this created a gap so 21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng we have to write fill bytes, if necessary. */ 21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng previous_scn_changed = true; 21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* From now on we have to keep track of the last position to eventually 21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng fill the gaps with the prescribed fill byte. */ 21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *last_position = ((char *) elf->map_address + elf->start_offset 21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng + MAX (elf_typesize (LIBELFBITS, ELF_T_EHDR, 1), 22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr->e_phoff) 22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng + elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum)); 22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Write all the sections. Well, only those which are modified. */ 22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shnum > 0) 22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_ScnList *list = &elf->state.ELFW(elf,LIBELFBITS).scns; 22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn **scns = (Elf_Scn **) alloca (shnum * sizeof (Elf_Scn *)); 22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *const shdr_start = ((char *) elf->map_address + elf->start_offset 22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng + ehdr->e_shoff); 23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *const shdr_end = shdr_start + ehdr->e_shnum * ehdr->e_shentsize; 23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if EV_NUM != 2 23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng xfct_t shdr_fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR]; 23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng# undef shdr_fctp 23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define shdr_fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR] 23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define shdr_dest ((ElfW2(LIBELFBITS,Shdr) *) shdr_start) 23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Get all sections into the array and sort them. */ 24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng sort_sections (scns, list); 24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We possibly have to copy the section header data because moving 24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng the sections might overwrite the data. */ 24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t cnt = 0; cnt < shnum; ++cnt) 24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *scn = scns[cnt]; 24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!elf->state.ELFW(elf,LIBELFBITS).shdr_malloced 25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (scn->shdr_flags & ELF_F_MALLOCED) == 0 25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng && scn->shdr.ELFW(e,LIBELFBITS) != &shdr_dest[scn->index]) 25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert ((char *) elf->map_address + elf->start_offset 25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng < (char *) scn->shdr.ELFW(e,LIBELFBITS)); 25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert ((char *) scn->shdr.ELFW(e,LIBELFBITS) 25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng < ((char *) elf->map_address + elf->start_offset 25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng + elf->maximum_size)); 25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *p = alloca (sizeof (ElfW2(LIBELFBITS,Shdr))); 26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng scn->shdr.ELFW(e,LIBELFBITS) 26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng = memcpy (p, scn->shdr.ELFW(e,LIBELFBITS), 26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof (ElfW2(LIBELFBITS,Shdr))); 26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If the file is mmaped and the original position of the 26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng section in the file is lower than the new position we 26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng need to save the section content since otherwise it is 26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng overwritten before it can be copied. If there are 26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng multiple data segments in the list only the first can be 27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng from the file. */ 27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (((char *) elf->map_address + elf->start_offset 27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng <= (char *) scn->data_list.data.d.d_buf) 27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ((char *) scn->data_list.data.d.d_buf 27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng < ((char *) elf->map_address + elf->start_offset 27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng + elf->maximum_size)) 27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (((char *) elf->map_address + elf->start_offset 27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng + scn->shdr.ELFW(e,LIBELFBITS)->sh_offset) 27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng > (char *) scn->data_list.data.d.d_buf)) 27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *p = malloc (scn->data_list.data.d.d_size); 28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (p == NULL) 28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_NOMEM); 28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng scn->data_list.data.d.d_buf = scn->data_base 28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng = memcpy (p, scn->data_list.data.d.d_buf, 28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng scn->data_list.data.d.d_size); 28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Iterate over all the section in the order in which they 29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng appear in the output file. */ 29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t cnt = 0; cnt < shnum; ++cnt) 29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *scn = scns[cnt]; 29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (scn->index == 0) 29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The dummy section header entry. It should not be 30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng possible to mark this "section" as dirty. */ 30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert ((scn->flags & ELF_F_DIRTY) == 0); 30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS); 30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_type == SHT_NOBITS) 30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto next; 30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *scn_start = ((char *) elf->map_address 31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng + elf->start_offset + shdr->sh_offset); 31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data_List *dl = &scn->data_list; 31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool scn_changed = false; 31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng void fill_mmap (size_t offset) 31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t written = 0; 31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (last_position < shdr_start) 31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng written = MIN (scn_start + offset - last_position, 32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng shdr_start - last_position); 32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng memset (last_position, __libelf_fill_byte, written); 32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (last_position + written != scn_start + offset 32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng && shdr_end < scn_start + offset) 32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *fill_start = MAX (shdr_end, scn_start); 33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng memset (fill_start, __libelf_fill_byte, 33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng scn_start + offset - fill_start); 33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (scn->data_list_rear != NULL) 33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng do 33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (dl->data.d.d_off >= 0); 33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert ((GElf_Off) dl->data.d.d_off <= shdr->sh_size); 34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (dl->data.d.d_size <= (shdr->sh_size 34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng - (GElf_Off) dl->data.d.d_off)); 34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If there is a gap, fill it. */ 34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (scn_start + dl->data.d.d_off > last_position 34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (dl->data.d.d_off == 0 34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng || ((scn->flags | dl->flags | elf->flags) 34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng & ELF_F_DIRTY) != 0)) 34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng fill_mmap (dl->data.d.d_off); 35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng last_position = scn_start + dl->data.d.d_off; 35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((scn->flags | dl->flags | elf->flags) & ELF_F_DIRTY) 35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Let it go backward if the sections use a bogus 35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng layout with overlaps. We'll overwrite the stupid 35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng user's section data with the latest one, rather than 35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng crashing. */ 35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng last_position = scn_start + dl->data.d.d_off; 36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (change_bo)) 36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if EV_NUM != 2 36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng xfct_t fctp; 36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng fctp = __elf_xfctstom[__libelf_version - 1][dl->data.d.d_version - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type]; 36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng# undef fctp 36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type] 37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Do the real work. */ 37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng (*fctp) (last_position, dl->data.d.d_buf, 37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng dl->data.d.d_size, 1); 37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng last_position += dl->data.d.d_size; 37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng last_position = mempcpy (last_position, 38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng dl->data.d.d_buf, 38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng dl->data.d.d_size); 38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng scn_changed = true; 38425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 38525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 38625b3c049e70834cf33790a28643ab058b507b35cBen Cheng last_position += dl->data.d.d_size; 38725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 38825b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (scn_start + dl->data.d.d_off + dl->data.d.d_size 38925b3c049e70834cf33790a28643ab058b507b35cBen Cheng == last_position); 39025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 39125b3c049e70834cf33790a28643ab058b507b35cBen Cheng dl->flags &= ~ELF_F_DIRTY; 39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 39325b3c049e70834cf33790a28643ab058b507b35cBen Cheng dl = dl->next; 39425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 39525b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (dl != NULL); 39625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 39725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If the previous section (or the ELF/program 39925b3c049e70834cf33790a28643ab058b507b35cBen Cheng header) changed we might have to fill the gap. */ 40025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (scn_start > last_position && previous_scn_changed) 40125b3c049e70834cf33790a28643ab058b507b35cBen Cheng fill_mmap (0); 40225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 40325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We have to trust the existing section header information. */ 40425b3c049e70834cf33790a28643ab058b507b35cBen Cheng last_position = scn_start + shdr->sh_size; 40525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 40625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 40725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 40825b3c049e70834cf33790a28643ab058b507b35cBen Cheng previous_scn_changed = scn_changed; 40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng next: 41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng scn->flags &= ~ELF_F_DIRTY; 41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 41325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Fill the gap between last section and section header table if 41425b3c049e70834cf33790a28643ab058b507b35cBen Cheng necessary. */ 41525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((elf->flags & ELF_F_DIRTY) 41625b3c049e70834cf33790a28643ab058b507b35cBen Cheng && last_position < ((char *) elf->map_address + elf->start_offset 41725b3c049e70834cf33790a28643ab058b507b35cBen Cheng + ehdr->e_shoff)) 41825b3c049e70834cf33790a28643ab058b507b35cBen Cheng memset (last_position, __libelf_fill_byte, 41925b3c049e70834cf33790a28643ab058b507b35cBen Cheng (char *) elf->map_address + elf->start_offset + ehdr->e_shoff 42025b3c049e70834cf33790a28643ab058b507b35cBen Cheng - last_position); 42125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 42225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Write the section header table entry if necessary. */ 42325b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t cnt = 0; cnt < shnum; ++cnt) 42425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 42525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *scn = scns[cnt]; 42625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 42725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((scn->shdr_flags | elf->flags) & ELF_F_DIRTY) 42825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 42925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (change_bo)) 43025b3c049e70834cf33790a28643ab058b507b35cBen Cheng (*shdr_fctp) (&shdr_dest[scn->index], 43125b3c049e70834cf33790a28643ab058b507b35cBen Cheng scn->shdr.ELFW(e,LIBELFBITS), 43225b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof (ElfW2(LIBELFBITS,Shdr)), 1); 43325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 43425b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (&shdr_dest[scn->index], 43525b3c049e70834cf33790a28643ab058b507b35cBen Cheng scn->shdr.ELFW(e,LIBELFBITS), 43625b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof (ElfW2(LIBELFBITS,Shdr))); 43725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 43825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If we previously made a copy of the section header 43925b3c049e70834cf33790a28643ab058b507b35cBen Cheng entry we now have to adjust the pointer again so 44025b3c049e70834cf33790a28643ab058b507b35cBen Cheng point to new place in the mapping. */ 44125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!elf->state.ELFW(elf,LIBELFBITS).shdr_malloced 44225b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (scn->shdr_flags & ELF_F_MALLOCED) == 0) 44325b3c049e70834cf33790a28643ab058b507b35cBen Cheng scn->shdr.ELFW(e,LIBELFBITS) = &shdr_dest[scn->index]; 44425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 44525b3c049e70834cf33790a28643ab058b507b35cBen Cheng scn->shdr_flags &= ~ELF_F_DIRTY; 44625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 44725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 44825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 44925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 45025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* That was the last part. Clear the overall flag. */ 45125b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->flags &= ~ELF_F_DIRTY; 45225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 45325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Make sure the content hits the disk. */ 45425b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *msync_start = ((char *) elf->map_address 45525b3c049e70834cf33790a28643ab058b507b35cBen Cheng + (elf->start_offset & ~(sysconf (_SC_PAGESIZE) - 1))); 45625b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *msync_end = ((char *) elf->map_address 45725b3c049e70834cf33790a28643ab058b507b35cBen Cheng + elf->start_offset + ehdr->e_shoff 45825b3c049e70834cf33790a28643ab058b507b35cBen Cheng + ehdr->e_shentsize * shnum); 45925b3c049e70834cf33790a28643ab058b507b35cBen Cheng (void) msync (msync_start, msync_end - msync_start, MS_SYNC); 46025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 46125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 46225b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 46325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 46425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 46525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Size of the buffer we use to generate the blocks of fill bytes. */ 46625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define FILLBUFSIZE 4096 46725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 46825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* If we have to convert the section buffer contents we have to use 46925b3c049e70834cf33790a28643ab058b507b35cBen Cheng temporary buffer. Only buffers up to MAX_TMPBUF bytes are allocated 47025b3c049e70834cf33790a28643ab058b507b35cBen Cheng on the stack. */ 47125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MAX_TMPBUF 32768 47225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 47325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 47425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Helper function to write out fill bytes. */ 47525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 47625b3c049e70834cf33790a28643ab058b507b35cBen Chengfill (int fd, off_t pos, size_t len, char *fillbuf, size_t *filledp) 47725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 47825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t filled = *filledp; 47925b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t fill_len = MIN (len, FILLBUFSIZE); 48025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 48125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (fill_len > filled) && filled < FILLBUFSIZE) 48225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 48325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Initialize a few more bytes. */ 48425b3c049e70834cf33790a28643ab058b507b35cBen Cheng memset (fillbuf + filled, __libelf_fill_byte, fill_len - filled); 48525b3c049e70834cf33790a28643ab058b507b35cBen Cheng *filledp = filled = fill_len; 48625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 48725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 48825b3c049e70834cf33790a28643ab058b507b35cBen Cheng do 48925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 49025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This many bytes we want to write in this round. */ 49125b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t n = MIN (filled, len); 49225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 49325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely ((size_t) pwrite_retry (fd, fillbuf, n, pos) != n)) 49425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 49525b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_WRITE_ERROR); 49625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 49725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 49825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 49925b3c049e70834cf33790a28643ab058b507b35cBen Cheng pos += n; 50025b3c049e70834cf33790a28643ab058b507b35cBen Cheng len -= n; 50125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 50225b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (len > 0); 50325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 50425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 50525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 50625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 50725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 50825b3c049e70834cf33790a28643ab058b507b35cBen Chengint 50925b3c049e70834cf33790a28643ab058b507b35cBen Chenginternal_function 51025b3c049e70834cf33790a28643ab058b507b35cBen Cheng__elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum) 51125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 51225b3c049e70834cf33790a28643ab058b507b35cBen Cheng char fillbuf[FILLBUFSIZE]; 51325b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t filled = 0; 51425b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool previous_scn_changed = false; 51525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 51625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We need the ELF header several times. */ 51725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr; 51825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 51925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Write out the ELF header. */ 52025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((elf->state.ELFW(elf,LIBELFBITS).ehdr_flags | elf->flags) & ELF_F_DIRTY) 52125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 52225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ElfW2(LIBELFBITS,Ehdr) tmp_ehdr; 52325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ElfW2(LIBELFBITS,Ehdr) *out_ehdr = ehdr; 52425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 52525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If the type sizes should be different at some time we have to 52625b3c049e70834cf33790a28643ab058b507b35cBen Cheng rewrite this code. */ 52725b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (sizeof (ElfW2(LIBELFBITS,Ehdr)) 52825b3c049e70834cf33790a28643ab058b507b35cBen Cheng == elf_typesize (LIBELFBITS, ELF_T_EHDR, 1)); 52925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 53025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (change_bo)) 53125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 53225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Today there is only one version of the ELF header. */ 53325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if EV_NUM != 2 53425b3c049e70834cf33790a28643ab058b507b35cBen Cheng xfct_t fctp; 53525b3c049e70834cf33790a28643ab058b507b35cBen Cheng fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR]; 53625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 53725b3c049e70834cf33790a28643ab058b507b35cBen Cheng# undef fctp 53825b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR] 53925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 54025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 54125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Write the converted ELF header in a temporary buffer. */ 54225b3c049e70834cf33790a28643ab058b507b35cBen Cheng (*fctp) (&tmp_ehdr, ehdr, sizeof (ElfW2(LIBELFBITS,Ehdr)), 1); 54325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 54425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This is the buffer we want to write. */ 54525b3c049e70834cf33790a28643ab058b507b35cBen Cheng out_ehdr = &tmp_ehdr; 54625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 54725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 54825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Write out the ELF header. */ 54925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (pwrite_retry (elf->fildes, out_ehdr, 55025b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof (ElfW2(LIBELFBITS,Ehdr)), 0) 55125b3c049e70834cf33790a28643ab058b507b35cBen Cheng != sizeof (ElfW2(LIBELFBITS,Ehdr)))) 55225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 55325b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_WRITE_ERROR); 55425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 55525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 55625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 55725b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ELFW(elf,LIBELFBITS).ehdr_flags &= ~ELF_F_DIRTY; 55825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 55925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We start writing sections after the ELF header only if there is 56025b3c049e70834cf33790a28643ab058b507b35cBen Cheng no program header. */ 56125b3c049e70834cf33790a28643ab058b507b35cBen Cheng previous_scn_changed = elf->state.ELFW(elf,LIBELFBITS).phdr == NULL; 56225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 56325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 56425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If the type sizes should be different at some time we have to 56525b3c049e70834cf33790a28643ab058b507b35cBen Cheng rewrite this code. */ 56625b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (sizeof (ElfW2(LIBELFBITS,Phdr)) 56725b3c049e70834cf33790a28643ab058b507b35cBen Cheng == elf_typesize (LIBELFBITS, ELF_T_PHDR, 1)); 56825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 56925b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t phnum; 57025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (__elf_getphdrnum_rdlock (elf, &phnum) != 0)) 57125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 57225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 57325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Write out the program header table. */ 57425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL 57525b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ((elf->state.ELFW(elf,LIBELFBITS).phdr_flags | elf->flags) 57625b3c049e70834cf33790a28643ab058b507b35cBen Cheng & ELF_F_DIRTY)) 57725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 57825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ElfW2(LIBELFBITS,Phdr) *tmp_phdr = NULL; 57925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ElfW2(LIBELFBITS,Phdr) *out_phdr = elf->state.ELFW(elf,LIBELFBITS).phdr; 58025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 58125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Maybe the user wants a gap between the ELF header and the program 58225b3c049e70834cf33790a28643ab058b507b35cBen Cheng header. */ 58325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr->e_phoff > ehdr->e_ehsize 58425b3c049e70834cf33790a28643ab058b507b35cBen Cheng && unlikely (fill (elf->fildes, ehdr->e_ehsize, 58525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr->e_phoff - ehdr->e_ehsize, fillbuf, &filled) 58625b3c049e70834cf33790a28643ab058b507b35cBen Cheng != 0)) 58725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 58825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 58925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (change_bo)) 59025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 59125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Today there is only one version of the ELF header. */ 59225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if EV_NUM != 2 59325b3c049e70834cf33790a28643ab058b507b35cBen Cheng xfct_t fctp; 59425b3c049e70834cf33790a28643ab058b507b35cBen Cheng fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR]; 59525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 59625b3c049e70834cf33790a28643ab058b507b35cBen Cheng# undef fctp 59725b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR] 59825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 59925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 60025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Allocate sufficient memory. */ 60125b3c049e70834cf33790a28643ab058b507b35cBen Cheng tmp_phdr = (ElfW2(LIBELFBITS,Phdr) *) 60225b3c049e70834cf33790a28643ab058b507b35cBen Cheng malloc (sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum); 60325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (tmp_phdr == NULL) 60425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 60525b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_NOMEM); 60625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 60725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 60825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 60925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Write the converted ELF header in a temporary buffer. */ 61025b3c049e70834cf33790a28643ab058b507b35cBen Cheng (*fctp) (tmp_phdr, elf->state.ELFW(elf,LIBELFBITS).phdr, 61125b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum, 1); 61225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 61325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This is the buffer we want to write. */ 61425b3c049e70834cf33790a28643ab058b507b35cBen Cheng out_phdr = tmp_phdr; 61525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 61625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 61725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Write out the ELF header. */ 61825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t phdr_size = sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum; 61925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely ((size_t) pwrite_retry (elf->fildes, out_phdr, 62025b3c049e70834cf33790a28643ab058b507b35cBen Cheng phdr_size, ehdr->e_phoff) 62125b3c049e70834cf33790a28643ab058b507b35cBen Cheng != phdr_size)) 62225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 62325b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_WRITE_ERROR); 62425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 62525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 62625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 62725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This is a no-op we we have not allocated any memory. */ 62825b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (tmp_phdr); 62925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 63025b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->state.ELFW(elf,LIBELFBITS).phdr_flags &= ~ELF_F_DIRTY; 63125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 63225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We modified the program header. Maybe this created a gap so 63325b3c049e70834cf33790a28643ab058b507b35cBen Cheng we have to write fill bytes, if necessary. */ 63425b3c049e70834cf33790a28643ab058b507b35cBen Cheng previous_scn_changed = true; 63525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 63625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 63725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* From now on we have to keep track of the last position to eventually 63825b3c049e70834cf33790a28643ab058b507b35cBen Cheng fill the gaps with the prescribed fill byte. */ 63925b3c049e70834cf33790a28643ab058b507b35cBen Cheng off_t last_offset; 64025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL) 64125b3c049e70834cf33790a28643ab058b507b35cBen Cheng last_offset = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1); 64225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 64325b3c049e70834cf33790a28643ab058b507b35cBen Cheng last_offset = (ehdr->e_phoff + sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum); 64425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 64525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Write all the sections. Well, only those which are modified. */ 64625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shnum > 0) 64725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 64825b3c049e70834cf33790a28643ab058b507b35cBen Cheng off_t shdr_offset = elf->start_offset + ehdr->e_shoff; 64925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if EV_NUM != 2 65025b3c049e70834cf33790a28643ab058b507b35cBen Cheng xfct_t shdr_fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR]; 65125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 65225b3c049e70834cf33790a28643ab058b507b35cBen Cheng# undef shdr_fctp 65325b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define shdr_fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR] 65425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 65525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 65625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ElfW2(LIBELFBITS,Shdr) *shdr_data; 65725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (change_bo || elf->state.ELFW(elf,LIBELFBITS).shdr == NULL) 65825b3c049e70834cf33790a28643ab058b507b35cBen Cheng shdr_data = (ElfW2(LIBELFBITS,Shdr) *) 65925b3c049e70834cf33790a28643ab058b507b35cBen Cheng alloca (shnum * sizeof (ElfW2(LIBELFBITS,Shdr))); 66025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 66125b3c049e70834cf33790a28643ab058b507b35cBen Cheng shdr_data = elf->state.ELFW(elf,LIBELFBITS).shdr; 66225b3c049e70834cf33790a28643ab058b507b35cBen Cheng int shdr_flags = elf->flags; 66325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 66425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Get all sections into the array and sort them. */ 66525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_ScnList *list = &elf->state.ELFW(elf,LIBELFBITS).scns; 66625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn **scns = (Elf_Scn **) alloca (shnum * sizeof (Elf_Scn *)); 66725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sort_sections (scns, list); 66825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 66925b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t cnt = 0; cnt < shnum; ++cnt) 67025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 67125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *scn = scns[cnt]; 67225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (scn->index == 0) 67325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 67425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The dummy section header entry. It should not be 67525b3c049e70834cf33790a28643ab058b507b35cBen Cheng possible to mark this "section" as dirty. */ 67625b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert ((scn->flags & ELF_F_DIRTY) == 0); 67725b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto next; 67825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 67925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 68025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS); 68125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr->sh_type == SHT_NOBITS) 68225b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto next; 68325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 68425b3c049e70834cf33790a28643ab058b507b35cBen Cheng off_t scn_start = elf->start_offset + shdr->sh_offset; 68525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data_List *dl = &scn->data_list; 68625b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool scn_changed = false; 68725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 68825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (scn->data_list_rear != NULL) 68925b3c049e70834cf33790a28643ab058b507b35cBen Cheng do 69025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 69125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If there is a gap, fill it. */ 69225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (scn_start + dl->data.d.d_off > last_offset 69325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ((previous_scn_changed && dl->data.d.d_off == 0) 69425b3c049e70834cf33790a28643ab058b507b35cBen Cheng || ((scn->flags | dl->flags | elf->flags) 69525b3c049e70834cf33790a28643ab058b507b35cBen Cheng & ELF_F_DIRTY) != 0)) 69625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 69725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (fill (elf->fildes, last_offset, 69825b3c049e70834cf33790a28643ab058b507b35cBen Cheng (scn_start + dl->data.d.d_off) 69925b3c049e70834cf33790a28643ab058b507b35cBen Cheng - last_offset, fillbuf, 70025b3c049e70834cf33790a28643ab058b507b35cBen Cheng &filled) != 0)) 70125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 70225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 70325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 70425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((scn->flags | dl->flags | elf->flags) & ELF_F_DIRTY) 70525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 70625b3c049e70834cf33790a28643ab058b507b35cBen Cheng char tmpbuf[MAX_TMPBUF]; 70725b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *buf = dl->data.d.d_buf; 70825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 70925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Let it go backward if the sections use a bogus 71025b3c049e70834cf33790a28643ab058b507b35cBen Cheng layout with overlaps. We'll overwrite the stupid 71125b3c049e70834cf33790a28643ab058b507b35cBen Cheng user's section data with the latest one, rather than 71225b3c049e70834cf33790a28643ab058b507b35cBen Cheng crashing. */ 71325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 71425b3c049e70834cf33790a28643ab058b507b35cBen Cheng last_offset = scn_start + dl->data.d.d_off; 71525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 71625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (change_bo)) 71725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 71825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if EV_NUM != 2 71925b3c049e70834cf33790a28643ab058b507b35cBen Cheng xfct_t fctp; 72025b3c049e70834cf33790a28643ab058b507b35cBen Cheng fctp = __elf_xfctstom[__libelf_version - 1][dl->data.d.d_version - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type]; 72125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 72225b3c049e70834cf33790a28643ab058b507b35cBen Cheng# undef fctp 72325b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type] 72425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 72525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 72625b3c049e70834cf33790a28643ab058b507b35cBen Cheng buf = tmpbuf; 72725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dl->data.d.d_size > MAX_TMPBUF) 72825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 72925b3c049e70834cf33790a28643ab058b507b35cBen Cheng buf = malloc (dl->data.d.d_size); 73025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (buf == NULL) 73125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 73225b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_NOMEM); 73325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 73425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 73525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 73625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 73725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Do the real work. */ 73825b3c049e70834cf33790a28643ab058b507b35cBen Cheng (*fctp) (buf, dl->data.d.d_buf, dl->data.d.d_size, 1); 73925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 74025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 74125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ssize_t n = pwrite_retry (elf->fildes, buf, 74225b3c049e70834cf33790a28643ab058b507b35cBen Cheng dl->data.d.d_size, 74325b3c049e70834cf33790a28643ab058b507b35cBen Cheng last_offset); 74425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely ((size_t) n != dl->data.d.d_size)) 74525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 74625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (buf != dl->data.d.d_buf && buf != tmpbuf) 74725b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (buf); 74825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 74925b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_WRITE_ERROR); 75025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 75125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 75225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 75325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (buf != dl->data.d.d_buf && buf != tmpbuf) 75425b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (buf); 75525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 75625b3c049e70834cf33790a28643ab058b507b35cBen Cheng scn_changed = true; 75725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 75825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 75925b3c049e70834cf33790a28643ab058b507b35cBen Cheng last_offset += dl->data.d.d_size; 76025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 76125b3c049e70834cf33790a28643ab058b507b35cBen Cheng dl->flags &= ~ELF_F_DIRTY; 76225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 76325b3c049e70834cf33790a28643ab058b507b35cBen Cheng dl = dl->next; 76425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 76525b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (dl != NULL); 76625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 76725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 76825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If the previous section (or the ELF/program 76925b3c049e70834cf33790a28643ab058b507b35cBen Cheng header) changed we might have to fill the gap. */ 77025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (scn_start > last_offset && previous_scn_changed) 77125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 77225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (fill (elf->fildes, last_offset, 77325b3c049e70834cf33790a28643ab058b507b35cBen Cheng scn_start - last_offset, fillbuf, 77425b3c049e70834cf33790a28643ab058b507b35cBen Cheng &filled) != 0)) 77525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 77625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 77725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 77825b3c049e70834cf33790a28643ab058b507b35cBen Cheng last_offset = scn_start + shdr->sh_size; 77925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 78025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 78125b3c049e70834cf33790a28643ab058b507b35cBen Cheng previous_scn_changed = scn_changed; 78225b3c049e70834cf33790a28643ab058b507b35cBen Cheng next: 78325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Collect the section header table information. */ 78425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (change_bo)) 78525b3c049e70834cf33790a28643ab058b507b35cBen Cheng (*shdr_fctp) (&shdr_data[scn->index], 78625b3c049e70834cf33790a28643ab058b507b35cBen Cheng scn->shdr.ELFW(e,LIBELFBITS), 78725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof (ElfW2(LIBELFBITS,Shdr)), 1); 78825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL) 78925b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (&shdr_data[scn->index], scn->shdr.ELFW(e,LIBELFBITS), 79025b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof (ElfW2(LIBELFBITS,Shdr))); 79125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 79225b3c049e70834cf33790a28643ab058b507b35cBen Cheng shdr_flags |= scn->shdr_flags; 79325b3c049e70834cf33790a28643ab058b507b35cBen Cheng scn->shdr_flags &= ~ELF_F_DIRTY; 79425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 79525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 79625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Fill the gap between last section and section header table if 79725b3c049e70834cf33790a28643ab058b507b35cBen Cheng necessary. */ 79825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((elf->flags & ELF_F_DIRTY) && last_offset < shdr_offset 79925b3c049e70834cf33790a28643ab058b507b35cBen Cheng && unlikely (fill (elf->fildes, last_offset, 80025b3c049e70834cf33790a28643ab058b507b35cBen Cheng shdr_offset - last_offset, 80125b3c049e70834cf33790a28643ab058b507b35cBen Cheng fillbuf, &filled) != 0)) 80225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 80325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 80425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Write out the section header table. */ 80525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr_flags & ELF_F_DIRTY 80625b3c049e70834cf33790a28643ab058b507b35cBen Cheng && unlikely ((size_t) pwrite_retry (elf->fildes, shdr_data, 80725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof (ElfW2(LIBELFBITS,Shdr)) 80825b3c049e70834cf33790a28643ab058b507b35cBen Cheng * shnum, shdr_offset) 80925b3c049e70834cf33790a28643ab058b507b35cBen Cheng != sizeof (ElfW2(LIBELFBITS,Shdr)) * shnum)) 81025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 81125b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libelf_seterrno (ELF_E_WRITE_ERROR); 81225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 81325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 81425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 81525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 81625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* That was the last part. Clear the overall flag. */ 81725b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->flags &= ~ELF_F_DIRTY; 81825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 81925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 82025b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 821