1 /* Write changed data structures. 2 Copyright (C) 2000, 2001, 2002, 2004 Red Hat, Inc. 3 Written by Ulrich Drepper <drepper (at) 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 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 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 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 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 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