diff options
Diffstat (limited to 'cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c')
-rw-r--r-- | cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c | 172 |
1 files changed, 19 insertions, 153 deletions
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c index 2a43211..597fef4 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c @@ -322,7 +322,11 @@ prepare_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf64_t *dep) char *strtab; int i, j, nrel; size_t strtabsz = 1; +#if defined(sun) uint32_t count = 0; +#else + uint64_t count = 0; +#endif size_t base; Elf64_Sym *sym; Elf64_Rela *rel; @@ -418,7 +422,6 @@ prepare_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf64_t *dep) s = &dofs[dofrh->dofr_tgtsec]; for (j = 0; j < nrel; j++) { -#ifdef DOODAD #if defined(__arm__) /* XXX */ #elif defined(__mips__) @@ -431,8 +434,13 @@ prepare_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf64_t *dep) #elif defined(__i386) || defined(__amd64) rel->r_offset = s->dofs_offset + dofr[j].dofr_offset; +#if defined(sun) rel->r_info = ELF64_R_INFO(count + dep->de_global, R_AMD64_64); +#else + rel->r_info = ELF64_R_INFO(count + dep->de_global, + R_X86_64_RELATIVE); +#endif #elif defined(__sparc) rel->r_offset = s->dofs_offset + dofr[j].dofr_offset; @@ -441,7 +449,6 @@ prepare_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf64_t *dep) #else #error unknown ISA #endif -#endif sym->st_name = base + dofr[j].dofr_name - 1; sym->st_value = 0; @@ -704,7 +711,11 @@ dump_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd) shp = &elf_file.shdr[ESHDR_DOF]; shp->sh_name = 11; /* DTRACE_SHSTRTAB64[11] = ".SUNW_dof" */ +#if defined(sun) shp->sh_flags = SHF_ALLOC; +#else + shp->sh_flags = SHF_WRITE | SHF_ALLOC; +#endif shp->sh_type = SHT_SUNW_dof; shp->sh_offset = off; shp->sh_size = dof->dofh_filesz; @@ -1662,19 +1673,6 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags, { #if !defined(sun) char tfile[PATH_MAX]; - Elf *e; - Elf_Scn *scn; - Elf_Data *data; - GElf_Shdr shdr; - int efd; - size_t stridx; - unsigned char *buf; - char *s; - int loc; - GElf_Ehdr ehdr; - Elf_Scn *scn0; - GElf_Shdr shdr0; - uint64_t off, rc; #endif char drti[PATH_MAX]; dof_hdr_t *dof; @@ -1810,21 +1808,21 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags, (void) unlink(file); #endif -#if defined(sun) if (dtp->dt_oflags & DTRACE_O_LP64) status = dump_elf64(dtp, dof, fd); else status = dump_elf32(dtp, dof, fd); +#if defined(sun) if (status != 0 || lseek(fd, 0, SEEK_SET) != 0) { return (dt_link_error(dtp, NULL, -1, NULL, "failed to write %s: %s", file, strerror(errno))); } #else - /* We don't write the ELF header, just the DOF section */ - if (dt_write(dtp, fd, dof, dof->dofh_filesz) < dof->dofh_filesz) + if (status != 0) return (dt_link_error(dtp, NULL, -1, NULL, - "failed to write %s: %s", tfile, strerror(errno))); + "failed to write %s: %s", tfile, + strerror(dtrace_errno(dtp)))); #endif if (!dtp->dt_lazyload) { @@ -1846,7 +1844,7 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags, (void) snprintf(cmd, len, fmt, dtp->dt_ld_path, file, fd, drti); #else - const char *fmt = "%s -o %s -r %s"; + const char *fmt = "%s -o %s -r %s %s"; #if defined(__amd64__) /* @@ -1868,10 +1866,9 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags, len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file, tfile, drti) + 1; - len *= 2; cmd = alloca(len); - (void) snprintf(cmd, len, fmt, dtp->dt_ld_path, file, + (void) snprintf(cmd, len, fmt, dtp->dt_ld_path, file, tfile, drti); #endif if ((status = system(cmd)) == -1) { @@ -1894,137 +1891,6 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags, file, dtp->dt_ld_path, WEXITSTATUS(status)); goto done; } -#if !defined(sun) -#define BROKEN_LIBELF - /* - * FreeBSD's ld(1) is not instructed to interpret and add - * correctly the SUNW_dof section present in tfile. - * We use libelf to add this section manually and hope the next - * ld invocation won't remove it. - */ - elf_version(EV_CURRENT); - if ((efd = open(file, O_RDWR, 0)) < 0) { - ret = dt_link_error(dtp, NULL, -1, NULL, - "failed to open file %s: %s", - file, strerror(errno)); - goto done; - } - if ((e = elf_begin(efd, ELF_C_RDWR, NULL)) == NULL) { - close(efd); - ret = dt_link_error(dtp, NULL, -1, NULL, - "failed to open elf file: %s", - elf_errmsg(elf_errno())); - goto done; - } - /* - * Add the string '.SUWN_dof' to the shstrtab section. - */ -#ifdef BROKEN_LIBELF - elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT); -#endif - elf_getshdrstrndx(e, &stridx); - scn = elf_getscn(e, stridx); - gelf_getshdr(scn, &shdr); - data = elf_newdata(scn); - data->d_off = shdr.sh_size; - data->d_buf = ".SUNW_dof"; - data->d_size = 10; - data->d_type = ELF_T_BYTE; - loc = shdr.sh_size; - shdr.sh_size += data->d_size; - gelf_update_shdr(scn, &shdr); -#ifdef BROKEN_LIBELF - off = shdr.sh_offset; - rc = shdr.sh_offset + shdr.sh_size; - gelf_getehdr(e, &ehdr); - if (ehdr.e_shoff > off) { - off = ehdr.e_shoff + ehdr.e_shnum * ehdr.e_shentsize; - rc = roundup(rc, 8); - ehdr.e_shoff = rc; - gelf_update_ehdr(e, &ehdr); - rc += ehdr.e_shnum * ehdr.e_shentsize; - } - for (;;) { - scn0 = NULL; - scn = NULL; - while ((scn = elf_nextscn(e, scn)) != NULL) { - gelf_getshdr(scn, &shdr); - if (shdr.sh_type == SHT_NOBITS || - shdr.sh_offset < off) - continue; - /* Find the immediately adjcent section. */ - if (scn0 == NULL || - shdr.sh_offset < shdr0.sh_offset) { - scn0 = scn; - gelf_getshdr(scn0, &shdr0); - } - } - if (scn0 == NULL) - break; - /* Load section data to work around another bug */ - elf_getdata(scn0, NULL); - /* Update section header, assure section alignment */ - off = shdr0.sh_offset + shdr0.sh_size; - rc = roundup(rc, shdr0.sh_addralign); - shdr0.sh_offset = rc; - gelf_update_shdr(scn0, &shdr0); - rc += shdr0.sh_size; - } - if (elf_update(e, ELF_C_WRITE) < 0) { - ret = dt_link_error(dtp, NULL, -1, NULL, - "failed to add append the shstrtab section: %s", - elf_errmsg(elf_errno())); - elf_end(e); - close(efd); - goto done; - } - elf_end(e); - e = elf_begin(efd, ELF_C_RDWR, NULL); -#endif - /* - * Construct the .SUNW_dof section. - */ - scn = elf_newscn(e); - data = elf_newdata(scn); - buf = mmap(NULL, dof->dofh_filesz, PROT_READ, MAP_SHARED, - fd, 0); - if (buf == MAP_FAILED) { - ret = dt_link_error(dtp, NULL, -1, NULL, - "failed to mmap buffer %s", strerror(errno)); - elf_end(e); - close(efd); - goto done; - } - data->d_buf = buf; - data->d_align = 4; - data->d_size = dof->dofh_filesz; - data->d_version = EV_CURRENT; - gelf_getshdr(scn, &shdr); - shdr.sh_name = loc; - shdr.sh_flags = SHF_ALLOC; - /* - * Actually this should be SHT_SUNW_dof, but FreeBSD's ld(1) - * will remove this 'unknown' section when we try to create an - * executable using the object we are modifying, so we stop - * playing by the rules and use SHT_PROGBITS. - * Also, note that our drti has modifications to handle this. - */ - shdr.sh_type = SHT_PROGBITS; - shdr.sh_addralign = 4; - gelf_update_shdr(scn, &shdr); - if (elf_update(e, ELF_C_WRITE) < 0) { - ret = dt_link_error(dtp, NULL, -1, NULL, - "failed to add the SUNW_dof section: %s", - elf_errmsg(elf_errno())); - munmap(buf, dof->dofh_filesz); - elf_end(e); - close(efd); - goto done; - } - munmap(buf, dof->dofh_filesz); - elf_end(e); - close(efd); -#endif (void) close(fd); /* release temporary file */ } else { (void) close(fd); |