2 * update.c - implementation of the elf_update(3) function.
3 * Copyright (C) 1995 - 2006 Michael Riepe
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 static const char rcsid[] = "@(#) $Id: update.c,v 1.34 2009/05/22 17:08:09 michael Exp $";
30 #endif /* HAVE_MMAP */
32 static const unsigned short __encoding = ELFDATA2LSB + (ELFDATA2MSB << 8);
33 #define native_encoding (*(unsigned char*)&__encoding)
35 #define rewrite(var,val,f) \
36 do{if((var)!=(val)){(var)=(val);(f)|=ELF_F_DIRTY;}}while(0)
38 #define align(var,val) \
39 do{if((val)>1){(var)+=(val)-1;(var)-=(var)%(val);}}while(0)
42 #define max(a,b) ((a)>(b)?(a):(b))
45 scn_data_layout(Elf_Scn *scn, unsigned v, unsigned type, size_t *algn, unsigned *flag) {
46 Elf *elf = scn->s_elf;
48 int layout = (elf->e_elf_flags & ELF_F_LAYOUT) == 0;
54 if (!(sd = scn->s_data_1)) {
55 /* no data in section */
59 /* load data from file, if any */
60 if (!(data = elf_getdata(scn, NULL))) {
63 elf_assert(data == &sd->sd_data);
64 for (; sd; sd = sd->sd_link) {
65 elf_assert(sd->sd_magic == DATA_MAGIC);
66 elf_assert(sd->sd_scn == scn);
68 if (!valid_version(sd->sd_data.d_version)) {
72 fsize = sd->sd_data.d_size;
73 if (fsize && type != SHT_NOBITS && valid_type(sd->sd_data.d_type)) {
74 if (elf->e_class == ELFCLASS32) {
75 fsize = _elf32_xltsize(&sd->sd_data, v, ELFDATA2LSB, 1);
78 else if (elf->e_class == ELFCLASS64) {
79 fsize = _elf64_xltsize(&sd->sd_data, v, ELFDATA2LSB, 1);
81 #endif /* __LIBELF64 */
83 elf_assert(valid_class(elf->e_class));
84 seterr(ERROR_UNIMPLEMENTED);
87 if (fsize == (size_t)-1) {
93 align(len, sd->sd_data.d_align);
94 scn_align = max(scn_align, sd->sd_data.d_align);
95 rewrite(sd->sd_data.d_off, (off_t)len, sd->sd_data_flags);
99 len = max(len, sd->sd_data.d_off + fsize);
102 *flag |= sd->sd_data_flags;
109 scn_entsize(const Elf *elf, unsigned version, unsigned stype) {
112 switch ((type = _elf_scn_type(stype))) {
117 return 0; /* What else can I do? Thank you, Sun! */
119 return _fsize(elf->e_class, version, type);
124 _elf32_layout(Elf *elf, unsigned *flag) {
125 int layout = (elf->e_elf_flags & ELF_F_LAYOUT) == 0;
126 int allow_overlap = (elf->e_elf_flags & ELF_F_LAYOUT_OVERLAP) != 0;
127 Elf32_Ehdr *ehdr = (Elf32_Ehdr*)elf->e_ehdr;
137 *flag = elf->e_elf_flags | elf->e_phdr_flags;
139 if ((version = ehdr->e_version) == EV_NONE) {
140 version = EV_CURRENT;
142 if (!valid_version(version)) {
143 seterr(ERROR_UNKNOWN_VERSION);
146 if ((encoding = ehdr->e_ident[EI_DATA]) == ELFDATANONE) {
147 encoding = native_encoding;
149 if (!valid_encoding(encoding)) {
150 seterr(ERROR_UNKNOWN_ENCODING);
153 entsize = _fsize(ELFCLASS32, version, ELF_T_EHDR);
155 rewrite(ehdr->e_ehsize, entsize, elf->e_ehdr_flags);
158 align_addr = _fsize(ELFCLASS32, version, ELF_T_ADDR);
159 elf_assert(align_addr);
161 if ((phnum = elf->e_phnum)) {
162 entsize = _fsize(ELFCLASS32, version, ELF_T_PHDR);
165 align(off, align_addr);
166 rewrite(ehdr->e_phoff, off, elf->e_ehdr_flags);
167 off += phnum * entsize;
170 off = max(off, ehdr->e_phoff + phnum * entsize);
176 rewrite(ehdr->e_phoff, 0, elf->e_ehdr_flags);
179 if (phnum >= PN_XNUM) {
180 Elf_Scn *scn = elf->e_scn_1;
181 Elf32_Shdr *shdr = &scn->s_shdr32;
184 elf_assert(scn->s_index == 0);
185 rewrite(shdr->sh_info, phnum, scn->s_shdr_flags);
186 *flag |= scn->s_shdr_flags;
189 rewrite(ehdr->e_phnum, phnum, elf->e_ehdr_flags);
190 rewrite(ehdr->e_phentsize, entsize, elf->e_ehdr_flags);
192 for (scn = elf->e_scn_1, shnum = 0; scn; scn = scn->s_link, ++shnum) {
193 Elf32_Shdr *shdr = &scn->s_shdr32;
194 size_t scn_align = 1;
197 elf_assert(scn->s_index == shnum);
199 *flag |= scn->s_scn_flags;
201 if (scn->s_index == SHN_UNDEF) {
202 rewrite(shdr->sh_entsize, 0, scn->s_shdr_flags);
204 rewrite(shdr->sh_offset, 0, scn->s_shdr_flags);
205 rewrite(shdr->sh_size, 0, scn->s_shdr_flags);
206 rewrite(shdr->sh_addralign, 0, scn->s_shdr_flags);
208 *flag |= scn->s_shdr_flags;
211 if (shdr->sh_type == SHT_NULL) {
212 *flag |= scn->s_shdr_flags;
216 len = scn_data_layout(scn, version, shdr->sh_type, &scn_align, flag);
222 * Never override the program's choice.
224 if (shdr->sh_entsize == 0) {
225 entsize = scn_entsize(elf, version, shdr->sh_type);
227 rewrite(shdr->sh_entsize, entsize, scn->s_shdr_flags);
232 align(off, scn_align);
233 rewrite(shdr->sh_offset, off, scn->s_shdr_flags);
234 rewrite(shdr->sh_size, (size_t)len, scn->s_shdr_flags);
235 rewrite(shdr->sh_addralign, scn_align, scn->s_shdr_flags);
237 if (shdr->sh_type != SHT_NOBITS) {
241 else if ((size_t)len > shdr->sh_size) {
242 seterr(ERROR_SCN2SMALL);
249 end1 = shdr->sh_offset;
250 if (shdr->sh_type != SHT_NOBITS) {
251 end1 += shdr->sh_size;
253 if (!allow_overlap && shdr->sh_offset < off) {
255 * check for overlapping sections
257 for (scn2 = elf->e_scn_1; scn2; scn2 = scn2->s_link) {
261 end2 = scn2->s_shdr32.sh_offset;
262 if (scn2->s_shdr32.sh_type != SHT_NOBITS) {
263 end2 += scn2->s_shdr32.sh_size;
265 if (end1 > scn2->s_shdr32.sh_offset
266 && end2 > shdr->sh_offset) {
267 seterr(ERROR_SCN_OVERLAP);
276 *flag |= scn->s_shdr_flags;
280 entsize = _fsize(ELFCLASS32, version, ELF_T_SHDR);
283 align(off, align_addr);
284 rewrite(ehdr->e_shoff, off, elf->e_ehdr_flags);
285 off += shnum * entsize;
288 off = max(off, ehdr->e_shoff + shnum * entsize);
294 rewrite(ehdr->e_shoff, 0, elf->e_ehdr_flags);
297 if (shnum >= SHN_LORESERVE) {
298 Elf_Scn *scn = elf->e_scn_1;
299 Elf32_Shdr *shdr = &scn->s_shdr32;
301 elf_assert(scn->s_index == 0);
302 rewrite(shdr->sh_size, shnum, scn->s_shdr_flags);
303 *flag |= scn->s_shdr_flags;
306 rewrite(ehdr->e_shnum, shnum, elf->e_ehdr_flags);
307 rewrite(ehdr->e_shentsize, entsize, elf->e_ehdr_flags);
309 rewrite(ehdr->e_ident[EI_MAG0], ELFMAG0, elf->e_ehdr_flags);
310 rewrite(ehdr->e_ident[EI_MAG1], ELFMAG1, elf->e_ehdr_flags);
311 rewrite(ehdr->e_ident[EI_MAG2], ELFMAG2, elf->e_ehdr_flags);
312 rewrite(ehdr->e_ident[EI_MAG3], ELFMAG3, elf->e_ehdr_flags);
313 rewrite(ehdr->e_ident[EI_CLASS], ELFCLASS32, elf->e_ehdr_flags);
314 rewrite(ehdr->e_ident[EI_DATA], encoding, elf->e_ehdr_flags);
315 rewrite(ehdr->e_ident[EI_VERSION], version, elf->e_ehdr_flags);
316 rewrite(ehdr->e_version, version, elf->e_ehdr_flags);
318 *flag |= elf->e_ehdr_flags;
326 _elf64_layout(Elf *elf, unsigned *flag) {
327 int layout = (elf->e_elf_flags & ELF_F_LAYOUT) == 0;
328 int allow_overlap = (elf->e_elf_flags & ELF_F_LAYOUT_OVERLAP) != 0;
329 Elf64_Ehdr *ehdr = (Elf64_Ehdr*)elf->e_ehdr;
339 *flag = elf->e_elf_flags | elf->e_phdr_flags;
341 if ((version = ehdr->e_version) == EV_NONE) {
342 version = EV_CURRENT;
344 if (!valid_version(version)) {
345 seterr(ERROR_UNKNOWN_VERSION);
348 if ((encoding = ehdr->e_ident[EI_DATA]) == ELFDATANONE) {
349 encoding = native_encoding;
351 if (!valid_encoding(encoding)) {
352 seterr(ERROR_UNKNOWN_ENCODING);
355 entsize = _fsize(ELFCLASS64, version, ELF_T_EHDR);
357 rewrite(ehdr->e_ehsize, entsize, elf->e_ehdr_flags);
360 align_addr = _fsize(ELFCLASS64, version, ELF_T_ADDR);
361 elf_assert(align_addr);
363 if ((phnum = elf->e_phnum)) {
364 entsize = _fsize(ELFCLASS64, version, ELF_T_PHDR);
367 align(off, align_addr);
368 rewrite(ehdr->e_phoff, off, elf->e_ehdr_flags);
369 off += phnum * entsize;
372 off = max(off, ehdr->e_phoff + phnum * entsize);
378 rewrite(ehdr->e_phoff, 0, elf->e_ehdr_flags);
381 if (phnum >= PN_XNUM) {
382 Elf_Scn *scn = elf->e_scn_1;
383 Elf32_Shdr *shdr = &scn->s_shdr32;
385 /* modify first section header, too! */
387 elf_assert(scn->s_index == 0);
388 rewrite(shdr->sh_info, phnum, scn->s_shdr_flags);
389 *flag |= scn->s_shdr_flags;
392 rewrite(ehdr->e_phnum, phnum, elf->e_ehdr_flags);
393 rewrite(ehdr->e_phentsize, entsize, elf->e_ehdr_flags);
395 for (scn = elf->e_scn_1, shnum = 0; scn; scn = scn->s_link, ++shnum) {
396 Elf64_Shdr *shdr = &scn->s_shdr64;
397 size_t scn_align = 1;
400 elf_assert(scn->s_index == shnum);
402 *flag |= scn->s_scn_flags;
404 if (scn->s_index == SHN_UNDEF) {
405 rewrite(shdr->sh_entsize, 0, scn->s_shdr_flags);
407 rewrite(shdr->sh_offset, 0, scn->s_shdr_flags);
408 rewrite(shdr->sh_size, 0, scn->s_shdr_flags);
409 rewrite(shdr->sh_addralign, 0, scn->s_shdr_flags);
411 *flag |= scn->s_shdr_flags;
414 if (shdr->sh_type == SHT_NULL) {
415 *flag |= scn->s_shdr_flags;
419 len = scn_data_layout(scn, version, shdr->sh_type, &scn_align, flag);
425 * Never override the program's choice.
427 if (shdr->sh_entsize == 0) {
428 entsize = scn_entsize(elf, version, shdr->sh_type);
430 rewrite(shdr->sh_entsize, entsize, scn->s_shdr_flags);
435 align(off, scn_align);
436 rewrite(shdr->sh_offset, off, scn->s_shdr_flags);
437 rewrite(shdr->sh_size, (size_t)len, scn->s_shdr_flags);
438 rewrite(shdr->sh_addralign, scn_align, scn->s_shdr_flags);
440 if (shdr->sh_type != SHT_NOBITS) {
444 else if ((size_t)len > shdr->sh_size) {
445 seterr(ERROR_SCN2SMALL);
452 end1 = shdr->sh_offset;
453 if (shdr->sh_type != SHT_NOBITS) {
454 end1 += shdr->sh_size;
456 if (!allow_overlap && shdr->sh_offset < off) {
458 * check for overlapping sections
460 for (scn2 = elf->e_scn_1; scn2; scn2 = scn2->s_link) {
464 end2 = scn2->s_shdr64.sh_offset;
465 if (scn2->s_shdr64.sh_type != SHT_NOBITS) {
466 end2 += scn2->s_shdr64.sh_size;
468 if (end1 > scn2->s_shdr64.sh_offset
469 && end2 > shdr->sh_offset) {
470 seterr(ERROR_SCN_OVERLAP);
479 *flag |= scn->s_shdr_flags;
483 entsize = _fsize(ELFCLASS64, version, ELF_T_SHDR);
486 align(off, align_addr);
487 rewrite(ehdr->e_shoff, off, elf->e_ehdr_flags);
488 off += shnum * entsize;
491 off = max(off, ehdr->e_shoff + shnum * entsize);
497 rewrite(ehdr->e_shoff, 0, elf->e_ehdr_flags);
500 if (shnum >= SHN_LORESERVE) {
501 Elf_Scn *scn = elf->e_scn_1;
502 Elf64_Shdr *shdr = &scn->s_shdr64;
504 elf_assert(scn->s_index == 0);
505 rewrite(shdr->sh_size, shnum, scn->s_shdr_flags);
506 *flag |= scn->s_shdr_flags;
509 rewrite(ehdr->e_shnum, shnum, elf->e_ehdr_flags);
510 rewrite(ehdr->e_shentsize, entsize, elf->e_ehdr_flags);
512 rewrite(ehdr->e_ident[EI_MAG0], ELFMAG0, elf->e_ehdr_flags);
513 rewrite(ehdr->e_ident[EI_MAG1], ELFMAG1, elf->e_ehdr_flags);
514 rewrite(ehdr->e_ident[EI_MAG2], ELFMAG2, elf->e_ehdr_flags);
515 rewrite(ehdr->e_ident[EI_MAG3], ELFMAG3, elf->e_ehdr_flags);
516 rewrite(ehdr->e_ident[EI_CLASS], ELFCLASS64, elf->e_ehdr_flags);
517 rewrite(ehdr->e_ident[EI_DATA], encoding, elf->e_ehdr_flags);
518 rewrite(ehdr->e_ident[EI_VERSION], version, elf->e_ehdr_flags);
519 rewrite(ehdr->e_version, version, elf->e_ehdr_flags);
521 *flag |= elf->e_ehdr_flags;
526 #endif /* __LIBELF64 */
528 #define ptrinside(p,a,l) ((p)>=(a)&&(p)<(a)+(l))
529 #define newptr(p,o,n) ((p)=((p)-(o))+(n))
532 _elf_update_pointers(Elf *elf, char *outbuf, size_t len) {
535 char *data, *rawdata;
538 elf_assert(elf->e_data);
539 elf_assert(!elf->e_parent);
540 elf_assert(!elf->e_unmap_data);
541 elf_assert(elf->e_kind == ELF_K_ELF);
542 elf_assert(len >= EI_NIDENT);
544 /* resize memory images */
545 if (len <= elf->e_dsize) {
546 /* don't shorten the memory image */
549 else if ((data = (char*)realloc(elf->e_data, len))) {
553 seterr(ERROR_IO_2BIG);
556 if (elf->e_rawdata == elf->e_data) {
557 /* update frozen raw image */
558 memcpy(data, outbuf, len);
559 elf->e_data = elf->e_rawdata = data;
560 /* cooked data is stored outside the raw image */
563 if (elf->e_rawdata) {
564 /* update raw image */
565 if (!(rawdata = (char*)realloc(elf->e_rawdata, len))) {
566 seterr(ERROR_IO_2BIG);
569 memcpy(rawdata, outbuf, len);
570 elf->e_rawdata = rawdata;
572 if (data == elf->e_data) {
573 /* nothing more to do */
576 /* adjust internal pointers */
577 for (scn = elf->e_scn_1; scn; scn = scn->s_link) {
578 elf_assert(scn->s_magic == SCN_MAGIC);
579 elf_assert(scn->s_elf == elf);
580 if ((sd = scn->s_data_1)) {
581 elf_assert(sd->sd_magic == DATA_MAGIC);
582 elf_assert(sd->sd_scn == scn);
583 if (sd->sd_memdata && !sd->sd_free_data) {
584 elf_assert(ptrinside(sd->sd_memdata, elf->e_data, elf->e_dsize));
585 if (sd->sd_data.d_buf == sd->sd_memdata) {
586 newptr(sd->sd_memdata, elf->e_data, data);
587 sd->sd_data.d_buf = sd->sd_memdata;
590 newptr(sd->sd_memdata, elf->e_data, data);
594 if ((sd = scn->s_rawdata)) {
595 elf_assert(sd->sd_magic == DATA_MAGIC);
596 elf_assert(sd->sd_scn == scn);
597 if (sd->sd_memdata && sd->sd_free_data) {
600 if (elf->e_class == ELFCLASS32) {
601 off = scn->s_shdr32.sh_offset;
602 len = scn->s_shdr32.sh_size;
605 else if (elf->e_class == ELFCLASS64) {
606 off = scn->s_shdr64.sh_offset;
607 len = scn->s_shdr64.sh_size;
609 #endif /* __LIBELF64 */
611 seterr(ERROR_UNIMPLEMENTED);
614 if (!(rawdata = (char*)realloc(sd->sd_memdata, len))) {
615 seterr(ERROR_IO_2BIG);
618 memcpy(rawdata, outbuf + off, len);
619 if (sd->sd_data.d_buf == sd->sd_memdata) {
620 sd->sd_data.d_buf = rawdata;
622 sd->sd_memdata = rawdata;
634 _elf32_write(Elf *elf, char *outbuf, size_t len) {
644 elf_assert(elf->e_ehdr);
645 ehdr = (Elf32_Ehdr*)elf->e_ehdr;
646 encode = ehdr->e_ident[EI_DATA];
649 src.d_type = ELF_T_EHDR;
650 src.d_size = _msize(ELFCLASS32, _elf_version, ELF_T_EHDR);
651 src.d_version = _elf_version;
653 dst.d_size = ehdr->e_ehsize;
654 dst.d_version = ehdr->e_version;
655 if (!elf32_xlatetof(&dst, &src, encode)) {
660 src.d_buf = elf->e_phdr;
661 src.d_type = ELF_T_PHDR;
662 src.d_size = elf->e_phnum * _msize(ELFCLASS32, _elf_version, ELF_T_PHDR);
663 src.d_version = _elf_version;
664 dst.d_buf = outbuf + ehdr->e_phoff;
665 dst.d_size = elf->e_phnum * ehdr->e_phentsize;
666 dst.d_version = ehdr->e_version;
667 if (!elf32_xlatetof(&dst, &src, encode)) {
672 for (scn = elf->e_scn_1; scn; scn = scn->s_link) {
673 elf_assert(scn->s_magic == SCN_MAGIC);
674 elf_assert(scn->s_elf == elf);
676 src.d_buf = &scn->s_uhdr;
677 src.d_type = ELF_T_SHDR;
678 src.d_size = _msize(ELFCLASS32, EV_CURRENT, ELF_T_SHDR);
679 src.d_version = EV_CURRENT;
680 dst.d_buf = outbuf + ehdr->e_shoff + scn->s_index * ehdr->e_shentsize;
681 dst.d_size = ehdr->e_shentsize;
682 dst.d_version = ehdr->e_version;
683 if (!elf32_xlatetof(&dst, &src, encode)) {
687 if (scn->s_index == SHN_UNDEF) {
690 shdr = &scn->s_shdr32;
691 if (shdr->sh_type == SHT_NULL || shdr->sh_type == SHT_NOBITS) {
694 /* XXX: this is probably no longer necessary */
695 if (scn->s_data_1 && !elf_getdata(scn, NULL)) {
698 for (sd = scn->s_data_1; sd; sd = sd->sd_link) {
699 elf_assert(sd->sd_magic == DATA_MAGIC);
700 elf_assert(sd->sd_scn == scn);
706 seterr(ERROR_NULLBUF);
709 dst.d_buf = outbuf + shdr->sh_offset + src.d_off;
710 dst.d_size = src.d_size;
711 dst.d_version = ehdr->e_version;
712 if (valid_type(src.d_type)) {
715 tmp = _elf32_xltsize(&src, dst.d_version, ELFDATA2LSB, 1);
716 if (tmp == (size_t)-1) {
722 src.d_type = ELF_T_BYTE;
724 if (!elf32_xlatetof(&dst, &src, encode)) {
731 if (elf->e_readable && _elf_update_pointers(elf, outbuf, len)) {
734 /* NOTE: ehdr is no longer valid! */
735 ehdr = (Elf32_Ehdr*)elf->e_ehdr; elf_assert(ehdr);
736 elf->e_encoding = ehdr->e_ident[EI_DATA];
737 elf->e_version = ehdr->e_ident[EI_VERSION];
738 elf->e_elf_flags &= ~ELF_F_DIRTY;
739 elf->e_ehdr_flags &= ~ELF_F_DIRTY;
740 elf->e_phdr_flags &= ~ELF_F_DIRTY;
741 for (scn = elf->e_scn_1; scn; scn = scn->s_link) {
742 scn->s_scn_flags &= ~ELF_F_DIRTY;
743 scn->s_shdr_flags &= ~ELF_F_DIRTY;
744 for (sd = scn->s_data_1; sd; sd = sd->sd_link) {
745 sd->sd_data_flags &= ~ELF_F_DIRTY;
747 if (elf->e_readable) {
748 shdr = &scn->s_shdr32;
749 scn->s_type = shdr->sh_type;
750 scn->s_size = shdr->sh_size;
751 scn->s_offset = shdr->sh_offset;
761 _elf64_write(Elf *elf, char *outbuf, size_t len) {
771 elf_assert(elf->e_ehdr);
772 ehdr = (Elf64_Ehdr*)elf->e_ehdr;
773 encode = ehdr->e_ident[EI_DATA];
776 src.d_type = ELF_T_EHDR;
777 src.d_size = _msize(ELFCLASS64, _elf_version, ELF_T_EHDR);
778 src.d_version = _elf_version;
780 dst.d_size = ehdr->e_ehsize;
781 dst.d_version = ehdr->e_version;
782 if (!elf64_xlatetof(&dst, &src, encode)) {
787 src.d_buf = elf->e_phdr;
788 src.d_type = ELF_T_PHDR;
789 src.d_size = elf->e_phnum * _msize(ELFCLASS64, _elf_version, ELF_T_PHDR);
790 src.d_version = _elf_version;
791 dst.d_buf = outbuf + ehdr->e_phoff;
792 dst.d_size = elf->e_phnum * ehdr->e_phentsize;
793 dst.d_version = ehdr->e_version;
794 if (!elf64_xlatetof(&dst, &src, encode)) {
799 for (scn = elf->e_scn_1; scn; scn = scn->s_link) {
800 elf_assert(scn->s_magic == SCN_MAGIC);
801 elf_assert(scn->s_elf == elf);
803 src.d_buf = &scn->s_uhdr;
804 src.d_type = ELF_T_SHDR;
805 src.d_size = _msize(ELFCLASS64, EV_CURRENT, ELF_T_SHDR);
806 src.d_version = EV_CURRENT;
807 dst.d_buf = outbuf + ehdr->e_shoff + scn->s_index * ehdr->e_shentsize;
808 dst.d_size = ehdr->e_shentsize;
809 dst.d_version = ehdr->e_version;
810 if (!elf64_xlatetof(&dst, &src, encode)) {
814 if (scn->s_index == SHN_UNDEF) {
817 shdr = &scn->s_shdr64;
818 if (shdr->sh_type == SHT_NULL || shdr->sh_type == SHT_NOBITS) {
821 /* XXX: this is probably no longer necessary */
822 if (scn->s_data_1 && !elf_getdata(scn, NULL)) {
825 for (sd = scn->s_data_1; sd; sd = sd->sd_link) {
826 elf_assert(sd->sd_magic == DATA_MAGIC);
827 elf_assert(sd->sd_scn == scn);
833 seterr(ERROR_NULLBUF);
836 dst.d_buf = outbuf + shdr->sh_offset + src.d_off;
837 dst.d_size = src.d_size;
838 dst.d_version = ehdr->e_version;
839 if (valid_type(src.d_type)) {
842 tmp = _elf64_xltsize(&src, dst.d_version, ELFDATA2LSB, 1);
843 if (tmp == (size_t)-1) {
849 src.d_type = ELF_T_BYTE;
851 if (!elf64_xlatetof(&dst, &src, encode)) {
858 if (elf->e_readable && _elf_update_pointers(elf, outbuf, len)) {
861 /* NOTE: ehdr is no longer valid! */
862 ehdr = (Elf64_Ehdr*)elf->e_ehdr; elf_assert(ehdr);
863 elf->e_encoding = ehdr->e_ident[EI_DATA];
864 elf->e_version = ehdr->e_ident[EI_VERSION];
865 elf->e_elf_flags &= ~ELF_F_DIRTY;
866 elf->e_ehdr_flags &= ~ELF_F_DIRTY;
867 elf->e_phdr_flags &= ~ELF_F_DIRTY;
868 for (scn = elf->e_scn_1; scn; scn = scn->s_link) {
869 scn->s_scn_flags &= ~ELF_F_DIRTY;
870 scn->s_shdr_flags &= ~ELF_F_DIRTY;
871 for (sd = scn->s_data_1; sd; sd = sd->sd_link) {
872 sd->sd_data_flags &= ~ELF_F_DIRTY;
874 if (elf->e_readable) {
875 shdr = &scn->s_shdr64;
876 scn->s_type = shdr->sh_type;
877 scn->s_size = shdr->sh_size;
878 scn->s_offset = shdr->sh_offset;
885 #endif /* __LIBELF64 */
888 xwrite(int fd, char *buffer, size_t len) {
893 n = write(fd, buffer + done, len - done);
895 /* file system full */
898 else if (n != (size_t)-1) {
899 /* some bytes written, continue */
902 else if (errno != EAGAIN && errno != EINTR) {
911 _elf_output(Elf *elf, int fd, size_t len, off_t (*_elf_write)(Elf*, char*, size_t)) {
918 #endif /* HAVE_FTRUNCATE */
921 * Make sure the file is (at least) len bytes long
924 lseek(fd, (off_t)len, SEEK_SET);
925 if (ftruncate(fd, len)) {
926 #else /* HAVE_FTRUNCATE */
928 #endif /* HAVE_FTRUNCATE */
929 if (lseek(fd, (off_t)len - 1, SEEK_SET) != (off_t)len - 1) {
930 seterr(ERROR_IO_SEEK);
933 if (xwrite(fd, "", 1)) {
934 seterr(ERROR_IO_WRITE);
938 buf = (void*)mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
939 if (buf != (char*)-1) {
940 if ((char)_elf_fill && !(elf->e_elf_flags & ELF_F_LAYOUT)) {
941 memset(buf, _elf_fill, len);
943 err = _elf_write(elf, buf, len);
947 #endif /* HAVE_MMAP */
948 if (!(buf = (char*)malloc(len))) {
949 seterr(ERROR_MEM_OUTBUF);
952 memset(buf, _elf_fill, len);
953 err = _elf_write(elf, buf, len);
954 if (err != -1 && (size_t)err == len) {
955 if (lseek(fd, (off_t)0, SEEK_SET)) {
956 seterr(ERROR_IO_SEEK);
959 else if (xwrite(fd, buf, len)) {
960 seterr(ERROR_IO_WRITE);
969 elf_update(Elf *elf, Elf_Cmd cmd) {
976 elf_assert(elf->e_magic == ELF_MAGIC);
977 if (cmd == ELF_C_WRITE) {
978 if (!elf->e_writable) {
979 seterr(ERROR_RDONLY);
982 if (elf->e_disabled) {
983 seterr(ERROR_FDDISABLED);
987 else if (cmd != ELF_C_NULL) {
988 seterr(ERROR_INVALID_CMD);
993 seterr(ERROR_NOEHDR);
995 else if (elf->e_kind != ELF_K_ELF) {
996 seterr(ERROR_NOTELF);
998 else if (elf->e_class == ELFCLASS32) {
999 len = _elf32_layout(elf, &flag);
1000 if (len != -1 && cmd == ELF_C_WRITE && (flag & ELF_F_DIRTY)) {
1001 len = _elf_output(elf, elf->e_fd, (size_t)len, _elf32_write);
1006 else if (elf->e_class == ELFCLASS64) {
1007 len = _elf64_layout(elf, &flag);
1008 if (len != -1 && cmd == ELF_C_WRITE && (flag & ELF_F_DIRTY)) {
1009 len = _elf_output(elf, elf->e_fd, (size_t)len, _elf64_write);
1013 #endif /* __LIBELF64 */
1014 else if (valid_class(elf->e_class)) {
1015 seterr(ERROR_UNIMPLEMENTED);
1018 seterr(ERROR_UNKNOWN_CLASS);