1df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard/* Merge string sections. 2df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard Copyright (C) 2015 Red Hat, Inc. 3df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard This file is part of elfutils. 4df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 5df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard This file is free software; you can redistribute it and/or modify 6df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard it under the terms of the GNU General Public License as published by 7df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard the Free Software Foundation; either version 3 of the License, or 8df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard (at your option) any later version. 9df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 10df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard elfutils is distributed in the hope that it will be useful, but 11df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard WITHOUT ANY WARRANTY; without even the implied warranty of 12df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GNU General Public License for more details. 14df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 15df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard You should have received a copy of the GNU General Public License 16df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 18df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard#include <config.h> 19df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 20df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard#include <assert.h> 21df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard#include <errno.h> 22df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard#include <stdlib.h> 23df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard#include <string.h> 24df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard#include <sys/types.h> 25df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard#include <sys/stat.h> 26df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard#include <fcntl.h> 27df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard#include <error.h> 28df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard#include <stdio.h> 29df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard#include <inttypes.h> 30df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard#include <unistd.h> 31df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 32df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard#include <gelf.h> 33df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard#include ELFUTILS_HEADER(ebl) 34df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 35df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard/* The original ELF file. */ 36df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardstatic int fd = -1; 37df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardstatic Elf *elf = NULL; 38df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardstatic bool replace; 39df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 40df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard/* The new ELF file. */ 41df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardstatic char *fnew = NULL; 42df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardstatic int fdnew = -1; 43df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardstatic Elf *elfnew = NULL; 44df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 45df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard/* The merged string table. */ 46df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardstatic struct Ebl_Strtab *strings = NULL; 47df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 48df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard/* Section name strents. */ 49df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardstatic struct Ebl_Strent **scnstrents = NULL; 50df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 51df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard/* Symbol name strends. */ 52df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardstatic struct Ebl_Strent **symstrents = NULL; 53df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 54df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard/* New ELF file buffers. */ 55df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardstatic Elf_Data newstrtabdata = { .d_buf = NULL }; 56df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardstatic size_t newshnums = 0; 57df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardstatic void **newscnbufs = NULL; 58df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 59df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard/* Release all files and resources allocated. */ 60df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardstatic void 61df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardrelease (void) 62df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard{ 63df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* The new string table. */ 64df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (strings != NULL) 65df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard ebl_strtabfree (strings); 66df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 67df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard free (scnstrents); 68df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard free (symstrents); 69df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard free (newstrtabdata.d_buf); 70df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 71df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Any new data buffers allocated. */ 72df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard for (size_t i = 0; i < newshnums; i++) 73df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard free (newscnbufs[i]); 74df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard free (newscnbufs); 75df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 76df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* The new ELF file. */ 77df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (fdnew != -1) 78df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 79df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard unlink (fnew); 80df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard elf_end (elfnew); 81df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard close (fdnew); 82df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 83df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard // Don't release, we might need it in the error message. 84df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard // if (replace) 85df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard // free (fnew); 86df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 87df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* The original ELF file. */ 88df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard elf_end (elf); 89df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard close (fd); 90df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard} 91df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 92df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard/* The various ways we can fail... Cleanup and show some message to 93df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard the user. The file name may be NULL. */ 94df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardstatic void __attribute__ ((noreturn)) 95df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardfail (const char *msg, const char *fname) 96df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard{ 97df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard release (); 98df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (fname != NULL) 99df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard error (1, 0, "%s: %s", fname, msg); 100df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard else 101df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard error (1, 0, "%s", msg); 102df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard abort(); 103df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard} 104df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 105df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardstatic void __attribute__ ((noreturn)) 106df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardfail_errno (const char *msg, const char *fname) 107df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard{ 108df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard release (); 109df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (fname != NULL) 110df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard error (1, errno, "%s: %s", fname, msg); 111df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard else 112df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard error (1, errno, "%s", msg); 113df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard abort(); 114df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard} 115df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 116df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardstatic void __attribute__ ((noreturn)) 117df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardfail_idx (const char *msg, const char *fname, size_t idx) 118df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard{ 119df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard release (); 120df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (fname != NULL) 121df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard error (1, 0, "%s: %s %zd", fname, msg, idx); 122df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard else 123df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard error (1, 0, "%s %zd", msg, idx); 124df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard abort(); 125df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard} 126df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 127df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardstatic void __attribute__ ((noreturn)) 128df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardfail_elf (const char *msg, const char *fname) 129df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard{ 130df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard release (); 131df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (fname != NULL) 132df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard error (1, 0, "%s: %s: %s", fname, msg, elf_errmsg (-1)); 133df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard else 134df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard error (1, 0, "%s: %s", msg, elf_errmsg (-1)); 135df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard abort(); 136df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard} 137df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 138df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardstatic void __attribute__ ((noreturn)) 139df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardfail_elf_idx (const char *msg, const char *fname, size_t idx) 140df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard{ 141df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard release (); 142df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (fname != NULL) 143df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard error (1, 0, "%s: %s %zd: %s", fname, msg, idx, elf_errmsg (-1)); 144df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard else 145df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard error (1, 0, "%s %zd: %s", msg, idx, elf_errmsg (-1)); 146df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard abort(); 147df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard} 148df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 149df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardint 150df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaardmain (int argc, char **argv) 151df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard{ 152df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard elf_version (EV_CURRENT); 153df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 154df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Basic command line handling. Need to replace the input file? */ 155df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if ((argc != 2 && argc != 4) 156df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard || (argc == 4 && strcmp (argv[1], "-o") != 0)) 157df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail ("Usage argument: [-o <outputfile>] <inputfile>", NULL); 158df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard replace = argc == 2; 159df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 160df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Get the ELF file. */ 161df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard const char *fname; 162df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (replace) 163df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fname = argv[1]; 164df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard else 165df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fname = argv[3]; 166df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fd = open (fname, O_RDONLY); 167df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (fd < 0) 168df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_errno ("couldn't open", fname); 169df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 170df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard elf = elf_begin (fd, ELF_C_READ, NULL); 171df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (elf == NULL) 172df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf ("couldn't open ELF file for reading", fname); 173df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 174df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Ehdr ehdr; 175df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (gelf_getehdr (elf, &ehdr) == NULL) 176df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf ("Couldn't get ehdr", fname); 177df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 178df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Get the section header string table. */ 179df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard size_t shdrstrndx; 180df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (elf_getshdrstrndx (elf, &shdrstrndx) != 0) 181df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf ("couldn't get section header string table index", fname); 182df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 183df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard Elf_Scn *shdrstrscn = elf_getscn (elf, shdrstrndx); 184df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Shdr shdrstrshdr_mem; 185df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Shdr *shdrstrshdr = gelf_getshdr (shdrstrscn, &shdrstrshdr_mem); 186df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (shdrstrshdr == NULL) 187df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf ("couldn't get section header string table section", fname); 188df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 189df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if ((shdrstrshdr->sh_flags & SHF_ALLOC) != 0) 190df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail ("section header string table is an allocated section", fname); 191df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 192df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Get the symtab section. */ 193df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard size_t symtabndx = 0; 194df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard Elf_Scn *symtabscn = NULL; 195df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Shdr symtabshdr_mem; 196df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Shdr *symtabshdr; 197df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard while ((symtabscn = elf_nextscn (elf, symtabscn)) != NULL) 198df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 199df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard symtabshdr = gelf_getshdr (symtabscn, &symtabshdr_mem); 200df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (symtabshdr == NULL) 201df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf ("couldn't get shdr", fname); 202df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 203df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (symtabshdr->sh_type == SHT_SYMTAB) 204df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 205df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Just pick the first, we don't expect more than one. */ 206df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard symtabndx = elf_ndxscn (symtabscn); 207df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard break; 208df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 209df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 210df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 211df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (symtabndx == 0) 212df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail ("No symtab found", fname); 213df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 214df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if ((symtabshdr->sh_flags & SHF_ALLOC) != 0) 215df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail ("symtab is an allocated section", fname); 216df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 217df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Get the strtab of the symtab. */ 218df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard size_t strtabndx = symtabshdr->sh_link; 219df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard Elf_Scn *strtabscn = elf_getscn (elf, strtabndx); 220df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Shdr strtabshdr_mem; 221df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Shdr *strtabshdr = gelf_getshdr (strtabscn, &strtabshdr_mem); 222df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (strtabshdr == NULL) 223df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf ("Couldn't get strtab section", fname); 224df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 225df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (shdrstrndx == strtabndx) 226df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 227df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard error (0, 0, "%s: Nothing to do, shstrtab == strtab", fname); 228df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard release (); 229df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard return 0; 230df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 231df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 232df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if ((strtabshdr->sh_flags & SHF_ALLOC) != 0) 233df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail ("strtab is an allocated section", fname); 234df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 235df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard size_t phnum; 236df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (elf_getphdrnum (elf, &phnum) != 0) 237df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf ("Couldn't get number of phdrs", fname); 238df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 239df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* If there are phdrs we want to maintain the layout of the 240df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard allocated sections in the file. */ 241df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard bool layout = phnum != 0; 242df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 243df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Create a new merged strings table that starts with the empty string. */ 244df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard strings = ebl_strtabinit (true); 245df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (strings == NULL) 246df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail ("No memory to create merged string table", NULL); 247df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 248df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Add the strings from all the sections. */ 249df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard size_t shdrnum; 250df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (elf_getshdrnum (elf, &shdrnum) != 0) 251df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf ("Couldn't get number of sections", fname); 252df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard scnstrents = malloc (shdrnum * sizeof (struct Ebl_Strent *)); 253df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (scnstrents == NULL) 254df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail ("couldn't allocate memory for section strings", NULL); 255df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 256df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* While going through all sections keep track of last allocated 257df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard offset if needed to keep the layout. We'll put any unallocated 258df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard sections behind those (strtab is unallocated and will change 259df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard size). */ 260df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Off last_offset = 0; 261df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (layout) 262df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard last_offset = (ehdr.e_phoff 263df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard + gelf_fsize (elf, ELF_T_PHDR, phnum, EV_CURRENT)); 264df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard Elf_Scn *scn = NULL; 265df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard while ((scn = elf_nextscn (elf, scn)) != NULL) 266df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 267df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard size_t scnnum = elf_ndxscn (scn); 268df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Shdr shdr_mem; 269df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 270df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (shdr == NULL) 271df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf_idx ("couldn't get shdr", fname, scnnum); 272df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Don't add the .shstrtab section itself, we'll not use it. */ 273df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (shdr->sh_name != 0 && scnnum != shdrstrndx) 274df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 275df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard const char *sname = elf_strptr (elf, shdrstrndx, shdr->sh_name); 276df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (sname == NULL) 277df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf_idx ("couldn't get section name", fname, scnnum); 278df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if ((scnstrents[scnnum] = ebl_strtabadd (strings, sname, 0)) == NULL) 279df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail ("No memory to add to merged string table", NULL); 280df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 281df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 282df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (layout) 283df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if ((shdr->sh_flags & SHF_ALLOC) != 0) 284df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 285df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Off off = shdr->sh_offset + (shdr->sh_type != SHT_NOBITS 286df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard ? shdr->sh_size : 0); 287df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (last_offset < off) 288df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard last_offset = off; 289df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 290df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 291df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 292df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Add the strings from all the symbols. */ 293df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT); 294df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard Elf_Data *symd = elf_getdata (symtabscn, NULL); 295df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (symd == NULL) 296df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf ("couldn't get symtab data", fname); 297df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard size_t symsnum = symd->d_size / elsize; 298df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard symstrents = malloc (symsnum * sizeof (struct Ebl_Strent *)); 299df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (symstrents == NULL) 300df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_errno ("Couldn't allocate memory for symbol strings", NULL); 301df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard for (size_t i = 0; i < symsnum; i++) 302df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 303df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Sym sym_mem; 304df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Sym *sym = gelf_getsym (symd, i, &sym_mem); 305df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (sym == NULL) 306df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf_idx ("Couldn't get symbol", fname, i); 307df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (sym->st_name != 0) 308df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 309df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard const char *sname = elf_strptr (elf, strtabndx, sym->st_name); 310df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (sname == NULL) 311df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf_idx ("Couldn't get symbol name", fname, i); 312df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if ((symstrents[i] = ebl_strtabadd (strings, sname, 0)) == NULL) 313df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_idx ("No memory to add to merged string table symbol", 314df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fname, i); 315df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 316df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 317df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 318df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* We got all strings, build the new string table and store it as 319df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard new strtab. */ 320df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard ebl_strtabfinalize (strings, &newstrtabdata); 321df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 322df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* We share at least the empty string so the result is at least 1 323df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard byte smaller. */ 324df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (newstrtabdata.d_size >= shdrstrshdr->sh_size + strtabshdr->sh_size) 325df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail ("Impossible, merged string table is larger", fname); 326df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 327df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* section index mapping and sanity checking. */ 328df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard size_t newsecndx (size_t secndx, const char *what, size_t widx, 329df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard const char *member, size_t midx) 330df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 331df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (unlikely (secndx == 0 || secndx == shdrstrndx || secndx >= shdrnum)) 332df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 333df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Don't use fail... too specialized messages. Call release 334df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard outselves and then error. Ignores midx if widx is 335df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard zero. */ 336df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard release (); 337df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (widx == 0) 338df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard error (1, 0, "%s: bad section index %zd in %s for %s", 339df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fname, secndx, what, member); 340df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard else if (midx == 0) 341df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard error (1, 0, "%s: bad section index %zd in %s %zd for %s", 342df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fname, secndx, what, widx, member); 343df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard else 344df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard error (1, 0, "%s: bad section index %zd in %s %zd for %s %zd", 345df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fname, secndx, what, widx, member, midx); 346df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 347df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 348df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard return secndx < shdrstrndx ? secndx : secndx - 1; 349df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 350df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 351df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard struct stat st; 352df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (fstat (fd, &st) != 0) 353df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_errno("Couldn't fstat", fname); 354df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 355df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Create a new (temporary) ELF file for the result. */ 356df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (replace) 357df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 358df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard size_t fname_len = strlen (fname); 359df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fnew = malloc (fname_len + sizeof (".XXXXXX")); 360df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (fnew == NULL) 361df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_errno ("couldn't allocate memory for new file name", NULL); 362df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard strcpy (mempcpy (fnew, fname, fname_len), ".XXXXXX"); 363df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 364df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fdnew = mkstemp (fnew); 365df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 366df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard else 367df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 368df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fnew = argv[2]; 369df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fdnew = open (fnew, O_WRONLY | O_CREAT, st.st_mode & ALLPERMS); 370df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 371df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 372df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (fdnew < 0) 373df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_errno ("couldn't create output file", fnew); 374df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 375df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard elfnew = elf_begin (fdnew, ELF_C_WRITE, NULL); 376df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (elfnew == NULL) 377df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf ("couldn't open new ELF for writing", fnew); 378df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 379df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Create the new ELF header and copy over all the data. */ 380df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (gelf_newehdr (elfnew, gelf_getclass (elf)) == 0) 381df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf ("Couldn't create new ehdr", fnew); 382df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Ehdr newehdr; 383df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (gelf_getehdr (elfnew, &newehdr) == NULL) 384df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf ("Couldn't get ehdr", fnew); 385df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 386df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newehdr.e_ident[EI_DATA] = ehdr.e_ident[EI_DATA]; 387df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newehdr.e_type = ehdr.e_type; 388df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newehdr.e_machine = ehdr.e_machine; 389df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newehdr.e_version = ehdr.e_version; 390df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newehdr.e_entry = ehdr.e_entry; 391df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newehdr.e_flags = ehdr.e_flags; 392df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 393df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* The new file uses the new strtab as shstrtab. */ 394df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard size_t newstrtabndx = newsecndx (strtabndx, "ehdr", 0, "e_shstrndx", 0); 395df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (newstrtabndx < SHN_LORESERVE) 396df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newehdr.e_shstrndx = newstrtabndx; 397df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard else 398df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 399df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard Elf_Scn *zscn = elf_getscn (elfnew, 0); 400df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Shdr zshdr_mem; 401df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Shdr *zshdr = gelf_getshdr (zscn, &zshdr_mem); 402df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (zshdr == NULL) 403df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf ("Couldn't get section zero", fnew); 404df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard zshdr->sh_link = strtabndx; 405df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (gelf_update_shdr (zscn, zshdr) == 0) 406df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf ("Couldn't update section zero", fnew); 407df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newehdr.e_shstrndx = SHN_XINDEX; 408df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 409df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 410df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (gelf_update_ehdr (elfnew, &newehdr) == 0) 411df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail ("Couldn't update ehdr", fnew); 412df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 413df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Copy the program headers if any. */ 414df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (phnum != 0) 415df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 416df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (gelf_newphdr (elfnew, phnum) == 0) 417df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf ("Couldn't create phdrs", fnew); 418df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 419df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard for (size_t cnt = 0; cnt < phnum; ++cnt) 420df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 421df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Phdr phdr_mem; 422df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem); 423df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (phdr == NULL) 424df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf_idx ("Couldn't get phdr", fname, cnt); 425df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (gelf_update_phdr (elfnew, cnt, phdr) == 0) 426df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf_idx ("Couldn't create phdr", fnew, cnt); 427df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 428df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 429df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 430df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newshnums = shdrnum - 1; 431df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newscnbufs = calloc (sizeof (void *), newshnums); 432df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (newscnbufs == NULL) 433df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_errno ("Couldn't allocate memory for new section buffers", NULL); 434df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 435df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Copy the sections, except the shstrtab, fill the strtab with the 436df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard combined strings and adjust section references. */ 437df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard while ((scn = elf_nextscn (elf, scn)) != NULL) 438df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 439df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard size_t ndx = elf_ndxscn (scn); 440df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 441df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Shdr shdr_mem; 442df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 443df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (shdr == NULL) 444df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf_idx ("Couldn't get shdr", fname, ndx); 445df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 446df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Section zero is always created. Skip the shtrtab. */ 447df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (ndx == 0 || ndx == shdrstrndx) 448df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard continue; 449df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 450df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard Elf_Scn *newscn = elf_newscn (elfnew); 451df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (newscn == NULL) 452df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf_idx ("couldn't create new section", fnew, ndx); 453df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 454df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Shdr newshdr; 455df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newshdr.sh_name = (shdr->sh_name != 0 456df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard ? ebl_strtaboffset (scnstrents[ndx]) : 0); 457df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newshdr.sh_type = shdr->sh_type; 458df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newshdr.sh_flags = shdr->sh_flags; 459df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newshdr.sh_addr = shdr->sh_addr; 460df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newshdr.sh_size = shdr->sh_size; 461df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (shdr->sh_link != 0) 462df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newshdr.sh_link = newsecndx (shdr->sh_link, "shdr", ndx, "sh_link", 0); 463df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard else 464df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newshdr.sh_link = 0; 465df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (SH_INFO_LINK_P (shdr) && shdr->sh_info != 0) 466df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newshdr.sh_info = newsecndx (shdr->sh_info, "shdr", ndx, "sh_info", 0); 467df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard else 468df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newshdr.sh_info = shdr->sh_info; 469df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newshdr.sh_entsize = shdr->sh_entsize; 470df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 471df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Some sections need a new data buffer because they need to 472df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard manipulate the original data. Allocate and check here, so we 473df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard have a list of all data buffers we might need to release when 474df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard done. */ 475df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard void new_data_buf (Elf_Data *d) 476df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 477df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard size_t s = d->d_size; 478df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (s == 0) 479df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_idx ("Expected data in section", fname, ndx); 480df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard void *b = malloc (d->d_size); 481df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (b == NULL) 482df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_idx ("Couldn't allocated buffer for section", NULL, ndx); 483df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newscnbufs[newsecndx (ndx, "section", ndx, "d_buf", 0)] = d->d_buf = b; 484df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 485df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 486df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard Elf_Data *newdata = elf_newdata (newscn); 487df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (newdata == NULL) 488df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf_idx ("Couldn't create new data for section", fnew, ndx); 489df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (ndx == strtabndx) 490df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard *newdata = newstrtabdata; 491df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard else 492df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 493df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* The symtab, dynsym, group and symtab_shndx sections 494df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard contain section indexes. Symbol tables (symtab and 495df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard dynsym) contain indexes to strings. Update both if 496df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard necessary. */ 497df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard Elf_Data *data = elf_getdata (scn, NULL); 498df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (data == NULL) 499df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf_idx ("Couldn't get data from section", fname, ndx); 500df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard *newdata = *data; 501df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard switch (shdr->sh_type) 502df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 503df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard case SHT_SYMTAB: 504df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard case SHT_DYNSYM: 505df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 506df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* We need to update the section numbers of the 507df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard symbols and if this symbol table uses the strtab 508df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard section also the name indexes. */ 509df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard const bool update_name = shdr->sh_link == strtabndx; 510df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (update_name && ndx != symtabndx) 511df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail ("Only one symbol table using strtab expected", fname); 512df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard new_data_buf (newdata); 513df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard size_t syms = (data->d_size 514df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard / gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT)); 515df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard for (size_t i = 0; i < syms; i++) 516df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 517df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard GElf_Sym sym; 518df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (gelf_getsym (data, i, &sym) == NULL) 519df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf_idx ("Couldn't get symbol", fname, i); 520df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 52129ee512fb8a71b0d22065c369a2117ff758bdf5eMark Wielaard if (GELF_ST_TYPE (sym.st_info) == STT_SECTION 52229ee512fb8a71b0d22065c369a2117ff758bdf5eMark Wielaard && sym.st_shndx == shdrstrndx) 52329ee512fb8a71b0d22065c369a2117ff758bdf5eMark Wielaard fprintf (stderr, "WARNING:" 52429ee512fb8a71b0d22065c369a2117ff758bdf5eMark Wielaard " symbol table [%zd] contains section symbol %zd" 52529ee512fb8a71b0d22065c369a2117ff758bdf5eMark Wielaard " for old shdrstrndx %zd\n", ndx, i, shdrstrndx); 52629ee512fb8a71b0d22065c369a2117ff758bdf5eMark Wielaard else if (sym.st_shndx != SHN_UNDEF 52729ee512fb8a71b0d22065c369a2117ff758bdf5eMark Wielaard && sym.st_shndx < SHN_LORESERVE) 528df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard sym.st_shndx = newsecndx (sym.st_shndx, "section", ndx, 529df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard "symbol", i); 530df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (update_name && sym.st_name != 0) 531df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard sym.st_name = ebl_strtaboffset (symstrents[i]); 532df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 533df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* We explicitly don't update the SHNDX table at 534df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard the same time, we do that below. */ 535df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (gelf_update_sym (newdata, i, &sym) == 0) 536df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf_idx ("Couldn't update symbol", fnew, i); 537df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 538df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 539df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard break; 540df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 541df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard case SHT_GROUP: 542df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 543df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard new_data_buf (newdata); 544df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* A section group contains Elf32_Words. The first 545df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard word is a falg value, the rest of the words are 546df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard indexes of the sections belonging to the group. */ 547df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard Elf32_Word *group = (Elf32_Word *) data->d_buf; 548df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard Elf32_Word *newgroup = (Elf32_Word *) newdata->d_buf; 549df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard size_t words = data->d_size / sizeof (Elf32_Word); 550df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (words == 0) 551df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_idx ("Not enough data in group section", fname, ndx); 552df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newgroup[0] = group[0]; 553df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard for (size_t i = 1; i < words; i++) 554df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newgroup[i] = newsecndx (group[i], "section", ndx, 555df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard "group", i); 556df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 557df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard break; 558df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 559df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard case SHT_SYMTAB_SHNDX: 560df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 561df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard new_data_buf (newdata); 562df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* A SHNDX just contains an array of section indexes 563df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard for the corresponding symbol table. The entry is 564df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard SHN_UNDEF unless the corresponding symbol is 565df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard SHN_XINDEX. */ 566df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard Elf32_Word *shndx = (Elf32_Word *) data->d_buf; 567df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard Elf32_Word *newshndx = (Elf32_Word *) newdata->d_buf; 568df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard size_t words = data->d_size / sizeof (Elf32_Word); 569df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard for (size_t i = 0; i < words; i++) 570df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (shndx[i] == SHN_UNDEF) 571df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newshndx[i] = SHN_UNDEF; 572df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard else 573df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newshndx[i] = newsecndx (shndx[i], "section", ndx, 574df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard "shndx", i); 575df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 576df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard break; 577df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 578df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard case SHT_DYNAMIC: 579df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Fallthrough. There are string indexes in here, but 580df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard they (should) point to a allocated string table, 581df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard which we don't alter. */ 582df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard default: 583df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Nothing to do. Section data doesn't contain section 584df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard or strtab indexes. */ 585df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard break; 586df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 587df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 588df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 589df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* When we are responsible for the layout explicitly set 590df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard sh_addralign, sh_size and sh_offset. Otherwise libelf will 591df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard calculate those from the Elf_Data. */ 592df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (layout) 593df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 594df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* We have just one Elf_Data. */ 595df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newshdr.sh_size = newdata->d_size; 596df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newshdr.sh_addralign = newdata->d_align; 597df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 598df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Keep the offset of allocated sections so they are at the 599df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard same place in the file. Add unallocated ones after the 600df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard allocated ones. */ 601df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if ((shdr->sh_flags & SHF_ALLOC) != 0) 602df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newshdr.sh_offset = shdr->sh_offset; 603df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard else 604df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 605df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Zero means one. No alignment constraints. */ 606df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard size_t addralign = newshdr.sh_addralign ?: 1; 607df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard last_offset = (last_offset + addralign - 1) & ~(addralign - 1); 608df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newshdr.sh_offset = last_offset; 609df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (newshdr.sh_type != SHT_NOBITS) 610df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard last_offset += newshdr.sh_size; 611df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 612df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 613df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard else 614df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 615df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newshdr.sh_addralign = 0; 616df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newshdr.sh_size = 0; 617df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newshdr.sh_offset = 0; 618df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 619df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 620df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (gelf_update_shdr (newscn, &newshdr) == 0) 621df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf_idx ("Couldn't update section header", fnew, ndx); 622df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 623df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 624df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* If we have phdrs we want elf_update to layout the SHF_ALLOC 625df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard sections precisely as in the original file. In that case we are 626df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard also responsible for setting phoff and shoff */ 627df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (layout) 628df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard { 629df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Position the shdrs after the last (unallocated) section. */ 630df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (gelf_getehdr (elfnew, &newehdr) == NULL) 631df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf ("Couldn't get ehdr", fnew); 632df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT); 633df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newehdr.e_shoff = ((last_offset + offsize - 1) 634df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard & ~((GElf_Off) (offsize - 1))); 635df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 636df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* The phdrs go in the same place as in the original file. 637df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard Normally right after the ELF header. */ 638df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard newehdr.e_phoff = ehdr.e_phoff; 639df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 640df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (gelf_update_ehdr (elfnew, &newehdr) == 0) 641df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf ("Couldn't update ehdr", fnew); 642df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 643df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard elf_flagelf (elfnew, ELF_C_SET, ELF_F_LAYOUT); 644df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard } 645df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 646df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (elf_update (elfnew, ELF_C_WRITE) == -1) 647df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_elf ("Couldn't write ELF", fnew); 648df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 649df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard elf_end (elfnew); 650df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard elfnew = NULL; 651df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 652df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Try to match mode and owner.group of the original file. */ 653df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (fchmod (fdnew, st.st_mode & ALLPERMS) != 0) 654df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard error (0, errno, "Couldn't fchmod %s", fnew); 655df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (fchown (fdnew, st.st_uid, st.st_gid) != 0) 656df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard error (0, errno, "Couldn't fchown %s", fnew); 657df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 658df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* Finally replace the old file with the new merged strings file. */ 659df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (replace) 660df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (rename (fnew, fname) != 0) 661df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fail_errno ("rename", fnew); 662df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 663df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard /* We are finally done with the new file, don't unlink it now. */ 664df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard close (fdnew); 665df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard if (replace) 666df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard free (fnew); 667df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fnew = NULL; 668df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard fdnew = -1; 669df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard 670df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard release (); 671df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard return 0; 672df7dfab451246e8b088040e052ca01f9d6aba774Mark Wielaard} 673