📄 update.c
字号:
rewrite(ehdr->e_ident[EI_MAG1], ELFMAG1, elf->e_ehdr_flags); rewrite(ehdr->e_ident[EI_MAG2], ELFMAG2, elf->e_ehdr_flags); rewrite(ehdr->e_ident[EI_MAG3], ELFMAG3, elf->e_ehdr_flags); rewrite(ehdr->e_ident[EI_CLASS], ELFCLASS64, elf->e_ehdr_flags); rewrite(ehdr->e_ident[EI_DATA], encoding, elf->e_ehdr_flags); rewrite(ehdr->e_ident[EI_VERSION], version, elf->e_ehdr_flags); rewrite(ehdr->e_version, version, elf->e_ehdr_flags); *flag |= elf->e_ehdr_flags; return off;}#endif /* __LIBELF64 */#define ptrinside(p,a,l) ((p)>=(a)&&(p)<(a)+(l))#define newptr(p,o,n) ((p)=((p)-(o))+(n))static int_elf_update_pointers(Elf *elf, char *outbuf, size_t len) { Elf_Scn *scn; Scn_Data *sd; char *data, *rawdata; elf_assert(elf); elf_assert(elf->e_data); elf_assert(!elf->e_parent); elf_assert(!elf->e_unmap_data); elf_assert(elf->e_kind == ELF_K_ELF); elf_assert(len >= EI_NIDENT); /* resize memory images */ if (len <= elf->e_dsize) { /* don't shorten the memory image */ data = elf->e_data; } else if ((data = (char*)realloc(elf->e_data, len))) { elf->e_dsize = len; } else { seterr(ERROR_IO_2BIG); return -1; } if (elf->e_rawdata == elf->e_data) { /* update frozen raw image */ memcpy(data, outbuf, len); elf->e_data = elf->e_rawdata = data; /* cooked data is stored outside the raw image */ return 0; } if (elf->e_rawdata) { /* update raw image */ if (!(rawdata = (char*)realloc(elf->e_rawdata, len))) { seterr(ERROR_IO_2BIG); return -1; } memcpy(rawdata, outbuf, len); elf->e_rawdata = rawdata; } if (data == elf->e_data) { /* nothing more to do */ return 0; } /* adjust internal pointers */ for (scn = elf->e_scn_1; scn; scn = scn->s_link) { elf_assert(scn->s_magic == SCN_MAGIC); elf_assert(scn->s_elf == elf); if ((sd = scn->s_data_1)) { elf_assert(sd->sd_magic == DATA_MAGIC); elf_assert(sd->sd_scn == scn); if (sd->sd_memdata && !sd->sd_free_data) { elf_assert(ptrinside(sd->sd_memdata, elf->e_data, elf->e_dsize)); if (sd->sd_data.d_buf == sd->sd_memdata) { newptr(sd->sd_memdata, elf->e_data, data); sd->sd_data.d_buf = sd->sd_memdata; } else { newptr(sd->sd_memdata, elf->e_data, data); } } } if ((sd = scn->s_rawdata)) { elf_assert(sd->sd_magic == DATA_MAGIC); elf_assert(sd->sd_scn == scn); if (sd->sd_memdata && sd->sd_free_data) { size_t off, len; if (elf->e_class == ELFCLASS32) { off = scn->s_shdr32.sh_offset; len = scn->s_shdr32.sh_size; }#if __LIBELF64 else if (elf->e_class == ELFCLASS64) { off = scn->s_shdr64.sh_offset; len = scn->s_shdr64.sh_size; }#endif /* __LIBELF64 */ else { seterr(ERROR_UNIMPLEMENTED); return -1; } if (!(rawdata = (char*)realloc(sd->sd_memdata, len))) { seterr(ERROR_IO_2BIG); return -1; } memcpy(rawdata, outbuf + off, len); if (sd->sd_data.d_buf == sd->sd_memdata) { sd->sd_data.d_buf = rawdata; } sd->sd_memdata = rawdata; } } } elf->e_data = data; return 0;}#undef ptrinside#undef newptrstatic off_t_elf32_write(Elf *elf, char *outbuf, size_t len) { Elf32_Ehdr *ehdr; Elf32_Shdr *shdr; Elf_Scn *scn; Scn_Data *sd; Elf_Data src; Elf_Data dst; unsigned encode; elf_assert(len); elf_assert(elf->e_ehdr); ehdr = (Elf32_Ehdr*)elf->e_ehdr; encode = ehdr->e_ident[EI_DATA]; src.d_buf = ehdr; src.d_type = ELF_T_EHDR; src.d_size = _msize(ELFCLASS32, _elf_version, ELF_T_EHDR); src.d_version = _elf_version; dst.d_buf = outbuf; dst.d_size = ehdr->e_ehsize; dst.d_version = ehdr->e_version; if (!elf32_xlatetof(&dst, &src, encode)) { return -1; } if (elf->e_phnum) { src.d_buf = elf->e_phdr; src.d_type = ELF_T_PHDR; src.d_size = elf->e_phnum * _msize(ELFCLASS32, _elf_version, ELF_T_PHDR); src.d_version = _elf_version; dst.d_buf = outbuf + ehdr->e_phoff; dst.d_size = elf->e_phnum * ehdr->e_phentsize; dst.d_version = ehdr->e_version; if (!elf32_xlatetof(&dst, &src, encode)) { return -1; } } for (scn = elf->e_scn_1; scn; scn = scn->s_link) { elf_assert(scn->s_magic == SCN_MAGIC); elf_assert(scn->s_elf == elf); src.d_buf = &scn->s_uhdr; src.d_type = ELF_T_SHDR; src.d_size = _msize(ELFCLASS32, EV_CURRENT, ELF_T_SHDR); src.d_version = EV_CURRENT; dst.d_buf = outbuf + ehdr->e_shoff + scn->s_index * ehdr->e_shentsize; dst.d_size = ehdr->e_shentsize; dst.d_version = ehdr->e_version; if (!elf32_xlatetof(&dst, &src, encode)) { return -1; } if (scn->s_index == SHN_UNDEF) { continue; } shdr = &scn->s_shdr32; if (shdr->sh_type == SHT_NULL || shdr->sh_type == SHT_NOBITS) { continue; } /* XXX: this is probably no longer necessary */ if (scn->s_data_1 && !elf_getdata(scn, NULL)) { return -1; } for (sd = scn->s_data_1; sd; sd = sd->sd_link) { elf_assert(sd->sd_magic == DATA_MAGIC); elf_assert(sd->sd_scn == scn); src = sd->sd_data; if (!src.d_size) { continue; } if (!src.d_buf) { seterr(ERROR_NULLBUF); return -1; } dst.d_buf = outbuf + shdr->sh_offset + src.d_off; dst.d_size = src.d_size; dst.d_version = ehdr->e_version; if (valid_type(src.d_type)) { size_t tmp; tmp = _elf32_xltsize(&src, dst.d_version, ELFDATA2LSB, 1); if (tmp == (size_t)-1) { return -1; } dst.d_size = tmp; } else { src.d_type = ELF_T_BYTE; } if (!elf32_xlatetof(&dst, &src, encode)) { return -1; } } } /* cleanup */ if (elf->e_readable && _elf_update_pointers(elf, outbuf, len)) { return -1; } /* NOTE: ehdr is no longer valid! */ ehdr = (Elf32_Ehdr*)elf->e_ehdr; elf_assert(ehdr); elf->e_encoding = ehdr->e_ident[EI_DATA]; elf->e_version = ehdr->e_ident[EI_VERSION]; elf->e_elf_flags &= ~ELF_F_DIRTY; elf->e_ehdr_flags &= ~ELF_F_DIRTY; elf->e_phdr_flags &= ~ELF_F_DIRTY; for (scn = elf->e_scn_1; scn; scn = scn->s_link) { scn->s_scn_flags &= ~ELF_F_DIRTY; scn->s_shdr_flags &= ~ELF_F_DIRTY; for (sd = scn->s_data_1; sd; sd = sd->sd_link) { sd->sd_data_flags &= ~ELF_F_DIRTY; } if (elf->e_readable) { shdr = &scn->s_shdr32; scn->s_type = shdr->sh_type; scn->s_size = shdr->sh_size; scn->s_offset = shdr->sh_offset; } } elf->e_size = len; return len;}#if __LIBELF64static off_t_elf64_write(Elf *elf, char *outbuf, size_t len) { Elf64_Ehdr *ehdr; Elf64_Shdr *shdr; Elf_Scn *scn; Scn_Data *sd; Elf_Data src; Elf_Data dst; unsigned encode; elf_assert(len); elf_assert(elf->e_ehdr); ehdr = (Elf64_Ehdr*)elf->e_ehdr; encode = ehdr->e_ident[EI_DATA]; src.d_buf = ehdr; src.d_type = ELF_T_EHDR; src.d_size = _msize(ELFCLASS64, _elf_version, ELF_T_EHDR); src.d_version = _elf_version; dst.d_buf = outbuf; dst.d_size = ehdr->e_ehsize; dst.d_version = ehdr->e_version; if (!elf64_xlatetof(&dst, &src, encode)) { return -1; } if (elf->e_phnum) { src.d_buf = elf->e_phdr; src.d_type = ELF_T_PHDR; src.d_size = elf->e_phnum * _msize(ELFCLASS64, _elf_version, ELF_T_PHDR); src.d_version = _elf_version; dst.d_buf = outbuf + ehdr->e_phoff; dst.d_size = elf->e_phnum * ehdr->e_phentsize; dst.d_version = ehdr->e_version; if (!elf64_xlatetof(&dst, &src, encode)) { return -1; } } for (scn = elf->e_scn_1; scn; scn = scn->s_link) { elf_assert(scn->s_magic == SCN_MAGIC); elf_assert(scn->s_elf == elf); src.d_buf = &scn->s_uhdr; src.d_type = ELF_T_SHDR; src.d_size = _msize(ELFCLASS64, EV_CURRENT, ELF_T_SHDR); src.d_version = EV_CURRENT; dst.d_buf = outbuf + ehdr->e_shoff + scn->s_index * ehdr->e_shentsize; dst.d_size = ehdr->e_shentsize; dst.d_version = ehdr->e_version; if (!elf64_xlatetof(&dst, &src, encode)) { return -1; } if (scn->s_index == SHN_UNDEF) { continue; } shdr = &scn->s_shdr64; if (shdr->sh_type == SHT_NULL || shdr->sh_type == SHT_NOBITS) { continue; } /* XXX: this is probably no longer necessary */ if (scn->s_data_1 && !elf_getdata(scn, NULL)) { return -1; } for (sd = scn->s_data_1; sd; sd = sd->sd_link) { elf_assert(sd->sd_magic == DATA_MAGIC); elf_assert(sd->sd_scn == scn); src = sd->sd_data; if (!src.d_size) { continue; } if (!src.d_buf) { seterr(ERROR_NULLBUF); return -1; } dst.d_buf = outbuf + shdr->sh_offset + src.d_off; dst.d_size = src.d_size; dst.d_version = ehdr->e_version; if (valid_type(src.d_type)) { size_t tmp; tmp = _elf64_xltsize(&src, dst.d_version, ELFDATA2LSB, 1); if (tmp == (size_t)-1) { return -1; } dst.d_size = tmp; } else { src.d_type = ELF_T_BYTE; } if (!elf64_xlatetof(&dst, &src, encode)) { return -1; } } } /* cleanup */ if (elf->e_readable && _elf_update_pointers(elf, outbuf, len)) { return -1; } /* NOTE: ehdr is no longer valid! */ ehdr = (Elf64_Ehdr*)elf->e_ehdr; elf_assert(ehdr); elf->e_encoding = ehdr->e_ident[EI_DATA]; elf->e_version = ehdr->e_ident[EI_VERSION]; elf->e_elf_flags &= ~ELF_F_DIRTY; elf->e_ehdr_flags &= ~ELF_F_DIRTY; elf->e_phdr_flags &= ~ELF_F_DIRTY; for (scn = elf->e_scn_1; scn; scn = scn->s_link) { scn->s_scn_flags &= ~ELF_F_DIRTY; scn->s_shdr_flags &= ~ELF_F_DIRTY; for (sd = scn->s_data_1; sd; sd = sd->sd_link) { sd->sd_data_flags &= ~ELF_F_DIRTY; } if (elf->e_readable) { shdr = &scn->s_shdr64; scn->s_type = shdr->sh_type; scn->s_size = shdr->sh_size; scn->s_offset = shdr->sh_offset; } } elf->e_size = len; return len;}#endif /* __LIBELF64 */static intxwrite(int fd, char *buffer, size_t len) { size_t done = 0; size_t n; while (done < len) { n = write(fd, buffer + done, len - done); if (n == 0) { /* file system full */ return -1; } else if (n != (size_t)-1) { /* some bytes written, continue */ done += n; } else if (errno != EAGAIN && errno != EINTR) { /* real error */ return -1; } } return 0;}static off_t_elf_output(Elf *elf, int fd, size_t len, off_t (*_elf_write)(Elf*, char*, size_t)) { char *buf; off_t err; elf_assert(len);#if HAVE_FTRUNCATE ftruncate(fd, 0);#endif /* HAVE_FTRUNCATE */#if HAVE_MMAP /* * Make sure the file is (at least) len bytes long */#if HAVE_FTRUNCATE lseek(fd, (off_t)len, SEEK_SET); if (ftruncate(fd, len)) {#else /* HAVE_FTRUNCATE */ {#endif /* HAVE_FTRUNCATE */ if (lseek(fd, (off_t)len - 1, SEEK_SET) != (off_t)len - 1) { seterr(ERROR_IO_SEEK); return -1; } if (xwrite(fd, "", 1)) { seterr(ERROR_IO_WRITE); return -1; } } buf = (void*)mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (buf != (char*)-1) { if ((char)_elf_fill && !(elf->e_elf_flags & ELF_F_LAYOUT)) { memset(buf, _elf_fill, len); } err = _elf_write(elf, buf, len); munmap(buf, len); return err; }#endif /* HAVE_MMAP */ if (!(buf = (char*)malloc(len))) { seterr(ERROR_MEM_OUTBUF); return -1; } memset(buf, _elf_fill, len); err = _elf_write(elf, buf, len); if (err != -1 && (size_t)err == len) { if (lseek(fd, (off_t)0, SEEK_SET)) { seterr(ERROR_IO_SEEK); err = -1; } else if (xwrite(fd, buf, len)) { seterr(ERROR_IO_WRITE); err = -1; } } free(buf); return err;}off_telf_update(Elf *elf, Elf_Cmd cmd) { unsigned flag; off_t len; if (!elf) { return -1; } elf_assert(elf->e_magic == ELF_MAGIC); if (cmd == ELF_C_WRITE) { if (!elf->e_writable) { seterr(ERROR_RDONLY); return -1; } if (elf->e_disabled) { seterr(ERROR_FDDISABLED); return -1; } } else if (cmd != ELF_C_NULL) { seterr(ERROR_INVALID_CMD); return -1; } if (!elf->e_ehdr) { seterr(ERROR_NOEHDR); } else if (elf->e_kind != ELF_K_ELF) { seterr(ERROR_NOTELF); } else if (elf->e_class == ELFCLASS32) { len = _elf32_layout(elf, &flag); if (len != -1 && cmd == ELF_C_WRITE && (flag & ELF_F_DIRTY)) { len = _elf_output(elf, elf->e_fd, (size_t)len, _elf32_write); } return len; }#if __LIBELF64 else if (elf->e_class == ELFCLASS64) { len = _elf64_layout(elf, &flag); if (len != -1 && cmd == ELF_C_WRITE && (flag & ELF_F_DIRTY)) { len = _elf_output(elf, elf->e_fd, (size_t)len, _elf64_write); } return len; }#endif /* __LIBELF64 */ else if (valid_class(elf->e_class)) { seterr(ERROR_UNIMPLEMENTED); } else { seterr(ERROR_UNKNOWN_CLASS); } return -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -