elf_update.c
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· C语言 代码 · 共 886 行 · 第 1/2 页
C
886 行
if ((rc = _libelf_resync_sections(e, rc)) < 0) return ((off_t) -1); /* * Compute the space taken up by the section header table, if * one is needed. */ if (shnum) { fsz = _libelf_fsize(ELF_T_SHDR, ec, eh_version, (size_t) 1); align = _libelf_falign(ELF_T_SHDR, ec); if (e->e_flags & ELF_F_LAYOUT) { if (rc > shoff) { LIBELF_SET_ERROR(HEADER, 0); return ((off_t) -1); } if (shoff % align) { LIBELF_SET_ERROR(LAYOUT, 0); return ((off_t) -1); } } else shoff = roundup(rc, align); rc = shoff + fsz * shnum; } else shoff = 0; /* * Set the fields of the Executable Header that could potentially use * extended numbering. */ _libelf_setphnum(e, ehdr, ec, phnum); _libelf_setshnum(e, ehdr, ec, shnum); /* * Update the `e_phoff' and `e_shoff' fields if the library is * doing the layout. */ if ((e->e_flags & ELF_F_LAYOUT) == 0) { if (ec == ELFCLASS32) { eh32->e_phoff = (uint32_t) phoff; eh32->e_shoff = (uint32_t) shoff; } else { eh64->e_phoff = (uint64_t) phoff; eh64->e_shoff = (uint64_t) shoff; } } return (rc);}/* * Write out the contents of a section. */static off_t_libelf_write_scn(Elf *e, char *nf, Elf_Scn *s, off_t rc){ int ec; size_t fsz, msz, nobjects; uint32_t sh_type; uint64_t sh_off; int elftype; Elf_Data *d, dst; if ((ec = e->e_class) == ELFCLASS32) sh_type = s->s_shdr.s_shdr32.sh_type; else sh_type = s->s_shdr.s_shdr64.sh_type; /* * Ignore sections that do not allocate space in the file. */ if (sh_type == SHT_NOBITS || sh_type == SHT_NULL) return (rc); elftype = _libelf_xlate_shtype(sh_type); assert(elftype >= ELF_T_FIRST && elftype <= ELF_T_LAST); msz = _libelf_msize(elftype, ec, e->e_version); sh_off = s->s_offset; assert(sh_off % _libelf_falign(elftype, ec) == 0); /* * If the section has a `rawdata' descriptor, and the section * contents have not been modified, use its contents directly. * The `s_rawoff' member contains the offset into the original * file, while `s_offset' contains its new location in the * destination. */ if (STAILQ_EMPTY(&s->s_data)) { if ((d = elf_rawdata(s, NULL)) == NULL) return ((off_t) -1); STAILQ_FOREACH(d, &s->s_rawdata, d_next) { if ((uint64_t) rc < sh_off + d->d_off) (void) memset(nf + rc, LIBELF_PRIVATE(fillchar), sh_off + d->d_off - rc); rc = sh_off + d->d_off; assert(d->d_buf != NULL); assert(d->d_type == ELF_T_BYTE); assert(d->d_version == e->e_version); (void) memcpy(nf + rc, e->e_rawfile + s->s_rawoff + d->d_off, d->d_size); rc += d->d_size; } return (rc); } /* * Iterate over the set of data descriptors for this section. * The prior call to _libelf_resync_elf() would have setup the * descriptors for this step. */ dst.d_version = e->e_version; STAILQ_FOREACH(d, &s->s_data, d_next) { if ((uint64_t) rc < sh_off + d->d_off) (void) memset(nf + rc, LIBELF_PRIVATE(fillchar), sh_off + d->d_off - rc); rc = sh_off + d->d_off; assert(d->d_buf != NULL); assert(d->d_type == (Elf_Type) elftype); assert(d->d_version == e->e_version); assert(d->d_size % msz == 0); nobjects = d->d_size / msz; fsz = _libelf_fsize(elftype, ec, e->e_version, nobjects); dst.d_buf = nf + rc; dst.d_size = fsz; if (_libelf_xlate(&dst, d, e->e_byteorder, ec, ELF_TOFILE) == NULL) return ((off_t) -1); rc += fsz; } return ((off_t) rc);}/* * Write out the file image. * * The original file could have been mapped in with an ELF_C_RDWR * command and the application could have added new content or * re-arranged its sections before calling elf_update(). Consequently * its not safe to work `in place' on the original file. So we * malloc() the required space for the updated ELF object and build * the object there and write it out to the underlying file at the * end. Note that the application may have opened the underlying file * in ELF_C_RDWR and only retrieved/modified a few sections. We take * care to avoid translating file sections unnecessarily. * * Gaps in the coverage of the file by the file's sections will be * filled with the fill character set by elf_fill(3). */static off_t_libelf_write_elf(Elf *e, off_t newsize){ int ec; off_t rc; size_t fsz, msz, phnum, shnum; uint64_t phoff, shoff; void *ehdr; char *newfile; Elf_Data dst, src; Elf_Scn *scn, *tscn; Elf32_Ehdr *eh32; Elf64_Ehdr *eh64; assert(e->e_kind == ELF_K_ELF); assert(e->e_cmd != ELF_C_READ); assert(e->e_fd >= 0); if ((newfile = malloc((size_t) newsize)) == NULL) { LIBELF_SET_ERROR(RESOURCE, errno); return ((off_t) -1); } ec = e->e_class; ehdr = _libelf_ehdr(e, ec, 0); assert(ehdr != NULL); phnum = e->e_u.e_elf.e_nphdr; if (ec == ELFCLASS32) { eh32 = (Elf32_Ehdr *) ehdr; phoff = (uint64_t) eh32->e_phoff; shnum = eh32->e_shnum; shoff = (uint64_t) eh32->e_shoff; } else { eh64 = (Elf64_Ehdr *) ehdr; phoff = eh64->e_phoff; shnum = eh64->e_shnum; shoff = eh64->e_shoff; } fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1); msz = _libelf_msize(ELF_T_EHDR, ec, e->e_version); (void) memset(&dst, 0, sizeof(dst)); (void) memset(&src, 0, sizeof(src)); src.d_buf = ehdr; src.d_size = msz; src.d_type = ELF_T_EHDR; src.d_version = dst.d_version = e->e_version; rc = 0; dst.d_buf = newfile + rc; dst.d_size = fsz; if (_libelf_xlate(&dst, &src, e->e_byteorder, ec, ELF_TOFILE) == NULL) goto error; rc += fsz; /* * Write the program header table if present. */ if (phnum != 0 && phoff != 0) { assert((unsigned) rc <= phoff); fsz = _libelf_fsize(ELF_T_PHDR, ec, e->e_version, phnum); assert(phoff % _libelf_falign(ELF_T_PHDR, ec) == 0); assert(fsz > 0); src.d_version = dst.d_version = e->e_version; src.d_type = ELF_T_PHDR; if (ec == ELFCLASS32) src.d_buf = e->e_u.e_elf.e_phdr.e_phdr32; else src.d_buf = e->e_u.e_elf.e_phdr.e_phdr64; src.d_size = phnum * _libelf_msize(ELF_T_PHDR, ec, e->e_version); dst.d_size = fsz; if ((uint64_t) rc < phoff) (void) memset(newfile + rc, LIBELF_PRIVATE(fillchar), phoff - rc); dst.d_buf = newfile + rc; if (_libelf_xlate(&dst, &src, e->e_byteorder, ec, ELF_TOFILE) == NULL) goto error; rc = phoff + fsz; } /* * Write out individual sections. */ STAILQ_FOREACH(scn, &e->e_u.e_elf.e_scn, s_next) if ((rc = _libelf_write_scn(e, newfile, scn, rc)) < 0) goto error; /* * Write out the section header table, if required. */ if (shnum != 0 && shoff != 0) { assert((unsigned) rc <= shoff); if ((uint64_t) rc < shoff) (void) memset(newfile + rc, LIBELF_PRIVATE(fillchar), shoff - rc); rc = shoff; assert(rc % _libelf_falign(ELF_T_SHDR, ec) == 0); src.d_type = ELF_T_SHDR; src.d_size = _libelf_msize(ELF_T_SHDR, ec, e->e_version); src.d_version = dst.d_version = e->e_version; fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1); STAILQ_FOREACH(scn, &e->e_u.e_elf.e_scn, s_next) { if (ec == ELFCLASS32) src.d_buf = &scn->s_shdr.s_shdr32; else src.d_buf = &scn->s_shdr.s_shdr64; dst.d_size = fsz; dst.d_buf = newfile + rc; if (_libelf_xlate(&dst, &src, e->e_byteorder, ec, ELF_TOFILE) != &dst) goto error; rc += fsz; } } /* */ assert(rc == newsize); /* * Write out the constructed contents and remap the file in * read-only. */ if (e->e_rawfile && munmap(e->e_rawfile, e->e_rawsize) < 0) { LIBELF_SET_ERROR(IO, errno); goto error; } if (write(e->e_fd, newfile, (size_t) newsize) != newsize || lseek(e->e_fd, (off_t) 0, SEEK_SET) < 0) { LIBELF_SET_ERROR(IO, errno); goto error; } if (e->e_cmd != ELF_C_WRITE) { if ((e->e_rawfile = mmap(NULL, (size_t) newsize, PROT_READ, MAP_PRIVATE, e->e_fd, (off_t) 0)) == MAP_FAILED) { LIBELF_SET_ERROR(IO, errno); goto error; } e->e_rawsize = newsize; } /* * Reset flags, remove existing section descriptors and * {E,P}HDR pointers so that a subsequent elf_get{e,p}hdr() * and elf_getscn() will function correctly. */ e->e_flags &= ~ELF_F_DIRTY; STAILQ_FOREACH_SAFE(scn, &e->e_u.e_elf.e_scn, s_next, tscn) _libelf_release_scn(scn); if (ec == ELFCLASS32) { free(e->e_u.e_elf.e_ehdr.e_ehdr32); if (e->e_u.e_elf.e_phdr.e_phdr32) free(e->e_u.e_elf.e_phdr.e_phdr32); e->e_u.e_elf.e_ehdr.e_ehdr32 = NULL; e->e_u.e_elf.e_phdr.e_phdr32 = NULL; } else { free(e->e_u.e_elf.e_ehdr.e_ehdr64); if (e->e_u.e_elf.e_phdr.e_phdr64) free(e->e_u.e_elf.e_phdr.e_phdr64); e->e_u.e_elf.e_ehdr.e_ehdr64 = NULL; e->e_u.e_elf.e_phdr.e_phdr64 = NULL; } return (rc); error: if (newfile) free(newfile); return ((off_t) -1);}off_telf_update(Elf *e, Elf_Cmd c){ int ec; off_t rc; rc = (off_t) -1; if (e == NULL || e->e_kind != ELF_K_ELF || (c != ELF_C_NULL && c != ELF_C_WRITE)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (rc); } if ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) { LIBELF_SET_ERROR(CLASS, 0); return (rc); } if (e->e_version == EV_NONE) e->e_version = EV_CURRENT; if (c == ELF_C_WRITE && e->e_cmd == ELF_C_READ) { LIBELF_SET_ERROR(MODE, 0); return (rc); } if ((rc = _libelf_resync_elf(e)) < 0) return (rc); if (c == ELF_C_NULL) return (rc); if (e->e_cmd == ELF_C_READ) { /* * This descriptor was opened in read-only mode or by * elf_memory(). */ if (e->e_fd) LIBELF_SET_ERROR(MODE, 0); else LIBELF_SET_ERROR(ARGUMENT, 0); return ((off_t) -1); } if (e->e_fd < 0) { LIBELF_SET_ERROR(SEQUENCE, 0); return ((off_t) -1); } return (_libelf_write_elf(e, rc));}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?