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