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