Author: markj
Date: Wed Feb 18 03:54:54 2015
New Revision: 278934
URL: https://svnweb.freebsd.org/changeset/base/278934

Log:
  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

Modified:
  head/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c
  head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h
  head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c
  head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
  head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c
  head/share/mk/bsd.dep.mk

Modified: head/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c
==============================================================================
--- head/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c   Wed Feb 18 
03:46:43 2015        (r278933)
+++ head/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c   Wed Feb 18 
03:54:54 2015        (r278934)
@@ -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 = "/device
 
 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) __attr
 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

Modified: head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h
==============================================================================
--- head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h        Wed Feb 
18 03:46:43 2015        (r278933)
+++ head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h        Wed Feb 
18 03:54:54 2015        (r278934)
@@ -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 */

Modified: head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c
==============================================================================
--- head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c        Wed Feb 
18 03:46:43 2015        (r278933)
+++ head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c        Wed Feb 
18 03:54:54 2015        (r278934)
@@ -281,7 +281,11 @@ printf("%s:%s(%d): DOODAD\n",__FUNCTION_
        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 d
        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_
 
        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, d
 #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, d
                    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);
        }

Modified: head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
==============================================================================
--- head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c        Wed Feb 
18 03:46:43 2015        (r278933)
+++ head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c        Wed Feb 
18 03:54:54 2015        (r278934)
@@ -785,6 +785,7 @@ const char *_dtrace_defld = "/usr/ccs/bi
 #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);

Modified: head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c
==============================================================================
--- head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c     Wed Feb 
18 03:46:43 2015        (r278933)
+++ head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c     Wed Feb 
18 03:54:54 2015        (r278934)
@@ -280,6 +280,28 @@ dt_opt_ld_path(dtrace_hdl_t *dtp, const 
        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_ctoptio
        { "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 },

Modified: head/share/mk/bsd.dep.mk
==============================================================================
--- head/share/mk/bsd.dep.mk    Wed Feb 18 03:46:43 2015        (r278933)
+++ head/share/mk/bsd.dep.mk    Wed Feb 18 03:54:54 2015        (r278934)
@@ -121,10 +121,7 @@ ${_YC:R}.o: ${_YC}
 .endfor
 
 # DTrace probe definitions
-# libelf is currently needed for drti.o
 .if ${SRCS:M*.d}
-LDADD+=                -lelf
-DPADD+=                ${LIBELF}
 CFLAGS+=       -I${.OBJDIR}
 .endif
 .for _DSRC in ${SRCS:M*.d:N*/*}
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to