00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <private.h>
00025
00026 #ifndef lint
00027 static const char rcsid[] = "@(#) $Id: update.c,v 1.1.1.1 2005/10/21 19:00:00 marcel Exp $";
00028 #endif
00029
00030 #if HAVE_MMAP
00031 #include <sys/mman.h>
00032 #endif
00033
00034 static const unsigned short __encoding = ELFDATA2LSB + (ELFDATA2MSB << 8);
00035 #define native_encoding (*(unsigned char*)&__encoding)
00036
00037 #define rewrite(var,val,f) \
00038 do{if((var)!=(val)){(var)=(val);(f)|=ELF_F_DIRTY;}}while(0)
00039
00040 #define align(var,val) \
00041 do{if((val)>1){(var)+=(val)-1;(var)-=(var)%(val);}}while(0)
00042
00043 #define max(a,b) ((a)>(b)?(a):(b))
00044
00045 static off_t
00046 scn_data_layout(Elf_Scn *scn, unsigned v, unsigned type, size_t *algn, unsigned *flag) {
00047 Elf *elf = scn->s_elf;
00048 Elf_Data *data;
00049 int layout = (elf->e_elf_flags & ELF_F_LAYOUT) == 0;
00050 size_t scn_align = 1;
00051 size_t len = 0;
00052 Scn_Data *sd;
00053 size_t fsize;
00054
00055 if (!(sd = scn->s_data_1)) {
00056
00057 *algn = scn_align;
00058 return (off_t)len;
00059 }
00060
00061 if (!(data = elf_getdata(scn, NULL))) {
00062 return (off_t)-1;
00063 }
00064 elf_assert(data == &sd->sd_data);
00065 for (; sd; sd = sd->sd_link) {
00066 elf_assert(sd->sd_magic == DATA_MAGIC);
00067 elf_assert(sd->sd_scn == scn);
00068
00069 if (!valid_version(sd->sd_data.d_version)) {
00070 return (off_t)-1;
00071 }
00072
00073 fsize = sd->sd_data.d_size;
00074 if (fsize && type != SHT_NOBITS && valid_type(sd->sd_data.d_type)) {
00075 if (elf->e_class == ELFCLASS32) {
00076 fsize = _elf32_xltsize(&sd->sd_data, v, ELFDATA2LSB, 1);
00077 }
00078 #if __LIBELF64
00079 else if (elf->e_class == ELFCLASS64) {
00080 fsize = _elf64_xltsize(&sd->sd_data, v, ELFDATA2LSB, 1);
00081 }
00082 #endif
00083 else {
00084 elf_assert(valid_class(elf->e_class));
00085 seterr(ERROR_UNIMPLEMENTED);
00086 return (off_t)-1;
00087 }
00088 if (fsize == (size_t)-1) {
00089 return (off_t)-1;
00090 }
00091 }
00092
00093 if (layout) {
00094 align(len, sd->sd_data.d_align);
00095 scn_align = max(scn_align, sd->sd_data.d_align);
00096 rewrite(sd->sd_data.d_off, (off_t)len, sd->sd_data_flags);
00097 len += fsize;
00098 }
00099 else {
00100 len = max(len, sd->sd_data.d_off + fsize);
00101 }
00102
00103 *flag |= sd->sd_data_flags;
00104 }
00105 *algn = scn_align;
00106 return (off_t)len;
00107 }
00108
00109 static size_t
00110 scn_entsize(const Elf *elf, unsigned version, unsigned stype) {
00111 Elf_Type type;
00112
00113 switch ((type = _elf_scn_type(stype))) {
00114 case ELF_T_BYTE:
00115 return 0;
00116 case ELF_T_VDEF:
00117 case ELF_T_VNEED:
00118 return 0;
00119 default:
00120 return _fsize(elf->e_class, version, type);
00121 }
00122 }
00123
00124 static off_t
00125 _elf32_layout(Elf *elf, unsigned *flag) {
00126 int layout = (elf->e_elf_flags & ELF_F_LAYOUT) == 0;
00127 Elf32_Ehdr *ehdr = (Elf32_Ehdr*)elf->e_ehdr;
00128 size_t off = 0;
00129 unsigned version;
00130 unsigned encoding;
00131 size_t align_addr;
00132 size_t entsize;
00133 unsigned shnum;
00134 Elf_Scn *scn;
00135
00136 *flag = elf->e_elf_flags | elf->e_phdr_flags;
00137
00138 if ((version = ehdr->e_version) == EV_NONE) {
00139 version = EV_CURRENT;
00140 }
00141 if (!valid_version(version)) {
00142 seterr(ERROR_UNKNOWN_VERSION);
00143 return -1;
00144 }
00145 if ((encoding = ehdr->e_ident[EI_DATA]) == ELFDATANONE) {
00146 encoding = native_encoding;
00147 }
00148 if (!valid_encoding(encoding)) {
00149 seterr(ERROR_UNKNOWN_ENCODING);
00150 return -1;
00151 }
00152 entsize = _fsize(ELFCLASS32, version, ELF_T_EHDR);
00153 elf_assert(entsize);
00154 rewrite(ehdr->e_ehsize, entsize, elf->e_ehdr_flags);
00155 off = entsize;
00156
00157 align_addr = _fsize(ELFCLASS32, version, ELF_T_ADDR);
00158 elf_assert(align_addr);
00159
00160 if (elf->e_phnum) {
00161 entsize = _fsize(ELFCLASS32, version, ELF_T_PHDR);
00162 elf_assert(entsize);
00163 if (layout) {
00164 align(off, align_addr);
00165 rewrite(ehdr->e_phoff, off, elf->e_ehdr_flags);
00166 off += elf->e_phnum * entsize;
00167 }
00168 else {
00169 off = max(off, ehdr->e_phoff + elf->e_phnum * entsize);
00170 }
00171 }
00172 else {
00173 entsize = 0;
00174 if (layout) {
00175 rewrite(ehdr->e_phoff, 0, elf->e_ehdr_flags);
00176 }
00177 }
00178 rewrite(ehdr->e_phnum, elf->e_phnum, elf->e_ehdr_flags);
00179 rewrite(ehdr->e_phentsize, entsize, elf->e_ehdr_flags);
00180
00181 for (scn = elf->e_scn_1, shnum = 0; scn; scn = scn->s_link, ++shnum) {
00182 Elf32_Shdr *shdr = &scn->s_shdr32;
00183 size_t scn_align = 1;
00184 off_t len;
00185
00186 elf_assert(scn->s_index == shnum);
00187
00188 *flag |= scn->s_scn_flags;
00189
00190 if (scn->s_index == SHN_UNDEF) {
00191 rewrite(shdr->sh_entsize, 0, scn->s_shdr_flags);
00192 if (layout) {
00193 rewrite(shdr->sh_offset, 0, scn->s_shdr_flags);
00194 rewrite(shdr->sh_size, 0, scn->s_shdr_flags);
00195 rewrite(shdr->sh_addralign, 0, scn->s_shdr_flags);
00196 }
00197 *flag |= scn->s_shdr_flags;
00198 continue;
00199 }
00200 if (shdr->sh_type == SHT_NULL) {
00201 *flag |= scn->s_shdr_flags;
00202 continue;
00203 }
00204
00205 len = scn_data_layout(scn, version, shdr->sh_type, &scn_align, flag);
00206 if (len == -1) {
00207 return -1;
00208 }
00209
00210
00211
00212
00213 if (shdr->sh_entsize == 0) {
00214 entsize = scn_entsize(elf, version, shdr->sh_type);
00215 if (entsize > 1) {
00216 rewrite(shdr->sh_entsize, entsize, scn->s_shdr_flags);
00217 }
00218 }
00219
00220 if (layout) {
00221 align(off, scn_align);
00222 rewrite(shdr->sh_offset, off, scn->s_shdr_flags);
00223 rewrite(shdr->sh_size, (size_t)len, scn->s_shdr_flags);
00224 rewrite(shdr->sh_addralign, scn_align, scn->s_shdr_flags);
00225
00226 if (shdr->sh_type != SHT_NOBITS) {
00227 off += (size_t)len;
00228 }
00229 }
00230 else if ((size_t)len > shdr->sh_size) {
00231 seterr(ERROR_SCN2SMALL);
00232 return -1;
00233 }
00234 else {
00235 Elf_Scn *scn2;
00236 size_t end1, end2;
00237
00238 end1 = shdr->sh_offset;
00239 if (shdr->sh_type != SHT_NOBITS) {
00240 end1 += shdr->sh_size;
00241 }
00242 if (shdr->sh_offset < off) {
00243
00244
00245
00246 for (scn2 = elf->e_scn_1; scn2; scn2 = scn2->s_link) {
00247 if (scn2 == scn) {
00248 break;
00249 }
00250 end2 = scn2->s_shdr32.sh_offset;
00251 if (scn2->s_shdr32.sh_type != SHT_NOBITS) {
00252 end2 += scn2->s_shdr32.sh_size;
00253 }
00254 if (end1 > scn2->s_shdr32.sh_offset
00255 && end2 > shdr->sh_offset) {
00256 seterr(ERROR_SCN_OVERLAP);
00257 return -1;
00258 }
00259 }
00260 }
00261 if (off < end1) {
00262 off = end1;
00263 }
00264 }
00265 *flag |= scn->s_shdr_flags;
00266 }
00267
00268 if (shnum) {
00269 entsize = _fsize(ELFCLASS32, version, ELF_T_SHDR);
00270 elf_assert(entsize);
00271 if (layout) {
00272 align(off, align_addr);
00273 rewrite(ehdr->e_shoff, off, elf->e_ehdr_flags);
00274 off += shnum * entsize;
00275 }
00276 else {
00277 off = max(off, ehdr->e_shoff + shnum * entsize);
00278 }
00279 }
00280 else {
00281 entsize = 0;
00282 if (layout) {
00283 rewrite(ehdr->e_shoff, 0, elf->e_ehdr_flags);
00284 }
00285 }
00286 if (shnum >= SHN_LORESERVE) {
00287 Elf_Scn *scn = elf->e_scn_1;
00288 Elf32_Shdr *shdr = &scn->s_shdr32;
00289
00290 elf_assert(scn->s_index == 0);
00291 rewrite(shdr->sh_size, shnum, scn->s_shdr_flags);
00292 *flag |= scn->s_shdr_flags;
00293 shnum = 0;
00294 }
00295 rewrite(ehdr->e_shnum, shnum, elf->e_ehdr_flags);
00296 rewrite(ehdr->e_shentsize, entsize, elf->e_ehdr_flags);
00297
00298 rewrite(ehdr->e_ident[EI_MAG0], ELFMAG0, elf->e_ehdr_flags);
00299 rewrite(ehdr->e_ident[EI_MAG1], ELFMAG1, elf->e_ehdr_flags);
00300 rewrite(ehdr->e_ident[EI_MAG2], ELFMAG2, elf->e_ehdr_flags);
00301 rewrite(ehdr->e_ident[EI_MAG3], ELFMAG3, elf->e_ehdr_flags);
00302 rewrite(ehdr->e_ident[EI_CLASS], ELFCLASS32, elf->e_ehdr_flags);
00303 rewrite(ehdr->e_ident[EI_DATA], encoding, elf->e_ehdr_flags);
00304 rewrite(ehdr->e_ident[EI_VERSION], version, elf->e_ehdr_flags);
00305 rewrite(ehdr->e_version, version, elf->e_ehdr_flags);
00306
00307 *flag |= elf->e_ehdr_flags;
00308
00309 return off;
00310 }
00311
00312 #if __LIBELF64
00313
00314 static off_t
00315 _elf64_layout(Elf *elf, unsigned *flag) {
00316 int layout = (elf->e_elf_flags & ELF_F_LAYOUT) == 0;
00317 Elf64_Ehdr *ehdr = (Elf64_Ehdr*)elf->e_ehdr;
00318 size_t off = 0;
00319 unsigned version;
00320 unsigned encoding;
00321 size_t align_addr;
00322 size_t entsize;
00323 unsigned shnum;
00324 Elf_Scn *scn;
00325
00326 *flag = elf->e_elf_flags | elf->e_phdr_flags;
00327
00328 if ((version = ehdr->e_version) == EV_NONE) {
00329 version = EV_CURRENT;
00330 }
00331 if (!valid_version(version)) {
00332 seterr(ERROR_UNKNOWN_VERSION);
00333 return -1;
00334 }
00335 if ((encoding = ehdr->e_ident[EI_DATA]) == ELFDATANONE) {
00336 encoding = native_encoding;
00337 }
00338 if (!valid_encoding(encoding)) {
00339 seterr(ERROR_UNKNOWN_ENCODING);
00340 return -1;
00341 }
00342 entsize = _fsize(ELFCLASS64, version, ELF_T_EHDR);
00343 elf_assert(entsize);
00344 rewrite(ehdr->e_ehsize, entsize, elf->e_ehdr_flags);
00345 off = entsize;
00346
00347 align_addr = _fsize(ELFCLASS64, version, ELF_T_ADDR);
00348 elf_assert(align_addr);
00349
00350 if (elf->e_phnum) {
00351 entsize = _fsize(ELFCLASS64, version, ELF_T_PHDR);
00352 elf_assert(entsize);
00353 if (layout) {
00354 align(off, align_addr);
00355 rewrite(ehdr->e_phoff, off, elf->e_ehdr_flags);
00356 off += elf->e_phnum * entsize;
00357 }
00358 else {
00359 off = max(off, ehdr->e_phoff + elf->e_phnum * entsize);
00360 }
00361 }
00362 else {
00363 entsize = 0;
00364 if (layout) {
00365 rewrite(ehdr->e_phoff, 0, elf->e_ehdr_flags);
00366 }
00367 }
00368 rewrite(ehdr->e_phnum, elf->e_phnum, elf->e_ehdr_flags);
00369 rewrite(ehdr->e_phentsize, entsize, elf->e_ehdr_flags);
00370
00371 for (scn = elf->e_scn_1, shnum = 0; scn; scn = scn->s_link, ++shnum) {
00372 Elf64_Shdr *shdr = &scn->s_shdr64;
00373 size_t scn_align = 1;
00374 off_t len;
00375
00376 elf_assert(scn->s_index == shnum);
00377
00378 *flag |= scn->s_scn_flags;
00379
00380 if (scn->s_index == SHN_UNDEF) {
00381 rewrite(shdr->sh_entsize, 0, scn->s_shdr_flags);
00382 if (layout) {
00383 rewrite(shdr->sh_offset, 0, scn->s_shdr_flags);
00384 rewrite(shdr->sh_size, 0, scn->s_shdr_flags);
00385 rewrite(shdr->sh_addralign, 0, scn->s_shdr_flags);
00386 }
00387 *flag |= scn->s_shdr_flags;
00388 continue;
00389 }
00390 if (shdr->sh_type == SHT_NULL) {
00391 *flag |= scn->s_shdr_flags;
00392 continue;
00393 }
00394
00395 len = scn_data_layout(scn, version, shdr->sh_type, &scn_align, flag);
00396 if (len == -1) {
00397 return -1;
00398 }
00399
00400
00401
00402
00403 if (shdr->sh_entsize == 0) {
00404 entsize = scn_entsize(elf, version, shdr->sh_type);
00405 if (entsize > 1) {
00406 rewrite(shdr->sh_entsize, entsize, scn->s_shdr_flags);
00407 }
00408 }
00409
00410 if (layout) {
00411 align(off, scn_align);
00412 rewrite(shdr->sh_offset, off, scn->s_shdr_flags);
00413 rewrite(shdr->sh_size, (size_t)len, scn->s_shdr_flags);
00414 rewrite(shdr->sh_addralign, scn_align, scn->s_shdr_flags);
00415
00416 if (shdr->sh_type != SHT_NOBITS) {
00417 off += (size_t)len;
00418 }
00419 }
00420 else if ((size_t)len > shdr->sh_size) {
00421 seterr(ERROR_SCN2SMALL);
00422 return -1;
00423 }
00424 else {
00425 Elf_Scn *scn2;
00426 size_t end1, end2;
00427
00428 end1 = shdr->sh_offset;
00429 if (shdr->sh_type != SHT_NOBITS) {
00430 end1 += shdr->sh_size;
00431 }
00432 if (shdr->sh_offset < off) {
00433
00434
00435
00436 for (scn2 = elf->e_scn_1; scn2; scn2 = scn2->s_link) {
00437 if (scn2 == scn) {
00438 break;
00439 }
00440 end2 = scn2->s_shdr64.sh_offset;
00441 if (scn2->s_shdr64.sh_type != SHT_NOBITS) {
00442 end2 += scn2->s_shdr64.sh_size;
00443 }
00444 if (end1 > scn2->s_shdr64.sh_offset
00445 && end2 > shdr->sh_offset) {
00446 seterr(ERROR_SCN_OVERLAP);
00447 return -1;
00448 }
00449 }
00450 }
00451 if (off < end1) {
00452 off = end1;
00453 }
00454 }
00455 *flag |= scn->s_shdr_flags;
00456 }
00457
00458 if (shnum) {
00459 entsize = _fsize(ELFCLASS64, version, ELF_T_SHDR);
00460 elf_assert(entsize);
00461 if (layout) {
00462 align(off, align_addr);
00463 rewrite(ehdr->e_shoff, off, elf->e_ehdr_flags);
00464 off += shnum * entsize;
00465 }
00466 else {
00467 off = max(off, ehdr->e_shoff + shnum * entsize);
00468 }
00469 }
00470 else {
00471 entsize = 0;
00472 if (layout) {
00473 rewrite(ehdr->e_shoff, 0, elf->e_ehdr_flags);
00474 }
00475 }
00476 if (shnum >= SHN_LORESERVE) {
00477 Elf_Scn *scn = elf->e_scn_1;
00478 Elf64_Shdr *shdr = &scn->s_shdr64;
00479
00480 elf_assert(scn->s_index == 0);
00481 rewrite(shdr->sh_size, shnum, scn->s_shdr_flags);
00482 *flag |= scn->s_shdr_flags;
00483 shnum = 0;
00484 }
00485 rewrite(ehdr->e_shnum, shnum, elf->e_ehdr_flags);
00486 rewrite(ehdr->e_shentsize, entsize, elf->e_ehdr_flags);
00487
00488 rewrite(ehdr->e_ident[EI_MAG0], ELFMAG0, elf->e_ehdr_flags);
00489 rewrite(ehdr->e_ident[EI_MAG1], ELFMAG1, elf->e_ehdr_flags);
00490 rewrite(ehdr->e_ident[EI_MAG2], ELFMAG2, elf->e_ehdr_flags);
00491 rewrite(ehdr->e_ident[EI_MAG3], ELFMAG3, elf->e_ehdr_flags);
00492 rewrite(ehdr->e_ident[EI_CLASS], ELFCLASS64, elf->e_ehdr_flags);
00493 rewrite(ehdr->e_ident[EI_DATA], encoding, elf->e_ehdr_flags);
00494 rewrite(ehdr->e_ident[EI_VERSION], version, elf->e_ehdr_flags);
00495 rewrite(ehdr->e_version, version, elf->e_ehdr_flags);
00496
00497 *flag |= elf->e_ehdr_flags;
00498
00499 return off;
00500 }
00501
00502 #endif
00503
00504 #define ptrinside(p,a,l) ((p)>=(a)&&(p)<(a)+(l))
00505 #define newptr(p,o,n) ((p)=((p)-(o))+(n))
00506
00507 static int
00508 _elf_update_pointers(Elf *elf, char *outbuf, size_t len) {
00509 Elf_Scn *scn;
00510 Scn_Data *sd;
00511 char *data, *rawdata;
00512
00513 elf_assert(elf);
00514 elf_assert(elf->e_data);
00515 elf_assert(!elf->e_parent);
00516 elf_assert(!elf->e_unmap_data);
00517 elf_assert(elf->e_kind == ELF_K_ELF);
00518 elf_assert(len >= EI_NIDENT);
00519
00520
00521 if (len <= elf->e_dsize) {
00522
00523 data = elf->e_data;
00524 }
00525 else if ((data = (char*)realloc(elf->e_data, len))) {
00526 elf->e_dsize = len;
00527 }
00528 else {
00529 seterr(ERROR_IO_2BIG);
00530 return -1;
00531 }
00532 if (elf->e_rawdata == elf->e_data) {
00533
00534 memcpy(data, outbuf, len);
00535 elf->e_data = elf->e_rawdata = data;
00536
00537 return 0;
00538 }
00539 if (elf->e_rawdata) {
00540
00541 if (!(rawdata = (char*)realloc(elf->e_rawdata, len))) {
00542 seterr(ERROR_IO_2BIG);
00543 return -1;
00544 }
00545 memcpy(rawdata, outbuf, len);
00546 elf->e_rawdata = rawdata;
00547 }
00548 if (data == elf->e_data) {
00549
00550 return 0;
00551 }
00552
00553 if (elf->e_ehdr && !elf->e_free_ehdr) {
00554 elf_assert(ptrinside(elf->e_ehdr, elf->e_data, elf->e_dsize));
00555 newptr(elf->e_ehdr, elf->e_data, data);
00556 }
00557 if (elf->e_phdr && !elf->e_free_phdr) {
00558 elf_assert(ptrinside(elf->e_phdr, elf->e_data, elf->e_dsize));
00559 newptr(elf->e_phdr, elf->e_data, data);
00560 }
00561 for (scn = elf->e_scn_1; scn; scn = scn->s_link) {
00562 elf_assert(scn->s_magic == SCN_MAGIC);
00563 elf_assert(scn->s_elf == elf);
00564 if ((sd = scn->s_data_1)) {
00565 elf_assert(sd->sd_magic == DATA_MAGIC);
00566 elf_assert(sd->sd_scn == scn);
00567 if (sd->sd_memdata && !sd->sd_free_data) {
00568 elf_assert(ptrinside(sd->sd_memdata, elf->e_data, elf->e_dsize));
00569 if (sd->sd_data.d_buf == sd->sd_memdata) {
00570 newptr(sd->sd_memdata, elf->e_data, data);
00571 sd->sd_data.d_buf = sd->sd_memdata;
00572 }
00573 else {
00574 newptr(sd->sd_memdata, elf->e_data, data);
00575 }
00576 }
00577 }
00578 if ((sd = scn->s_rawdata)) {
00579 elf_assert(sd->sd_magic == DATA_MAGIC);
00580 elf_assert(sd->sd_scn == scn);
00581 if (sd->sd_memdata && sd->sd_free_data) {
00582 size_t off, len;
00583
00584 if (elf->e_class == ELFCLASS32) {
00585 off = scn->s_shdr32.sh_offset;
00586 len = scn->s_shdr32.sh_size;
00587 }
00588 #if __LIBELF64
00589 else if (elf->e_class == ELFCLASS64) {
00590 off = scn->s_shdr64.sh_offset;
00591 len = scn->s_shdr64.sh_size;
00592 }
00593 #endif
00594 else {
00595 seterr(ERROR_UNIMPLEMENTED);
00596 return -1;
00597 }
00598 if (!(rawdata = (char*)realloc(sd->sd_memdata, len))) {
00599 seterr(ERROR_IO_2BIG);
00600 return -1;
00601 }
00602 memcpy(rawdata, outbuf + off, len);
00603 if (sd->sd_data.d_buf == sd->sd_memdata) {
00604 sd->sd_data.d_buf = rawdata;
00605 }
00606 sd->sd_memdata = rawdata;
00607 }
00608 }
00609 }
00610 elf->e_data = data;
00611 return 0;
00612 }
00613
00614 #undef ptrinside
00615 #undef newptr
00616
00617 static off_t
00618 _elf32_write(Elf *elf, char *outbuf, size_t len) {
00619 Elf32_Ehdr *ehdr;
00620 Elf32_Shdr *shdr;
00621 Elf_Scn *scn;
00622 Scn_Data *sd;
00623 Elf_Data src;
00624 Elf_Data dst;
00625 unsigned encode;
00626
00627 elf_assert(len);
00628 elf_assert(elf->e_ehdr);
00629 ehdr = (Elf32_Ehdr*)elf->e_ehdr;
00630 encode = ehdr->e_ident[EI_DATA];
00631
00632 src.d_buf = ehdr;
00633 src.d_type = ELF_T_EHDR;
00634 src.d_size = _msize(ELFCLASS32, _elf_version, ELF_T_EHDR);
00635 src.d_version = _elf_version;
00636 dst.d_buf = outbuf;
00637 dst.d_size = ehdr->e_ehsize;
00638 dst.d_version = ehdr->e_version;
00639 if (!elf32_xlatetof(&dst, &src, encode)) {
00640 return -1;
00641 }
00642
00643 if (ehdr->e_phnum) {
00644 src.d_buf = elf->e_phdr;
00645 src.d_type = ELF_T_PHDR;
00646 src.d_size = ehdr->e_phnum * _msize(ELFCLASS32, _elf_version, ELF_T_PHDR);
00647 src.d_version = _elf_version;
00648 dst.d_buf = outbuf + ehdr->e_phoff;
00649 dst.d_size = ehdr->e_phnum * ehdr->e_phentsize;
00650 dst.d_version = ehdr->e_version;
00651 if (!elf32_xlatetof(&dst, &src, encode)) {
00652 return -1;
00653 }
00654 }
00655
00656 for (scn = elf->e_scn_1; scn; scn = scn->s_link) {
00657 elf_assert(scn->s_magic == SCN_MAGIC);
00658 elf_assert(scn->s_elf == elf);
00659
00660 src.d_buf = &scn->s_uhdr;
00661 src.d_type = ELF_T_SHDR;
00662 src.d_size = _msize(ELFCLASS32, EV_CURRENT, ELF_T_SHDR);
00663 src.d_version = EV_CURRENT;
00664 dst.d_buf = outbuf + ehdr->e_shoff + scn->s_index * ehdr->e_shentsize;
00665 dst.d_size = ehdr->e_shentsize;
00666 dst.d_version = ehdr->e_version;
00667 if (!elf32_xlatetof(&dst, &src, encode)) {
00668 return -1;
00669 }
00670
00671 if (scn->s_index == SHN_UNDEF) {
00672 continue;
00673 }
00674 shdr = &scn->s_shdr32;
00675 if (shdr->sh_type == SHT_NULL || shdr->sh_type == SHT_NOBITS) {
00676 continue;
00677 }
00678
00679 if (scn->s_data_1 && !elf_getdata(scn, NULL)) {
00680 return -1;
00681 }
00682 for (sd = scn->s_data_1; sd; sd = sd->sd_link) {
00683 elf_assert(sd->sd_magic == DATA_MAGIC);
00684 elf_assert(sd->sd_scn == scn);
00685 src = sd->sd_data;
00686 if (!src.d_size) {
00687 continue;
00688 }
00689 if (!src.d_buf) {
00690 seterr(ERROR_NULLBUF);
00691 return -1;
00692 }
00693 dst.d_buf = outbuf + shdr->sh_offset + src.d_off;
00694 dst.d_size = src.d_size;
00695 dst.d_version = ehdr->e_version;
00696 if (valid_type(src.d_type)) {
00697 size_t tmp;
00698
00699 tmp = _elf32_xltsize(&src, dst.d_version, ELFDATA2LSB, 1);
00700 if (tmp == (size_t)-1) {
00701 return -1;
00702 }
00703 dst.d_size = tmp;
00704 }
00705 else {
00706 src.d_type = ELF_T_BYTE;
00707 }
00708 if (!elf32_xlatetof(&dst, &src, encode)) {
00709 return -1;
00710 }
00711 }
00712 }
00713
00714
00715 if (elf->e_readable && _elf_update_pointers(elf, outbuf, len)) {
00716 return -1;
00717 }
00718
00719 ehdr = (Elf32_Ehdr*)elf->e_ehdr; elf_assert(ehdr);
00720 elf->e_encoding = ehdr->e_ident[EI_DATA];
00721 elf->e_version = ehdr->e_ident[EI_VERSION];
00722 elf->e_elf_flags &= ~ELF_F_DIRTY;
00723 elf->e_ehdr_flags &= ~ELF_F_DIRTY;
00724 elf->e_phdr_flags &= ~ELF_F_DIRTY;
00725 for (scn = elf->e_scn_1; scn; scn = scn->s_link) {
00726 scn->s_scn_flags &= ~ELF_F_DIRTY;
00727 scn->s_shdr_flags &= ~ELF_F_DIRTY;
00728 for (sd = scn->s_data_1; sd; sd = sd->sd_link) {
00729 sd->sd_data_flags &= ~ELF_F_DIRTY;
00730 }
00731 if (elf->e_readable) {
00732 shdr = &scn->s_shdr32;
00733 scn->s_type = shdr->sh_type;
00734 scn->s_size = shdr->sh_size;
00735 scn->s_offset = shdr->sh_offset;
00736 }
00737 }
00738 elf->e_size = len;
00739 return len;
00740 }
00741
00742 #if __LIBELF64
00743
00744 static off_t
00745 _elf64_write(Elf *elf, char *outbuf, size_t len) {
00746 Elf64_Ehdr *ehdr;
00747 Elf64_Shdr *shdr;
00748 Elf_Scn *scn;
00749 Scn_Data *sd;
00750 Elf_Data src;
00751 Elf_Data dst;
00752 unsigned encode;
00753
00754 elf_assert(len);
00755 elf_assert(elf->e_ehdr);
00756 ehdr = (Elf64_Ehdr*)elf->e_ehdr;
00757 encode = ehdr->e_ident[EI_DATA];
00758
00759 src.d_buf = ehdr;
00760 src.d_type = ELF_T_EHDR;
00761 src.d_size = _msize(ELFCLASS64, _elf_version, ELF_T_EHDR);
00762 src.d_version = _elf_version;
00763 dst.d_buf = outbuf;
00764 dst.d_size = ehdr->e_ehsize;
00765 dst.d_version = ehdr->e_version;
00766 if (!elf64_xlatetof(&dst, &src, encode)) {
00767 return -1;
00768 }
00769
00770 if (ehdr->e_phnum) {
00771 src.d_buf = elf->e_phdr;
00772 src.d_type = ELF_T_PHDR;
00773 src.d_size = ehdr->e_phnum * _msize(ELFCLASS64, _elf_version, ELF_T_PHDR);
00774 src.d_version = _elf_version;
00775 dst.d_buf = outbuf + ehdr->e_phoff;
00776 dst.d_size = ehdr->e_phnum * ehdr->e_phentsize;
00777 dst.d_version = ehdr->e_version;
00778 if (!elf64_xlatetof(&dst, &src, encode)) {
00779 return -1;
00780 }
00781 }
00782
00783 for (scn = elf->e_scn_1; scn; scn = scn->s_link) {
00784 elf_assert(scn->s_magic == SCN_MAGIC);
00785 elf_assert(scn->s_elf == elf);
00786
00787 src.d_buf = &scn->s_uhdr;
00788 src.d_type = ELF_T_SHDR;
00789 src.d_size = _msize(ELFCLASS64, EV_CURRENT, ELF_T_SHDR);
00790 src.d_version = EV_CURRENT;
00791 dst.d_buf = outbuf + ehdr->e_shoff + scn->s_index * ehdr->e_shentsize;
00792 dst.d_size = ehdr->e_shentsize;
00793 dst.d_version = ehdr->e_version;
00794 if (!elf64_xlatetof(&dst, &src, encode)) {
00795 return -1;
00796 }
00797
00798 if (scn->s_index == SHN_UNDEF) {
00799 continue;
00800 }
00801 shdr = &scn->s_shdr64;
00802 if (shdr->sh_type == SHT_NULL || shdr->sh_type == SHT_NOBITS) {
00803 continue;
00804 }
00805
00806 if (scn->s_data_1 && !elf_getdata(scn, NULL)) {
00807 return -1;
00808 }
00809 for (sd = scn->s_data_1; sd; sd = sd->sd_link) {
00810 elf_assert(sd->sd_magic == DATA_MAGIC);
00811 elf_assert(sd->sd_scn == scn);
00812 src = sd->sd_data;
00813 if (!src.d_size) {
00814 continue;
00815 }
00816 if (!src.d_buf) {
00817 seterr(ERROR_NULLBUF);
00818 return -1;
00819 }
00820 dst.d_buf = outbuf + shdr->sh_offset + src.d_off;
00821 dst.d_size = src.d_size;
00822 dst.d_version = ehdr->e_version;
00823 if (valid_type(src.d_type)) {
00824 size_t tmp;
00825
00826 tmp = _elf64_xltsize(&src, dst.d_version, ELFDATA2LSB, 1);
00827 if (tmp == (size_t)-1) {
00828 return -1;
00829 }
00830 dst.d_size = tmp;
00831 }
00832 else {
00833 src.d_type = ELF_T_BYTE;
00834 }
00835 if (!elf64_xlatetof(&dst, &src, encode)) {
00836 return -1;
00837 }
00838 }
00839 }
00840
00841
00842 if (elf->e_readable && _elf_update_pointers(elf, outbuf, len)) {
00843 return -1;
00844 }
00845
00846 ehdr = (Elf64_Ehdr*)elf->e_ehdr; elf_assert(ehdr);
00847 elf->e_encoding = ehdr->e_ident[EI_DATA];
00848 elf->e_version = ehdr->e_ident[EI_VERSION];
00849 elf->e_elf_flags &= ~ELF_F_DIRTY;
00850 elf->e_ehdr_flags &= ~ELF_F_DIRTY;
00851 elf->e_phdr_flags &= ~ELF_F_DIRTY;
00852 for (scn = elf->e_scn_1; scn; scn = scn->s_link) {
00853 scn->s_scn_flags &= ~ELF_F_DIRTY;
00854 scn->s_shdr_flags &= ~ELF_F_DIRTY;
00855 for (sd = scn->s_data_1; sd; sd = sd->sd_link) {
00856 sd->sd_data_flags &= ~ELF_F_DIRTY;
00857 }
00858 if (elf->e_readable) {
00859 shdr = &scn->s_shdr64;
00860 scn->s_type = shdr->sh_type;
00861 scn->s_size = shdr->sh_size;
00862 scn->s_offset = shdr->sh_offset;
00863 }
00864 }
00865 elf->e_size = len;
00866 return len;
00867 }
00868
00869 #endif
00870
00871 static off_t
00872 _elf_output(Elf *elf, int fd, size_t len, off_t (*_elf_write)(Elf*, char*, size_t)) {
00873 char *buf;
00874 off_t err;
00875
00876 elf_assert(len);
00877 #if HAVE_FTRUNCATE
00878 ftruncate(fd, 0);
00879 #endif
00880 #if HAVE_MMAP
00881
00882
00883
00884 #if HAVE_FTRUNCATE
00885 if (ftruncate(fd, len)) {
00886 #else
00887 {
00888 #endif
00889 if (lseek(fd, (off_t)len - 1, SEEK_SET) != (off_t)len - 1) {
00890 seterr(ERROR_IO_SEEK);
00891 return -1;
00892 }
00893 if (write(fd, "", 1) != 1) {
00894 seterr(ERROR_IO_WRITE);
00895 return -1;
00896 }
00897 }
00898 buf = (void*)mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
00899 if (buf != (char*)-1) {
00900 if ((char)_elf_fill && !(elf->e_elf_flags & ELF_F_LAYOUT)) {
00901 memset(buf, _elf_fill, len);
00902 }
00903 err = _elf_write(elf, buf, len);
00904 munmap(buf, len);
00905 return err;
00906 }
00907 #endif
00908 if (!(buf = (char*)malloc(len))) {
00909 seterr(ERROR_MEM_OUTBUF);
00910 return -1;
00911 }
00912 memset(buf, _elf_fill, len);
00913 err = _elf_write(elf, buf, len);
00914 if (err != -1 && (size_t)err == len) {
00915 if (lseek(fd, (off_t)0, SEEK_SET)) {
00916 seterr(ERROR_IO_SEEK);
00917 err = -1;
00918 }
00919 else if (write(fd, buf, len) != len) {
00920 seterr(ERROR_IO_WRITE);
00921 err = -1;
00922 }
00923 }
00924 free(buf);
00925 return err;
00926 }
00927
00928 off_t
00929 elf_update(Elf *elf, Elf_Cmd cmd) {
00930 unsigned flag;
00931 off_t len;
00932
00933 if (!elf) {
00934 return -1;
00935 }
00936 elf_assert(elf->e_magic == ELF_MAGIC);
00937 if (cmd == ELF_C_WRITE) {
00938 if (!elf->e_writable) {
00939 seterr(ERROR_RDONLY);
00940 return -1;
00941 }
00942 if (elf->e_disabled) {
00943 seterr(ERROR_FDDISABLED);
00944 return -1;
00945 }
00946 }
00947 else if (cmd != ELF_C_NULL) {
00948 seterr(ERROR_INVALID_CMD);
00949 return -1;
00950 }
00951
00952 if (!elf->e_ehdr) {
00953 seterr(ERROR_NOEHDR);
00954 }
00955 else if (elf->e_kind != ELF_K_ELF) {
00956 seterr(ERROR_NOTELF);
00957 }
00958 else if (elf->e_class == ELFCLASS32) {
00959 len = _elf32_layout(elf, &flag);
00960 if (len != -1 && cmd == ELF_C_WRITE && (flag & ELF_F_DIRTY)) {
00961 len = _elf_output(elf, elf->e_fd, (size_t)len, _elf32_write);
00962 }
00963 return len;
00964 }
00965 #if __LIBELF64
00966 else if (elf->e_class == ELFCLASS64) {
00967 len = _elf64_layout(elf, &flag);
00968 if (len != -1 && cmd == ELF_C_WRITE && (flag & ELF_F_DIRTY)) {
00969 len = _elf_output(elf, elf->e_fd, (size_t)len, _elf64_write);
00970 }
00971 return len;
00972 }
00973 #endif
00974 else if (valid_class(elf->e_class)) {
00975 seterr(ERROR_UNIMPLEMENTED);
00976 }
00977 else {
00978 seterr(ERROR_UNKNOWN_CLASS);
00979 }
00980 return -1;
00981 }