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