1 /* Write changed data structures.
2 Copyright (C) 2000, 2001, 2002, 2004 Red Hat, Inc.
3 Written by Ulrich Drepper <drepper@redhat.com>, 2000.
4
5 This program 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, version 2.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <assert.h>
23 #include <libelf.h>
24 #include <stdbool.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <sys/param.h>
29
30 #include "libelfP.h"
31
32
33 #ifndef LIBELFBITS
34 # define LIBELFBITS 32
35 #endif
36
37
38 static int
compare_sections(const void * a,const void * b)39 compare_sections (const void *a, const void *b)
40 {
41 const Elf_Scn **scna = (const Elf_Scn **) a;
42 const Elf_Scn **scnb = (const Elf_Scn **) b;
43
44 if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_offset
45 < (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_offset)
46 return -1;
47
48 if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_offset
49 > (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_offset)
50 return 1;
51
52 if ((*scna)->index < (*scnb)->index)
53 return -1;
54
55 if ((*scna)->index > (*scnb)->index)
56 return 1;
57
58 return 0;
59 }
60
61
62 /* Insert the sections in the list into the provided array and sort
63 them according to their start offsets. For sections with equal
64 start offsets the section index is used. */
65 static void
sort_sections(Elf_Scn ** scns,Elf_ScnList * list)66 sort_sections (Elf_Scn **scns, Elf_ScnList *list)
67 {
68 Elf_Scn **scnp = scns;
69 do
70 {
71 size_t cnt;
72
73 for (cnt = 0; cnt < list->cnt; ++cnt)
74 *scnp++ = &list->data[cnt];
75 }
76 while ((list = list->next) != NULL);
77
78 qsort (scns, scnp - scns, sizeof (*scns), compare_sections);
79 }
80
81
82 int
83 internal_function_def
__elfw2(LIBELFBITS,updatemmap)84 __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
85 {
86 ElfW2(LIBELFBITS,Ehdr) *ehdr;
87 xfct_t fctp;
88 char *last_position;
89
90 /* We need the ELF header several times. */
91 ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
92
93 /* Write out the ELF header. */
94 if ((elf->state.ELFW(elf,LIBELFBITS).ehdr_flags | elf->flags) & ELF_F_DIRTY)
95 {
96 /* If the type sizes should be different at some time we have to
97 rewrite this code. */
98 assert (sizeof (ElfW2(LIBELFBITS,Ehdr))
99 == elf_typesize (LIBELFBITS, ELF_T_EHDR, 1));
100
101 if (unlikely (change_bo))
102 {
103 /* Today there is only one version of the ELF header. */
104 #if EV_NUM != 2
105 fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR];
106 #else
107 # undef fctp
108 # define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR]
109 #endif
110
111 /* Do the real work. */
112 (*fctp) ((char *) elf->map_address + elf->start_offset, ehdr,
113 sizeof (ElfW2(LIBELFBITS,Ehdr)), 1);
114 }
115 else
116 memcpy (elf->map_address + elf->start_offset, ehdr,
117 sizeof (ElfW2(LIBELFBITS,Ehdr)));
118
119 elf->state.ELFW(elf,LIBELFBITS).ehdr_flags &= ~ELF_F_DIRTY;
120 }
121
122 /* Write out the program header table. */
123 if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL
124 && ((elf->state.ELFW(elf,LIBELFBITS).phdr_flags | elf->flags)
125 & ELF_F_DIRTY))
126 {
127 /* If the type sizes should be different at some time we have to
128 rewrite this code. */
129 assert (sizeof (ElfW2(LIBELFBITS,Phdr))
130 == elf_typesize (LIBELFBITS, ELF_T_PHDR, 1));
131
132 /* Maybe the user wants a gap between the ELF header and the program
133 header. */
134 if (ehdr->e_phoff > ehdr->e_ehsize)
135 memset (elf->map_address + elf->start_offset + ehdr->e_ehsize,
136 __libelf_fill_byte, ehdr->e_phoff - ehdr->e_ehsize);
137
138 if (unlikely (change_bo))
139 {
140 /* Today there is only one version of the ELF header. */
141 #if EV_NUM != 2
142 fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR];
143 #else
144 # undef fctp
145 # define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR]
146 #endif
147
148 /* Do the real work. */
149 (*fctp) (elf->map_address + elf->start_offset + ehdr->e_phoff,
150 elf->state.ELFW(elf,LIBELFBITS).phdr,
151 sizeof (ElfW2(LIBELFBITS,Phdr)) * ehdr->e_phnum, 1);
152 }
153 else
154 memcpy (elf->map_address + elf->start_offset + ehdr->e_phoff,
155 elf->state.ELFW(elf,LIBELFBITS).phdr,
156 sizeof (ElfW2(LIBELFBITS,Phdr)) * ehdr->e_phnum);
157
158 elf->state.ELFW(elf,LIBELFBITS).phdr_flags &= ~ELF_F_DIRTY;
159 }
160
161 /* From now on we have to keep track of the last position to eventually
162 fill the gaps with the prescribed fill byte. */
163 last_position = ((char *) elf->map_address + elf->start_offset
164 + MAX (elf_typesize (LIBELFBITS, ELF_T_EHDR, 1),
165 ehdr->e_phoff)
166 + elf_typesize (LIBELFBITS, ELF_T_PHDR, ehdr->e_phnum));
167
168 /* Write all the sections. Well, only those which are modified. */
169 if (shnum > 0)
170 {
171 ElfW2(LIBELFBITS,Shdr) *shdr_dest;
172 Elf_ScnList *list = &elf->state.ELFW(elf,LIBELFBITS).scns;
173 Elf_Scn **scns = (Elf_Scn **) alloca (shnum * sizeof (Elf_Scn *));
174 char *shdr_start = ((char *) elf->map_address + elf->start_offset
175 + ehdr->e_shoff);
176 char *shdr_end = shdr_start + ehdr->e_shnum * ehdr->e_shentsize;
177 size_t cnt;
178
179 #if EV_NUM != 2
180 xfct_t shdr_fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR];
181 #else
182 # undef shdr_fctp
183 # define shdr_fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR]
184 #endif
185 shdr_dest = (ElfW2(LIBELFBITS,Shdr) *)
186 ((char *) elf->map_address + elf->start_offset + ehdr->e_shoff);
187
188 /* Get all sections into the array and sort them. */
189 sort_sections (scns, list);
190
191 /* Iterate over all the section in the order in which they
192 appear in the output file. */
193 for (cnt = 0; cnt < shnum; ++cnt)
194 {
195 Elf_Scn *scn = scns[cnt];
196 ElfW2(LIBELFBITS,Shdr) *shdr;
197 char *scn_start;
198 Elf_Data_List *dl;
199
200 shdr = scn->shdr.ELFW(e,LIBELFBITS);
201
202 scn_start = ((char *) elf->map_address
203 + elf->start_offset + shdr->sh_offset);
204 dl = &scn->data_list;
205
206 if (shdr->sh_type != SHT_NOBITS && scn->data_list_rear != NULL)
207 do
208 {
209 if ((scn->flags | dl->flags | elf->flags) & ELF_F_DIRTY)
210 {
211 if (scn_start + dl->data.d.d_off != last_position)
212 {
213 if (scn_start + dl->data.d.d_off > last_position)
214 {
215 /* This code assumes that the data blocks for
216 a section are ordered by offset. */
217 size_t written = 0;
218
219 if (last_position < shdr_start)
220 {
221 written = MIN (scn_start + dl->data.d.d_off
222 - last_position,
223 shdr_start - last_position);
224
225 memset (last_position, __libelf_fill_byte,
226 written);
227 }
228
229 if (last_position + written
230 != scn_start + dl->data.d.d_off
231 && shdr_end < scn_start + dl->data.d.d_off)
232 memset (shdr_end, __libelf_fill_byte,
233 scn_start + dl->data.d.d_off - shdr_end);
234
235 last_position = scn_start + dl->data.d.d_off;
236 }
237 }
238
239 if (unlikely (change_bo))
240 {
241 #if EV_NUM != 2
242 fctp = __elf_xfctstom[__libelf_version - 1][dl->data.d.d_version - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type];
243 #else
244 # undef fctp
245 fctp = __elf_xfctstom[0][0][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type];
246 #endif
247
248 /* Do the real work. */
249 (*fctp) (last_position, dl->data.d.d_buf,
250 dl->data.d.d_size, 1);
251
252 last_position += dl->data.d.d_size;
253 }
254 else
255 last_position = mempcpy (last_position,
256 dl->data.d.d_buf,
257 dl->data.d.d_size);
258 }
259 else
260 last_position += dl->data.d.d_size;
261
262 dl->flags &= ~ELF_F_DIRTY;
263
264 dl = dl->next;
265 }
266 while (dl != NULL);
267 else if (shdr->sh_type != SHT_NOBITS && scn->index != 0)
268 /* We have to trust the existing section header information. */
269 last_position += shdr->sh_size;
270
271 /* Write the section header table entry if necessary. */
272 if ((scn->shdr_flags | elf->flags) & ELF_F_DIRTY)
273 {
274 if (unlikely (change_bo))
275 (*shdr_fctp) (&shdr_dest[scn->index],
276 scn->shdr.ELFW(e,LIBELFBITS),
277 sizeof (ElfW2(LIBELFBITS,Shdr)), 1);
278 else
279 memcpy (&shdr_dest[scn->index],
280 scn->shdr.ELFW(e,LIBELFBITS),
281 sizeof (ElfW2(LIBELFBITS,Shdr)));
282
283 scn->shdr_flags &= ~ELF_F_DIRTY;
284 }
285
286 scn->flags &= ~ELF_F_DIRTY;
287 }
288
289 /* Fill the gap between last section and section header table if
290 necessary. */
291 if ((elf->flags & ELF_F_DIRTY)
292 && last_position < ((char *) elf->map_address + elf->start_offset
293 + ehdr->e_shoff))
294 memset (last_position, __libelf_fill_byte,
295 (char *) elf->map_address + elf->start_offset + ehdr->e_shoff
296 - last_position);
297 }
298
299 /* That was the last part. Clear the overall flag. */
300 elf->flags &= ~ELF_F_DIRTY;
301
302 return 0;
303 }
304
305
306 /* Size of the buffer we use to generate the blocks of fill bytes. */
307 #define FILLBUFSIZE 4096
308
309 /* If we have to convert the section buffer contents we have to use
310 temporary buffer. Only buffers up to MAX_TMPBUF bytes are allocated
311 on the stack. */
312 #define MAX_TMPBUF 32768
313
314
315 /* Helper function to write out fill bytes. */
316 static int
fill(int fd,off_t pos,size_t len,char * fillbuf,size_t * filledp)317 fill (int fd, off_t pos, size_t len, char *fillbuf, size_t *filledp)
318 {
319 size_t filled = *filledp;
320 size_t fill_len = MIN (len, FILLBUFSIZE);
321
322 if (unlikely (fill_len > filled) && filled < FILLBUFSIZE)
323 {
324 /* Initialize a few more bytes. */
325 memset (fillbuf + filled, __libelf_fill_byte, fill_len - filled);
326 *filledp = filled = fill_len;
327 }
328
329 do
330 {
331 /* This many bytes we want to write in this round. */
332 size_t n = MIN (filled, len);
333
334 if (unlikely ((size_t) pwrite (fd, fillbuf, n, pos) != n))
335 {
336 __libelf_seterrno (ELF_E_WRITE_ERROR);
337 return 1;
338 }
339
340 pos += n;
341 len -= n;
342 }
343 while (len > 0);
344
345 return 0;
346 }
347
348
349 int
350 internal_function_def
__elfw2(LIBELFBITS,updatefile)351 __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
352 {
353 char fillbuf[FILLBUFSIZE];
354 size_t filled = 0;
355 ElfW2(LIBELFBITS,Ehdr) *ehdr;
356 xfct_t fctp;
357 off_t last_offset;
358
359 /* We need the ELF header several times. */
360 ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
361
362 /* Write out the ELF header. */
363 if ((elf->state.ELFW(elf,LIBELFBITS).ehdr_flags | elf->flags) & ELF_F_DIRTY)
364 {
365 ElfW2(LIBELFBITS,Ehdr) tmp_ehdr;
366 ElfW2(LIBELFBITS,Ehdr) *out_ehdr = ehdr;
367
368 /* If the type sizes should be different at some time we have to
369 rewrite this code. */
370 assert (sizeof (ElfW2(LIBELFBITS,Ehdr))
371 == elf_typesize (LIBELFBITS, ELF_T_EHDR, 1));
372
373 if (unlikely (change_bo))
374 {
375 /* Today there is only one version of the ELF header. */
376 #if EV_NUM != 2
377 fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR];
378 #else
379 # undef fctp
380 # define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR]
381 #endif
382
383 /* Write the converted ELF header in a temporary buffer. */
384 (*fctp) (&tmp_ehdr, ehdr, sizeof (ElfW2(LIBELFBITS,Ehdr)), 1);
385
386 /* This is the buffer we want to write. */
387 out_ehdr = &tmp_ehdr;
388 }
389
390 /* Write out the ELF header. */
391 if (unlikely (pwrite (elf->fildes, out_ehdr,
392 sizeof (ElfW2(LIBELFBITS,Ehdr)), 0)
393 != sizeof (ElfW2(LIBELFBITS,Ehdr))))
394 {
395 __libelf_seterrno (ELF_E_WRITE_ERROR);
396 return 1;
397 }
398
399 elf->state.ELFW(elf,LIBELFBITS).ehdr_flags &= ~ELF_F_DIRTY;
400 }
401
402 /* If the type sizes should be different at some time we have to
403 rewrite this code. */
404 assert (sizeof (ElfW2(LIBELFBITS,Phdr))
405 == elf_typesize (LIBELFBITS, ELF_T_PHDR, 1));
406
407 /* Write out the program header table. */
408 if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL
409 && ((elf->state.ELFW(elf,LIBELFBITS).phdr_flags | elf->flags)
410 & ELF_F_DIRTY))
411 {
412 ElfW2(LIBELFBITS,Phdr) *tmp_phdr = NULL;
413 ElfW2(LIBELFBITS,Phdr) *out_phdr = elf->state.ELFW(elf,LIBELFBITS).phdr;
414
415 /* Maybe the user wants a gap between the ELF header and the program
416 header. */
417 if (ehdr->e_phoff > ehdr->e_ehsize
418 && unlikely (fill (elf->fildes, ehdr->e_ehsize,
419 ehdr->e_phoff - ehdr->e_ehsize, fillbuf, &filled)
420 != 0))
421 return 1;
422
423 if (unlikely (change_bo))
424 {
425 /* Today there is only one version of the ELF header. */
426 #if EV_NUM != 2
427 fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR];
428 #else
429 # undef fctp
430 # define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR]
431 #endif
432
433 /* Allocate sufficient memory. */
434 tmp_phdr = (ElfW2(LIBELFBITS,Phdr) *)
435 malloc (sizeof (ElfW2(LIBELFBITS,Phdr)) * ehdr->e_phnum);
436 if (tmp_phdr == NULL)
437 {
438 __libelf_seterrno (ELF_E_NOMEM);
439 return 1;
440 }
441
442 /* Write the converted ELF header in a temporary buffer. */
443 (*fctp) (tmp_phdr, elf->state.ELFW(elf,LIBELFBITS).phdr,
444 sizeof (ElfW2(LIBELFBITS,Phdr)) * ehdr->e_phnum, 1);
445
446 /* This is the buffer we want to write. */
447 out_phdr = tmp_phdr;
448 }
449
450 /* Write out the ELF header. */
451 if (unlikely ((size_t) pwrite (elf->fildes, out_phdr,
452 sizeof (ElfW2(LIBELFBITS,Phdr))
453 * ehdr->e_phnum, ehdr->e_phoff)
454 != sizeof (ElfW2(LIBELFBITS,Phdr)) * ehdr->e_phnum))
455 {
456 __libelf_seterrno (ELF_E_WRITE_ERROR);
457 return 1;
458 }
459
460 /* This is a no-op we we have not allocated any memory. */
461 free (tmp_phdr);
462
463 elf->state.ELFW(elf,LIBELFBITS).phdr_flags &= ~ELF_F_DIRTY;
464 }
465
466 /* From now on we have to keep track of the last position to eventually
467 fill the gaps with the prescribed fill byte. */
468 if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
469 last_offset = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
470 else
471 last_offset = (ehdr->e_phoff
472 + sizeof (ElfW2(LIBELFBITS,Phdr)) * ehdr->e_phnum);
473
474 /* Write all the sections. Well, only those which are modified. */
475 if (shnum > 0)
476 {
477 off_t shdr_offset;
478 Elf_ScnList *list = &elf->state.ELFW(elf,LIBELFBITS).scns;
479 ElfW2(LIBELFBITS,Shdr) *shdr_data;
480 Elf_Scn **scns = (Elf_Scn **) alloca (shnum * sizeof (Elf_Scn *));
481 int shdr_flags;
482 size_t cnt;
483
484 shdr_offset = elf->start_offset + ehdr->e_shoff;
485 #if EV_NUM != 2
486 xfct_t shdr_fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR];
487 #else
488 # undef shdr_fctp
489 # define shdr_fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR]
490 #endif
491
492 if (change_bo || elf->state.ELFW(elf,LIBELFBITS).shdr == NULL)
493 shdr_data = (ElfW2(LIBELFBITS,Shdr) *)
494 alloca (shnum * sizeof (ElfW2(LIBELFBITS,Shdr)));
495 else
496 shdr_data = elf->state.ELFW(elf,LIBELFBITS).shdr;
497 shdr_flags = elf->flags;
498
499 /* Get all sections into the array and sort them. */
500 sort_sections (scns, list);
501
502 for (cnt = 0; cnt < shnum; ++cnt)
503 {
504 Elf_Scn *scn = scns[cnt];
505 ElfW2(LIBELFBITS,Shdr) *shdr;
506 off_t scn_start;
507 Elf_Data_List *dl;
508
509 shdr = scn->shdr.ELFW(e,LIBELFBITS);
510
511 scn_start = elf->start_offset + shdr->sh_offset;
512 dl = &scn->data_list;
513
514 if (shdr->sh_type != SHT_NOBITS && scn->data_list_rear != NULL
515 && scn->index != 0)
516 do
517 {
518 if ((scn->flags | dl->flags | elf->flags) & ELF_F_DIRTY)
519 {
520 char tmpbuf[MAX_TMPBUF];
521 void *buf = dl->data.d.d_buf;
522
523 if (scn_start + dl->data.d.d_off != last_offset)
524 {
525 assert (last_offset < scn_start + dl->data.d.d_off);
526
527 if (unlikely (fill (elf->fildes, last_offset,
528 (scn_start + dl->data.d.d_off)
529 - last_offset, fillbuf,
530 &filled) != 0))
531 return 1;
532
533 last_offset = scn_start + dl->data.d.d_off;
534 }
535
536 if (unlikely (change_bo))
537 {
538 #if EV_NUM != 2
539 fctp = __elf_xfctstom[__libelf_version - 1][dl->data.d.d_version - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type];
540 #else
541 # undef fctp
542 fctp = __elf_xfctstom[0][0][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type];
543 #endif
544
545 buf = tmpbuf;
546 if (dl->data.d.d_size > MAX_TMPBUF)
547 {
548 buf = malloc (dl->data.d.d_size);
549 if (buf == NULL)
550 {
551 __libelf_seterrno (ELF_E_NOMEM);
552 return 1;
553 }
554 }
555
556 /* Do the real work. */
557 (*fctp) (buf, dl->data.d.d_buf, dl->data.d.d_size, 1);
558 }
559
560 if (unlikely ((size_t) pwrite (elf->fildes, buf,
561 dl->data.d.d_size,
562 last_offset)
563 != dl->data.d.d_size))
564 {
565 if (buf != dl->data.d.d_buf && buf != tmpbuf)
566 free (buf);
567
568 __libelf_seterrno (ELF_E_WRITE_ERROR);
569 return 1;
570 }
571
572 if (buf != dl->data.d.d_buf && buf != tmpbuf)
573 free (buf);
574 }
575
576 last_offset += dl->data.d.d_size;
577
578 dl->flags &= ~ELF_F_DIRTY;
579
580 dl = dl->next;
581 }
582 while (dl != NULL);
583 else if (shdr->sh_type != SHT_NOBITS && scn->index != 0)
584 last_offset = scn_start + shdr->sh_size;
585
586 /* Collect the section header table information. */
587 if (unlikely (change_bo))
588 (*shdr_fctp) (&shdr_data[scn->index],
589 scn->shdr.ELFW(e,LIBELFBITS),
590 sizeof (ElfW2(LIBELFBITS,Shdr)), 1);
591 else if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL)
592 memcpy (&shdr_data[scn->index], scn->shdr.ELFW(e,LIBELFBITS),
593 sizeof (ElfW2(LIBELFBITS,Shdr)));
594
595 shdr_flags |= scn->shdr_flags;
596 scn->shdr_flags &= ~ELF_F_DIRTY;
597 }
598
599 /* Fill the gap between last section and section header table if
600 necessary. */
601 if ((elf->flags & ELF_F_DIRTY) && last_offset < shdr_offset
602 && unlikely (fill (elf->fildes, last_offset,
603 shdr_offset - last_offset,
604 fillbuf, &filled) != 0))
605 return 1;
606
607 /* Write out the section header table. */
608 if (shdr_flags & ELF_F_DIRTY
609 && unlikely ((size_t) pwrite (elf->fildes, shdr_data,
610 sizeof (ElfW2(LIBELFBITS,Shdr))
611 * shnum, shdr_offset)
612 != sizeof (ElfW2(LIBELFBITS,Shdr)) * shnum))
613 {
614 __libelf_seterrno (ELF_E_WRITE_ERROR);
615 return 1;
616 }
617 }
618
619 /* That was the last part. Clear the overall flag. */
620 elf->flags &= ~ELF_F_DIRTY;
621
622 return 0;
623 }
624