summaryrefslogtreecommitdiffstats
path: root/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c
diff options
context:
space:
mode:
Diffstat (limited to 'cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c')
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c172
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);
OpenPOWER on IntegriCloud