aboutsummaryrefslogtreecommitdiff
path: root/cddl
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2015-02-18 03:54:54 +0000
committerMark Johnston <markj@FreeBSD.org>2015-02-18 03:54:54 +0000
commit03a5f9f0fdb9927663c465c37848ad116e39e203 (patch)
tree5ef309e19daa5a505406b7f2926c31f722790437 /cddl
parent70f82314c23d902626bc71fa6881df2961e11753 (diff)
downloadsrc-03a5f9f0fdb9927663c465c37848ad116e39e203.tar.gz
src-03a5f9f0fdb9927663c465c37848ad116e39e203.zip
Remove drti.o's dependency on libelf. This makes it possible to add DTrace
probes to userland programs and libraries without also needing to link libelf. dtrace -G places the __SUNW_dof symbol at the beginning of the DOF (DTrace probe and provider metdata) section in the generated object file; drti.o now just uses this symbol to locate the section. A complication occurs when multiple dtrace-generated object files are linked together, since the __SUNW_dof symbol defined in each file is global. This is handled by using objcopy(1) to convert __SUNW_dof to a local symbol once drti.o has been linked with the generated object file. Upstream, this is done using a linker feature not present in GNU ld. Differential Revision: https://reviews.freebsd.org/D1757 Reviewed by: rpaulo MFC after: 1 month Relnotes: yes
Notes
Notes: svn path=/head/; revision=278934
Diffstat (limited to 'cddl')
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/drti.c65
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h3
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c55
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c10
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c25
5 files changed, 86 insertions, 72 deletions
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c b/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c
index fdfe416804fc..a75dc02d5ad9 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c
@@ -36,7 +36,6 @@
#include <string.h>
#include <errno.h>
#include <libelf.h>
-#include <gelf.h>
/*
* In Solaris 10 GA, the only mechanism for communicating helper information
@@ -62,9 +61,7 @@ static const char *olddevname = "/devices/pseudo/dtrace@0:helper";
static const char *modname; /* Name of this load object */
static int gen; /* DOF helper generation */
-#ifdef illumos
extern dof_hdr_t __SUNW_dof; /* DOF defined in the .SUNW_dof section */
-#endif
static boolean_t dof_init_debug = B_FALSE; /* From DTRACE_DOF_INIT_DEBUG */
static void
@@ -99,11 +96,7 @@ static void dtrace_dof_init(void) __attribute__ ((constructor));
static void
dtrace_dof_init(void)
{
-#ifdef illumos
dof_hdr_t *dof = &__SUNW_dof;
-#else
- dof_hdr_t *dof = NULL;
-#endif
#ifdef _LP64
Elf64_Ehdr *elf;
#else
@@ -118,17 +111,6 @@ dtrace_dof_init(void)
#endif
int fd;
const char *p;
-#ifndef illumos
- Elf *e;
- Elf_Scn *scn = NULL;
- Elf_Data *dofdata = NULL;
- dof_hdr_t *dof_next = NULL;
- GElf_Shdr shdr;
- int efd;
- char *s;
- size_t shstridx;
- uint64_t aligned_filesz;
-#endif
if (getenv("DTRACE_DOF_INIT_DISABLE") != NULL)
return;
@@ -152,42 +134,6 @@ dtrace_dof_init(void)
modname = lmp->l_name;
else
modname++;
-#ifndef illumos
- elf_version(EV_CURRENT);
- if ((efd = open(lmp->l_name, O_RDONLY, 0)) < 0) {
- dprintf(1, "couldn't open file for reading\n");
- return;
- }
- if ((e = elf_begin(efd, ELF_C_READ, NULL)) == NULL) {
- dprintf(1, "elf_begin failed\n");
- close(efd);
- return;
- }
- elf_getshdrstrndx(e, &shstridx);
- dof = NULL;
- while ((scn = elf_nextscn(e, scn)) != NULL) {
- gelf_getshdr(scn, &shdr);
- if (shdr.sh_type == SHT_SUNW_dof) {
- s = elf_strptr(e, shstridx, shdr.sh_name);
- if (s != NULL && strcmp(s, ".SUNW_dof") == 0) {
- dofdata = elf_getdata(scn, NULL);
- dof = dofdata->d_buf;
- break;
- }
- }
- }
- if (dof == NULL) {
- dprintf(1, "SUNW_dof section not found\n");
- elf_end(e);
- close(efd);
- return;
- }
-
- while ((char *) dof < (char *) dofdata->d_buf + dofdata->d_size) {
- aligned_filesz = (shdr.sh_addralign == 0 ? dof->dofh_filesz :
- roundup2(dof->dofh_filesz, shdr.sh_addralign));
- dof_next = (void *) ((char *) dof + aligned_filesz);
-#endif
if (dof->dofh_ident[DOF_ID_MAG0] != DOF_MAG_MAG0 ||
dof->dofh_ident[DOF_ID_MAG1] != DOF_MAG_MAG1 ||
@@ -237,21 +183,12 @@ dtrace_dof_init(void)
dprintf(1, "DTrace ioctl failed for DOF at %p", dof);
else {
dprintf(1, "DTrace ioctl succeeded for DOF at %p\n", dof);
-#ifndef illumos
+#ifdef __FreeBSD__
gen = dh.gen;
#endif
}
(void) close(fd);
-
-#ifndef illumos
- /* End of while loop */
- dof = dof_next;
- }
-
- elf_end(e);
- (void) close(efd);
-#endif
}
#ifdef illumos
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h
index c9e8e20d0b71..51bed72556d0 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h
@@ -275,6 +275,9 @@ struct dtrace_hdl {
int dt_cpp_argc; /* count of initialized cpp(1) arguments */
int dt_cpp_args; /* size of dt_cpp_argv[] array */
char *dt_ld_path; /* pathname of ld(1) to invoke if needed */
+#ifdef __FreeBSD__
+ char *dt_objcopy_path; /* pathname of objcopy(1) to invoke if needed */
+#endif
dt_list_t dt_lib_path; /* linked-list forming library search path */
uint_t dt_lazyload; /* boolean: set via -xlazyload */
uint_t dt_droptags; /* boolean: set via -xdroptags */
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c
index 3991714086a7..ae41269afa16 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c
@@ -281,7 +281,11 @@ printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
sym->st_value = 0;
sym->st_size = dof->dofh_filesz;
sym->st_info = ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT);
+#ifdef illumos
sym->st_other = 0;
+#else
+ sym->st_other = ELF32_ST_VISIBILITY(STV_HIDDEN);
+#endif
sym->st_shndx = ESHDR_DOF;
sym++;
@@ -471,7 +475,11 @@ prepare_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf64_t *dep)
sym->st_value = 0;
sym->st_size = dof->dofh_filesz;
sym->st_info = GELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
+#ifdef illumos
sym->st_other = 0;
+#else
+ sym->st_other = ELF64_ST_VISIBILITY(STV_HIDDEN);
+#endif
sym->st_shndx = ESHDR_DOF;
sym++;
@@ -711,11 +719,7 @@ 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" */
-#ifdef illumos
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;
@@ -1874,7 +1878,7 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
#endif
(void) snprintf(drti, sizeof (drti), "/usr/lib%s/dtrace/drti.o",
- use_32 ? "32":"");
+ use_32 ? "32" : "");
len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file, tfile,
drti) + 1;
@@ -1885,26 +1889,61 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
drti);
#endif
if ((status = system(cmd)) == -1) {
- ret = dt_link_error(dtp, NULL, -1, NULL,
+ ret = dt_link_error(dtp, NULL, fd, NULL,
"failed to run %s: %s", dtp->dt_ld_path,
strerror(errno));
goto done;
}
if (WIFSIGNALED(status)) {
- ret = dt_link_error(dtp, NULL, -1, NULL,
+ ret = dt_link_error(dtp, NULL, fd, NULL,
"failed to link %s: %s failed due to signal %d",
file, dtp->dt_ld_path, WTERMSIG(status));
goto done;
}
if (WEXITSTATUS(status) != 0) {
- ret = dt_link_error(dtp, NULL, -1, NULL,
+ ret = dt_link_error(dtp, NULL, fd, NULL,
"failed to link %s: %s exited with status %d\n",
file, dtp->dt_ld_path, WEXITSTATUS(status));
goto done;
}
(void) close(fd); /* release temporary file */
+
+#ifdef __FreeBSD__
+ /*
+ * Now that we've linked drti.o, reduce the global __SUNW_dof
+ * symbol to a local symbol. This is needed to so that multiple
+ * generated object files (for different providers, for
+ * instance) can be linked together. This is accomplished using
+ * the -Blocal flag with Sun's linker, but GNU ld doesn't appear
+ * to have an equivalent option.
+ */
+ asprintf(&cmd, "%s --localize-hidden %s", dtp->dt_objcopy_path,
+ file);
+ if ((status = system(cmd)) == -1) {
+ ret = dt_link_error(dtp, NULL, -1, NULL,
+ "failed to run %s: %s", dtp->dt_objcopy_path,
+ strerror(errno));
+ free(cmd);
+ goto done;
+ }
+ free(cmd);
+
+ if (WIFSIGNALED(status)) {
+ ret = dt_link_error(dtp, NULL, -1, NULL,
+ "failed to link %s: %s failed due to signal %d",
+ file, dtp->dt_objcopy_path, WTERMSIG(status));
+ goto done;
+ }
+
+ if (WEXITSTATUS(status) != 0) {
+ ret = dt_link_error(dtp, NULL, -1, NULL,
+ "failed to link %s: %s exited with status %d\n",
+ file, dtp->dt_objcopy_path, WEXITSTATUS(status));
+ goto done;
+ }
+#endif
} else {
(void) close(fd);
}
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
index b8b146732a89..c95224373bcd 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
@@ -785,6 +785,7 @@ const char *_dtrace_defld = "/usr/ccs/bin/ld"; /* default ld(1) to invoke */
#else
const char *_dtrace_defcpp = "cpp"; /* default cpp(1) to invoke */
const char *_dtrace_defld = "ld"; /* default ld(1) to invoke */
+const char *_dtrace_defobjcopy = "objcopy"; /* default objcopy(1) to invoke */
#endif
const char *_dtrace_libdir = "/usr/lib/dtrace"; /* default library directory */
@@ -1185,6 +1186,9 @@ alloc:
dtp->dt_cpp_argc = 1;
dtp->dt_cpp_args = 1;
dtp->dt_ld_path = strdup(_dtrace_defld);
+#ifdef __FreeBSD__
+ dtp->dt_objcopy_path = strdup(_dtrace_defobjcopy);
+#endif
dtp->dt_provmod = provmod;
dtp->dt_vector = vector;
dtp->dt_varg = arg;
@@ -1193,6 +1197,9 @@ alloc:
if (dtp->dt_mods == NULL || dtp->dt_provs == NULL ||
dtp->dt_procs == NULL || dtp->dt_ld_path == NULL ||
+#ifdef __FreeBSD__
+ dtp->dt_objcopy_path == NULL ||
+#endif
dtp->dt_cpp_path == NULL || dtp->dt_cpp_argv == NULL)
return (set_open_errno(dtp, errp, EDT_NOMEM));
@@ -1673,6 +1680,9 @@ dtrace_close(dtrace_hdl_t *dtp)
free(dtp->dt_cpp_argv);
free(dtp->dt_cpp_path);
free(dtp->dt_ld_path);
+#ifdef __FreeBSD__
+ free(dtp->dt_objcopy_path);
+#endif
free(dtp->dt_mods);
free(dtp->dt_provs);
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c
index e9164d09a857..758422e3407f 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c
@@ -280,6 +280,28 @@ dt_opt_ld_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
return (0);
}
+#ifdef __FreeBSD__
+static int
+dt_opt_objcopy_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
+{
+ char *objcopy;
+
+ if (arg == NULL)
+ return (dt_set_errno(dtp, EDT_BADOPTVAL));
+
+ if (dtp->dt_pcb != NULL)
+ return (dt_set_errno(dtp, EDT_BADOPTCTX));
+
+ if ((objcopy = strdup(arg)) == NULL)
+ return (dt_set_errno(dtp, EDT_NOMEM));
+
+ free(dtp->dt_objcopy_path);
+ dtp->dt_objcopy_path = objcopy;
+
+ return (0);
+}
+#endif
+
/*ARGSUSED*/
static int
dt_opt_libdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
@@ -960,6 +982,9 @@ static const dt_option_t _dtrace_ctoptions[] = {
{ "linkmode", dt_opt_linkmode },
{ "linktype", dt_opt_linktype },
{ "nolibs", dt_opt_cflags, DTRACE_C_NOLIBS },
+#ifdef __FreeBSD__
+ { "objcopypath", dt_opt_objcopy_path },
+#endif
{ "pgmax", dt_opt_pgmax },
{ "pspec", dt_opt_cflags, DTRACE_C_PSPEC },
{ "setenv", dt_opt_setenv, 1 },