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