コード例 #1
0
ファイル: getoff.c プロジェクト: AboorvaDevarajan/valgrind
int main (int argc, char** argv)
{
   int i;
   FILE *outputfile;
   int nr_errors = 0;
   
   outputfile = stdout;

   i = 1;
   while (i < argc) {
      if (is_opt(argv[i], "--help") || is_opt(argv[i], "-h")) {
         usage(argv[0]);
         exit(0);
      } else if (is_opt(argv[i], "-v")) {
         verbose++;
      } else if (is_opt(argv[i], "-o")) {
         if (i+1 == argc) {
            fprintf(stderr, 
                    "missing output file for -o option\n"
                    "Use --help for more information.\n");
            exit (1);
         }
         i++;
         outputfile = fopen(argv[i], "w");
         if (outputfile == NULL) {
            fprintf(stderr, "Could not fopen %s in write mode\n", argv[i]);
            perror ("fopen output file failed");
            exit (1);
         }
      } else {
         fprintf (stderr, 
                  "unknown or invalid argument %s\n"
                  "Use --help for more information.\n",
                  argv[i]);
         exit(1);
      }
      i++;
   }

#ifdef HAVE_DLINFO_RTLD_DI_TLS_MODID
   /* Compute offset of lm_modid in struct link_map.
      This is needed to support QGetTlsAddr gdbsrv query.
      Computation is done using an ugly hack, but less ugly than
      hardcoding the offset depending on the glibc version and
      platform.
      The below works, based the assumption that RTLD_DI_TLS_MODID
      just access and returns directly the field in the dummy
      link_map structure we have prepared.

      If glibc debug info is installed on your system, you can
      also find this offset by doing in GDB:
          p &((struct link_map*)0x0)->l_tls_modid
      (see also coregrind/m_gdbserver/valgrind_low.h target_get_dtv
       comments).
   */
   {
      #define MAX_LINKMAP_WORDS 10000
      size_t dummy_link_map[MAX_LINKMAP_WORDS];
      size_t off;
      size_t modid_offset;
      for (off = 0; off < MAX_LINKMAP_WORDS; off++)
         dummy_link_map[off] = off;
      if (dlinfo ((void*)dummy_link_map, RTLD_DI_TLS_MODID, 
                  &modid_offset) == 0) {
         assert(modid_offset >= 0 && modid_offset < MAX_LINKMAP_WORDS);
         fprintf(outputfile,
                 "lm_modid_offset 0x%zx\n", modid_offset*sizeof(size_t));
      } else {
         fprintf(stderr, 
                 "Error computing lm_modid_offset.\n"
                 "dlinfo error %s\n", dlerror());
         nr_errors++;
      }
      #undef MAX_LINKMAP_WORDS
   }
   
   if (outputfile != stdout)
      if (fclose (outputfile) != 0) {
         perror ("fclose output file failed\n");
         nr_errors++;
      }
#else
   if (verbose)
      fprintf(stderr, 
              "cannot compute lm_modid_offset.\n"
              "configure did not define HAVE_DLINFO_RTLD_DI_TLS_MODID.\n");
#endif

   if (nr_errors == 0)
      exit(0);
   else
      exit(1);
}
コード例 #2
0
void
OsInit(void)
{
    static Bool been_here = FALSE;
#ifndef XQUARTZ
    static const char *devnull = "/dev/null";
    char fname[PATH_MAX];
#endif

    if (!been_here) {
#if !defined(WIN32) || defined(__CYGWIN__)
        struct sigaction act, oact;
        int i;

        int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS,
            SIGSYS,
            SIGXCPU,
            SIGXFSZ,
#ifdef SIGEMT
            SIGEMT,
#endif
            0 /* must be last */
        };
        sigemptyset(&act.sa_mask);
#ifdef SA_SIGINFO
        act.sa_sigaction = OsSigHandler;
        act.sa_flags = SA_SIGINFO;
#else
        act.sa_handler = OsSigHandler;
        act.sa_flags = 0;
#endif
        for (i = 0; siglist[i] != 0; i++) {
            if (sigaction(siglist[i], &act, &oact)) {
                ErrorF("failed to install signal handler for signal %d: %s\n",
                       siglist[i], strerror(errno));
            }
        }
#endif /* !WIN32 || __CYGWIN__ */
#ifdef BUSFAULT
        busfault_init();
#endif

#ifdef HAVE_BACKTRACE
        /*
         * initialize the backtracer, since the ctor calls dlopen(), which
         * calls malloc(), which isn't signal-safe.
         */
        do {
            void *array;

            backtrace(&array, 1);
        } while (0);
#endif

#ifdef RTLD_DI_SETSIGNAL
        /* Tell runtime linker to send a signal we can catch instead of SIGKILL
         * for failures to load libraries/modules at runtime so we can clean up
         * after ourselves.
         */
        {
            int failure_signal = SIGQUIT;

            dlinfo(RTLD_SELF, RTLD_DI_SETSIGNAL, &failure_signal);
        }
#endif

#if !defined(XQUARTZ)    /* STDIN is already /dev/null and STDOUT/STDERR is managed by console_redirect.c */
# if defined(__APPLE__)
        int devnullfd = open(devnull, O_RDWR, 0);
        assert(devnullfd > 2);

        dup2(devnullfd, STDIN_FILENO);
        dup2(devnullfd, STDOUT_FILENO);
        close(devnullfd);
# elif !defined(__CYGWIN__)
        fclose(stdin);
        fclose(stdout);
# endif
        /*
         * If a write of zero bytes to stderr returns non-zero, i.e. -1,
         * then writing to stderr failed, and we'll write somewhere else
         * instead. (Apparently this never happens in the Real World.)
         */
        if (write(2, fname, 0) == -1) {
            FILE *err;

            if (strlen(display) + strlen(ADMPATH) + 1 < sizeof fname)
                snprintf(fname, sizeof(fname), ADMPATH, display);
            else
                strcpy(fname, devnull);
            /*
             * uses stdio to avoid os dependencies here,
             * a real os would use
             *  open (fname, O_WRONLY|O_APPEND|O_CREAT, 0666)
             */
            if (!(err = fopen(fname, "a+")))
                err = fopen(devnull, "w");
            if (err && (fileno(err) != 2)) {
                dup2(fileno(err), 2);
                fclose(err);
            }
#if defined(SYSV) || defined(SVR4) || defined(WIN32) || defined(__CYGWIN__)
            {
                static char buf[BUFSIZ];

                setvbuf(stderr, buf, _IOLBF, BUFSIZ);
            }
#else
            setlinebuf(stderr);
#endif
        }
#endif /* !XQUARTZ */

#if !defined(WIN32) || defined(__CYGWIN__)
        if (getpgrp() == 0)
            setpgid(0, 0);
#endif

#ifdef RLIMIT_DATA
        if (limitDataSpace >= 0) {
            struct rlimit rlim;

            if (!getrlimit(RLIMIT_DATA, &rlim)) {
                if ((limitDataSpace > 0) && (limitDataSpace < rlim.rlim_max))
                    rlim.rlim_cur = limitDataSpace;
                else
                    rlim.rlim_cur = rlim.rlim_max;
                (void) setrlimit(RLIMIT_DATA, &rlim);
            }
        }
#endif
#ifdef RLIMIT_STACK
        if (limitStackSpace >= 0) {
            struct rlimit rlim;

            if (!getrlimit(RLIMIT_STACK, &rlim)) {
                if ((limitStackSpace > 0) && (limitStackSpace < rlim.rlim_max))
                    rlim.rlim_cur = limitStackSpace;
                else
                    rlim.rlim_cur = rlim.rlim_max;
                (void) setrlimit(RLIMIT_STACK, &rlim);
            }
        }
#endif
#ifdef RLIMIT_NOFILE
        if (limitNoFile >= 0) {
            struct rlimit rlim;

            if (!getrlimit(RLIMIT_NOFILE, &rlim)) {
                if ((limitNoFile > 0) && (limitNoFile < rlim.rlim_max))
                    rlim.rlim_cur = limitNoFile;
                else
                    rlim.rlim_cur = rlim.rlim_max;
                (void) setrlimit(RLIMIT_NOFILE, &rlim);
            }
        }
#endif
        LockServer();
        been_here = TRUE;
    }
    TimerInit();
    OsVendorInit();
    OsResetSignals();
    /*
     * No log file by default.  OsVendorInit() should call LogInit() with the
     * log file name if logging to a file is desired.
     */
    LogInit(NULL, NULL);
    SmartScheduleInit();
}
コード例 #3
0
ファイル: drti.c プロジェクト: Alkzndr/freebsd
static void
dtrace_dof_init(void)
{
#if defined(sun)
	dof_hdr_t *dof = &__SUNW_dof;
#else
	dof_hdr_t *dof = NULL;
#endif
#ifdef _LP64
	Elf64_Ehdr *elf;
#else
	Elf32_Ehdr *elf;
#endif
	dof_helper_t dh;
	Link_map *lmp;
#if defined(sun)
	Lmid_t lmid;
#else
	u_long lmid = 0;
#endif
	int fd;
	const char *p;
#if !defined(sun)
	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;
#endif

	if (getenv("DTRACE_DOF_INIT_DISABLE") != NULL)
		return;

	if (getenv("DTRACE_DOF_INIT_DEBUG") != NULL)
		dof_init_debug = B_TRUE;

	if (dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &lmp) == -1 || lmp == NULL) {
		dprintf(1, "couldn't discover module name or address\n");
		return;
	}

#if defined(sun)
	if (dlinfo(RTLD_SELF, RTLD_DI_LMID, &lmid) == -1) {
		dprintf(1, "couldn't discover link map ID\n");
		return;
	}
#endif

	if ((modname = strrchr(lmp->l_name, '/')) == NULL)
		modname = lmp->l_name;
	else
		modname++;
#if !defined(sun)
	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;
			}
		}
	}
	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) {
		dof_next = (void *) ((char *) dof + dof->dofh_filesz);
#endif

	if (dof->dofh_ident[DOF_ID_MAG0] != DOF_MAG_MAG0 ||
	    dof->dofh_ident[DOF_ID_MAG1] != DOF_MAG_MAG1 ||
	    dof->dofh_ident[DOF_ID_MAG2] != DOF_MAG_MAG2 ||
	    dof->dofh_ident[DOF_ID_MAG3] != DOF_MAG_MAG3) {
		dprintf(0, ".SUNW_dof section corrupt\n");
		return;
	}

	elf = (void *)lmp->l_addr;

	dh.dofhp_dof = (uintptr_t)dof;
	dh.dofhp_addr = elf->e_type == ET_DYN ? (uintptr_t) lmp->l_addr : 0;

	if (lmid == 0) {
		(void) snprintf(dh.dofhp_mod, sizeof (dh.dofhp_mod),
		    "%s", modname);
	} else {
		(void) snprintf(dh.dofhp_mod, sizeof (dh.dofhp_mod),
		    "LM%lu`%s", lmid, modname);
	}

	if ((p = getenv("DTRACE_DOF_INIT_DEVNAME")) != NULL)
		devnamep = p;

	if ((fd = open64(devnamep, O_RDWR)) < 0) {
		dprintf(1, "failed to open helper device %s", devnamep);
#if defined(sun)
		/*
		 * If the device path wasn't explicitly set, try again with
		 * the old device path.
		 */
		if (p != NULL)
			return;

		devnamep = olddevname;

		if ((fd = open64(devnamep, O_RDWR)) < 0) {
			dprintf(1, "failed to open helper device %s", devnamep);
			return;
		}
#else
		return;
#endif
	}
	if ((gen = ioctl(fd, DTRACEHIOC_ADDDOF, &dh)) == -1)
		dprintf(1, "DTrace ioctl failed for DOF at %p", dof);
	else {
		dprintf(1, "DTrace ioctl succeeded for DOF at %p\n", dof);
#if !defined(sun)
		gen = dh.gen;
#endif
	}

	(void) close(fd);

#if !defined(sun)
		/* End of while loop */
		dof = dof_next;
	}

	elf_end(e);
	(void) close(efd);
#endif
}
コード例 #4
0
/**
 * Prints a stack backtrace for the current thread to the specified ostream.
 *
 * Does not malloc, does not throw.
 *
 * The format of the backtrace is:
 *
 * ----- BEGIN BACKTRACE -----
 * JSON backtrace
 * Human-readable backtrace
 * -----  END BACKTRACE  -----
 *
 * The JSON backtrace will be a JSON object with a "backtrace" field, and optionally others.
 * The "backtrace" field is an array, whose elements are frame objects.  A frame object has a
 * "b" field, which is the base-address of the library or executable containing the symbol, and
 * an "o" field, which is the offset into said library or executable of the symbol.
 *
 * The JSON backtrace may optionally contain additional information useful to a backtrace
 * analysis tool.  For example, on Linux it contains a subobject named "somap", describing
 * the objects referenced in the "b" fields of the "backtrace" list.
 *
 * @param os    ostream& to receive printed stack backtrace
 */
void printStackTrace(std::ostream& os) {
    static const char unknownFileName[] = "???";
    void* addresses[maxBackTraceFrames];
    Dl_info dlinfoForFrames[maxBackTraceFrames];

    ////////////////////////////////////////////////////////////
    // Get the backtrace addresses.
    ////////////////////////////////////////////////////////////

    const int addressCount = backtrace(addresses, maxBackTraceFrames);
    if (addressCount == 0) {
        const int err = errno;
        os << "Unable to collect backtrace addresses (errno: " <<
           err << ' ' << strerror(err) << ')' << std::endl;
        return;
    }

    ////////////////////////////////////////////////////////////
    // Collect symbol information for each backtrace address.
    ////////////////////////////////////////////////////////////

    os << std::hex << std::uppercase << '\n';
    for (int i = 0; i < addressCount; ++i) {
        Dl_info& dlinfo(dlinfoForFrames[i]);
        if (!dladdr(addresses[i], &dlinfo)) {
            dlinfo.dli_fname = unknownFileName;
            dlinfo.dli_fbase = NULL;
            dlinfo.dli_sname = NULL;
            dlinfo.dli_saddr = NULL;
        }
        os << ' ' << addresses[i];
    }

    os << "\n----- BEGIN BACKTRACE -----\n";

    ////////////////////////////////////////////////////////////
    // Display the JSON backtrace
    ////////////////////////////////////////////////////////////

    os << "{\"backtrace\":[";
    for (int i = 0; i < addressCount; ++i) {
        const Dl_info& dlinfo = dlinfoForFrames[i];
        const uintptr_t fileOffset = uintptr_t(addresses[i]) - uintptr_t(dlinfo.dli_fbase);
        if (i)
            os << ',';
        os << "{\"b\":\"" << uintptr_t(dlinfo.dli_fbase) <<
           "\",\"o\":\"" << fileOffset << "\"}";
    }
    os << ']';

    if (soMapJson)
        os << ",\"processInfo\":" << *soMapJson;
    os << "}\n";

    ////////////////////////////////////////////////////////////
    // Display the human-readable trace
    ////////////////////////////////////////////////////////////
    for (int i = 0; i < addressCount; ++i) {
        Dl_info& dlinfo(dlinfoForFrames[i]);
        os << ' ';
        if (dlinfo.dli_fbase) {
            os << getBaseName(dlinfo.dli_fname) << '(';
            if (dlinfo.dli_sname) {
                const uintptr_t offset = uintptr_t(addresses[i]) - uintptr_t(dlinfo.dli_saddr);
                os << dlinfo.dli_sname << "+0x" << offset;
            }
            else {
                const uintptr_t offset = uintptr_t(addresses[i]) - uintptr_t(dlinfo.dli_fbase);
                os << "+0x" << offset;
            }
            os << ')';
        }
        else {
            os << unknownFileName;
        }
        os << " [" << addresses[i] << ']' << std::endl;
    }

    os << std::dec << std::nouppercase;
    os << "-----  END BACKTRACE  -----" << std::endl;
}
コード例 #5
0
ファイル: pkg_elf.c プロジェクト: dnaeon/pkgng
static int
analyse_elf(struct pkgdb *db, struct pkg *pkg, const char *fpath)
{
	struct pkg_dep *dep = NULL;
	struct pkg *p = NULL;
	struct pkgdb_it *it = NULL;
	Elf *e;
	Elf_Scn *scn = NULL;
	GElf_Shdr shdr;
	Elf_Data *data;
	GElf_Dyn *dyn, dyn_mem;
	size_t numdyn;
	size_t dynidx;
	void *handle;
	Link_map *map;
	char *name;
	bool found=false;

	int fd;

	if ((fd = open(fpath, O_RDONLY, 0)) < 0)
		return (EPKG_FATAL);

	if (( e = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
		return (EPKG_FATAL);

	if (elf_kind(e) != ELF_K_ELF)
		return (EPKG_FATAL);

	while (( scn = elf_nextscn(e, scn)) != NULL) {
		if (gelf_getshdr(scn, &shdr) != &shdr)
			return (EPKG_FATAL);

		if (shdr.sh_type == SHT_DYNAMIC)
			break;
	}

	if  (scn == NULL)
		return (EPKG_OK);

	data = elf_getdata(scn, NULL);
	numdyn = shdr.sh_size / shdr.sh_entsize;

	for (dynidx = 0; dynidx < numdyn; dynidx++) {
		if ((dyn = gelf_getdyn(data, dynidx, &dyn_mem)) == NULL)
			return (EPKG_FATAL);

		if (dyn->d_tag != DT_NEEDED)
			continue;

		name = elf_strptr(e, shdr.sh_link, dyn->d_un.d_val);
		handle = dlopen(name, RTLD_LAZY);

		if (handle != NULL) {
			dlinfo(handle, RTLD_DI_LINKMAP, &map);
			if ((it = pkgdb_query_which(db, map->l_name)) == NULL)
				return (EPKG_FATAL);

			if (pkgdb_it_next(it, &p, PKG_LOAD_BASIC) == EPKG_OK) {
				found = false;
				while (pkg_deps(pkg, &dep) == EPKG_OK) {
					if (strcmp(pkg_dep_origin(dep), pkg_get(p, PKG_ORIGIN)) == 0)
						found = true;
				}
				if (!found) {
					pkg_emit_error("adding forgotten depends (%s): %s-%s",
								   map->l_name, pkg_get(p, PKG_NAME),
								   pkg_get(p, PKG_VERSION));
					pkg_adddep(pkg, pkg_get(p, PKG_NAME), pkg_get(p, PKG_ORIGIN), pkg_get(p, PKG_VERSION));
				}
			}
			dlclose(handle);
		}
		pkgdb_it_free(it);
	}
	pkg_free(p);
	close(fd);

	return (EPKG_OK);

}
コード例 #6
0
ファイル: profile.c プロジェクト: andreiw/polaris
int
profile_open(const char *fname, Link_map *lmp)
{
	size_t		hsize;		/* struct hdr size */
	size_t		psize;		/* profile histogram size */
	size_t		csize;		/* call graph array size */
	size_t		msize;		/* size of memory being profiled */
	int		i, fd, fixed = 0;
	caddr_t		lpc;
	caddr_t		hpc;
	caddr_t		addr;
	struct stat	status;
	int		new_buffer = 0;
	sigset_t	mask;
	int		err;
	Ehdr *		ehdr;		/* ELF header for file */
	Phdr *		phdr;		/* program headers for file */
	Dyn *		dynp = 0;	/* Dynamic section */
	Word		nsym = 0;	/* no. of symtab ntries */

	if (*Profile == '\0') {
		const char	*dir, *suf;
		char		*tmp;

		/*
		 * From the basename of the specified filename generate the
		 * appropriate profile buffer name.  The profile file is created
		 * if it does not already exist.
		 */
		if (((tmp = strrchr(fname, '/')) != 0) && (*(++tmp)))
			fname = tmp;

#if	defined(_ELF64)
		suf = MSG_ORIG(MSG_SUF_PROFILE_64);
#else
		suf = MSG_ORIG(MSG_SUF_PROFILE);
#endif
		if (dlinfo((void *)NULL, RTLD_DI_PROFILEOUT, &dir) == -1)
			dir = MSG_ORIG(MSG_PTH_VARTMP);

		(void) snprintf(Profile, MAXPATHLEN, MSG_ORIG(MSG_FMT_PROFILE),
		    dir, fname, suf);
	}

	if ((fd = open(Profile, (O_RDWR | O_CREAT), 0666)) == -1) {
		err = errno;
		(void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), Profile,
		    strerror(err));
		return (0);
	}

	/*
	 * Now we determine the valid pc range for this object.  The lpc is easy
	 * (lmp->l_addr), to determine the hpc we must examine the Phdrs.
	 */
	lpc = hpc = (caddr_t)lmp->l_addr;
	/* LINTED */
	ehdr = (Ehdr *)lpc;
	if (ehdr->e_phnum == 0) {
		(void) close(fd);
		return (0);
	}
	if (ehdr->e_type == ET_EXEC)
		fixed = 1;
	/* LINTED */
	phdr = (Phdr *)(ehdr->e_phoff + lpc);
	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
		caddr_t	_hpc;

		if (phdr->p_type == PT_DYNAMIC) {
			dynp = (Dyn *)phdr->p_vaddr;
			if (fixed == 0) {
				dynp = (Dyn *)((unsigned long)dynp +
					(unsigned long)lpc);
			}
			continue;
		}

		if (phdr->p_type != PT_LOAD)
			continue;

		_hpc = (caddr_t)(phdr->p_vaddr + phdr->p_memsz);
		if (fixed == 0) {
			_hpc = (caddr_t)((unsigned long)_hpc +
				(unsigned long)lpc);
		}
		if (_hpc > hpc)
			hpc = _hpc;
	}
	if (lpc == hpc) {
		(void) close(fd);
		return (0);
	}

	/*
	 * In order to determine the number of symbols in the object scan the
	 * dynamic section until we find the DT_HASH entry (hash[1] == symcnt).
	 */
	if (dynp) {
		for (; dynp->d_tag != DT_NULL; dynp++) {
			unsigned int	*hashp;

			if (dynp->d_tag != DT_HASH)
				continue;

			hashp = (unsigned int *)dynp->d_un.d_ptr;
			if (fixed == 0) {
				hashp = (unsigned int *)((unsigned long)hashp +
					(unsigned long)lpc);
			}
			nsym = hashp[1];
			break;
		}
	}

	/*
	 * Determine the (minimum) size of the buffer to allocate
	 */
	Lpc = lpc = (caddr_t)PRF_ROUNDWN((long)lpc, sizeof (long));
	Hpc = hpc = (caddr_t)PRF_ROUNDUP((long)hpc, sizeof (long));

	hsize = sizeof (L_hdr);
	msize = (size_t)(hpc - lpc);
	psize = (size_t)PRF_ROUNDUP((msize / PRF_BARSIZE), sizeof (long));
	csize = (nsym + 1) * PRF_CGINIT * sizeof (L_cgarc);
	Fsize = (hsize + psize + csize);

	/*
	 * If the file size is zero (ie. we just created it), truncate it
	 * to the minimum size.
	 */
	(void) fstat(fd, &status);
	if (status.st_size == 0) {
		if (ftruncate(fd, Fsize) == -1) {
			err = errno;
			(void) fprintf(stderr, MSG_INTL(MSG_SYS_FTRUNC),
			    Profile, strerror(err));
			(void) close(fd);
			return (0);
		}
		new_buffer++;
	} else
		Fsize = status.st_size;

	/*
	 * Map the file in.
	 */
	if ((addr = (caddr_t)mmap(0, Fsize, (PROT_READ | PROT_WRITE),
	    MAP_SHARED, fd, 0)) == (char *)-1) {
		err = errno;
		(void) fprintf(stderr, MSG_INTL(MSG_SYS_MMAP), Profile,
		    strerror(err));
		(void) close(fd);
		return (0);
	}
	(void) close(fd);

	/*
	 * Initialize the remaining elements of the header.  All pc addresses
	 * that are recorded are relative to zero thus allowing the recorded
	 * entries to be correlated with the symbols in the original file,
	 * and to compensate for any differences in where the file is mapped.
	 * If the high pc address has been initialized from a previous run,
	 * and the new entry is different from the original then a new library
	 * must have been installed.  In this case bale out.
	 */
	/* LINTED */
	Hptr = (L_hdr *)addr;

	if (new_buffer)
		(void) prof_mutex_init((lwp_mutex_t *)&Hptr->hd_mutex);

	(void) prof_mutex_lock((mutex_t *)&Hptr->hd_mutex, &mask);
	if (Hptr->hd_hpc) {
		if (Hptr->hd_hpc != (caddr_t)(hpc - lpc)) {
			(void) fprintf(stderr, MSG_INTL(MSG_GEN_PROFSZCHG),
			    Profile);
			(void) prof_mutex_unlock((mutex_t *)&Hptr->
			    hd_mutex, &mask);
			(void) munmap((caddr_t)Hptr, Fsize);
			return (0);
		}
	} else {
		/*
		 * Initialize the header information as we must have just
		 * created the output file.
		 */
		Hptr->hd_magic = (unsigned int)PRF_MAGIC;
#if	defined(_ELF64)
		Hptr->hd_version = (unsigned int)PRF_VERSION_64;
#else
		Hptr->hd_version = (unsigned int)PRF_VERSION;
#endif
		Hptr->hd_hpc = (caddr_t)(hpc - lpc);
		/* LINTED */
		Hptr->hd_psize = (unsigned int)psize;
		/* LINTED */
		Hptr->hd_fsize = (unsigned int)Fsize;
		Hptr->hd_ncndx = nsym;
		Hptr->hd_lcndx = (nsym + 1) * PRF_CGINIT;
	}

	(void) prof_mutex_unlock((mutex_t *)&Hptr->hd_mutex, &mask);
	/* LINTED */
	Cptr = (L_cgarc *)(addr + hsize + psize);

	/*
	 * Turn on profiling
	 */
	/* LINTED */
	profil((unsigned short *)(addr + hsize),
		psize, (unsigned long)lpc, (unsigned int) PRF_SCALE);

	return (1);
}
コード例 #7
0
ファイル: shd-main.c プロジェクト: desphunter/shadow
static gulong _main_computeLoadSize(Lmid_t lmid, const gchar* pluginPath, const gchar* preloadPath, gint dlmopenFlags) {
    gulong tlsSizeStart = 0, tlsSizeEnd = 0, tlsSizePerLoad = 0;
    gpointer handle1 = NULL, handle2 = NULL;
    gint result = 0;

    debug("computing static TLS size needed for library at path '%s' and preload at path '%s'",
            pluginPath, preloadPath ? preloadPath : "NULL");

    /* clear error */
    dlerror();

    /* get the initial TLS size used */
    result = dlinfo(NULL, RTLD_DI_STATIC_TLS_SIZE, &tlsSizeStart);

    if (result != 0) {
        warning("error in dlinfo() while computing TLS start size, dlerror is '%s'", dlerror());
        goto err;
    }

    /* open the plugin library in the requested lmid */
    handle1 = dlmopen(lmid, pluginPath, dlmopenFlags);

    if(handle1 == NULL) {
        warning("error in plugin dlmopen() while computing TLS size, dlerror is '%s'", dlerror());
        goto err;
    }

    if(preloadPath) {
        /* get the LMID so we can load it in the same namespace as the plugin */
        Lmid_t prev_lmid = 0;
        result = dlinfo(handle1, RTLD_DI_LMID, &prev_lmid);

        if(result != 0) {
            warning("dlinfo() failed when querying for previous LMID: %s", dlerror());
            goto err;
        }

        handle2 = dlmopen(prev_lmid, preloadPath, dlmopenFlags|RTLD_INTERPOSE);
        if(handle2 == NULL) {
            warning("error in preload dlmopen() while computing TLS size, dlerror is '%s'", dlerror());
            goto err;
        }
    }

    result = dlinfo(NULL, RTLD_DI_STATIC_TLS_SIZE, &tlsSizeEnd);

    if (result != 0) {
        warning("error in dlinfo() while computing TLS end size, dlerror is '%s'", dlerror());
        goto err;
    }

// TODO close the handles to clean up, after elf loader supports interleaving dlopens and dlcloses
//    dlclose(handle1);
//    dlclose(handle2);

    tlsSizePerLoad = (tlsSizeEnd - tlsSizeStart);

    /* log the result */
    GString* msg = g_string_new(NULL);
    g_string_printf(msg, "we need %lu bytes of static TLS per load of namespace with library at path '%s'", tlsSizePerLoad, pluginPath);
    if(preloadPath) {
        g_string_append_printf(msg, " and preload at path '%s'", preloadPath);
    }
    message("%s", msg->str);
    g_string_free(msg, TRUE);

    /* make sure we dont return 0 when successful */
    if(tlsSizePerLoad < 1) {
        tlsSizePerLoad = 1;
    }
    return tlsSizePerLoad;

err:
// TODO close the handles to clean up, after elf loader supports interleaving dlopens and dlcloses
//    if(handle1) {
//        dlclose(handle1);
//    }
//    if(handle2) {
//        dlclose(handle2);
//    }
    return 0;
}
コード例 #8
0
ファイル: modstatic2.c プロジェクト: AdvancedC/glibc
int
test (FILE *out, int a)
{
  fputs ("in modstatic2.c (test)\n", out);

  void *handle = dlopen ("modstatic2-nonexistent.so", RTLD_LAZY);
  if (handle == NULL)
    fprintf (out, "nonexistent: %s\n", dlerror ());
  else
    exit (1);

  handle = dlopen ("modstatic2.so", RTLD_LAZY);
  if (handle == NULL)
    {
      fprintf (out, "%s\n", dlerror ());
      exit (1);
    }

  int (*test2) (FILE *, int);
  test2 = dlsym (handle, "test");
  if (test2 == NULL)
    {
      fprintf (out, "%s\n", dlerror ());
      exit (1);
    }
  if (test2 != test)
    {
      fprintf (out, "test %p != test2 %p\n", test, test2);
      exit (1);
    }

  Dl_info info;
  int res = dladdr (test2, &info);
  if (res == 0)
    {
      fputs ("dladdr returned 0\n", out);
      exit (1);
    }
  else
    {
      if (strstr (info.dli_fname, "modstatic2.so") == NULL
	  || strcmp (info.dli_sname, "test") != 0)
	{
	  fprintf (out, "fname %s sname %s\n", info.dli_fname, info.dli_sname);
	  exit (1);
	}
      if (info.dli_saddr != (void *) test2)
	{
	  fprintf (out, "saddr %p != test %p\n", info.dli_saddr, test2);
	  exit (1);
	}
    }

  ElfW(Sym) *sym;
  void *symp;
  res = dladdr1 (test2, &info, &symp, RTLD_DL_SYMENT);
  if (res == 0)
    {
      fputs ("dladdr1 returned 0\n", out);
      exit (1);
    }
  else
    {
      if (strstr (info.dli_fname, "modstatic2.so") == NULL
	  || strcmp (info.dli_sname, "test") != 0)
	{
	  fprintf (out, "fname %s sname %s\n", info.dli_fname, info.dli_sname);
	  exit (1);
	}
      if (info.dli_saddr != (void *) test2)
	{
	  fprintf (out, "saddr %p != test %p\n", info.dli_saddr, test2);
	  exit (1);
	}
      sym = symp;
      if (sym == NULL)
	{
	  fputs ("sym == NULL\n", out);
	  exit (1);
	}
      if (ELF32_ST_BIND (sym->st_info) != STB_GLOBAL
	  || ELF32_ST_VISIBILITY (sym->st_other) != STV_DEFAULT)
	{
	  fprintf (out, "bind %d visibility %d\n",
		   (int) ELF32_ST_BIND (sym->st_info),
		   (int) ELF32_ST_VISIBILITY (sym->st_other));
	  exit (1);
	}
    }

  Lmid_t lmid;
  res = dlinfo (handle, RTLD_DI_LMID, &lmid);
  if (res != 0)
    {
      fprintf (out, "dlinfo returned %d %s\n", res, dlerror ());
      exit (1);
    }
  else if (lmid != LM_ID_BASE)
    {
      fprintf (out, "lmid %d != %d\n", (int) lmid, (int) LM_ID_BASE);
      exit (1);
    }

  void *handle2 = dlopen (LIBDL_SO, RTLD_LAZY);
  if (handle2 == NULL)
    {
      fprintf (out, "libdl.so: %s\n", dlerror ());
      exit (1);
    }

#ifdef DO_VERSIONING
  if (dlvsym (handle2, "_dlfcn_hook", "GLIBC_PRIVATE") == NULL)
    {
      fprintf (out, "dlvsym: %s\n", dlerror ());
      exit (1);
    }
#endif

  void *(*dlsymfn) (void *, const char *);
  dlsymfn = dlsym (handle2, "dlsym");
  if (dlsymfn == NULL)
    {
      fprintf (out, "dlsym \"dlsym\": %s\n", dlerror ());
      exit (1);
    }
  void *test3 = dlsymfn (handle, "test");
  if (test3 == NULL)
    {
      fprintf (out, "%s\n", dlerror ());
      exit (1);
    }
  else if (test3 != (void *) test2)
    {
      fprintf (out, "test2 %p != test3 %p\n", test2, test3);
      exit (1);
    }

  dlclose (handle2);
  dlclose (handle);

  handle = dlmopen (LM_ID_BASE, "modstatic2.so", RTLD_LAZY);
  if (handle == NULL)
    {
      fprintf (out, "%s\n", dlerror ());
      exit (1);
    }
  dlclose (handle);

  handle = dlmopen (LM_ID_NEWLM, "modstatic2.so", RTLD_LAZY);
  if (handle == NULL)
    fprintf (out, "LM_ID_NEWLM: %s\n", dlerror ());
  else
    {
      fputs ("LM_ID_NEWLM unexpectedly succeeded\n", out);
      exit (1);
    }

  handle = dlopen ("modstatic.so", RTLD_LAZY);
  if (handle == NULL)
    {
      fprintf (out, "%s\n", dlerror ());
      exit (1);
    }

  int (*test4) (int);
  test4 = dlsym (handle, "test");
  if (test4 == NULL)
    {
      fprintf (out, "%s\n", dlerror ());
      exit (1);
    }

  res = test4 (16);
  if (res != 16 + 16)
    {
      fprintf (out, "modstatic.so (test) returned %d\n", res);
      exit (1);
    }

  res = dladdr1 (test4, &info, &symp, RTLD_DL_SYMENT);
  if (res == 0)
    {
      fputs ("dladdr1 returned 0\n", out);
      exit (1);
    }
  else
    {
      if (strstr (info.dli_fname, "modstatic.so") == NULL
	  || strcmp (info.dli_sname, "test") != 0)
	{
	  fprintf (out, "fname %s sname %s\n", info.dli_fname, info.dli_sname);
	  exit (1);
	}
      if (info.dli_saddr != (void *) test4)
	{
	  fprintf (out, "saddr %p != test %p\n", info.dli_saddr, test4);
	  exit (1);
	}
      sym = symp;
      if (sym == NULL)
	{
	  fputs ("sym == NULL\n", out);
	  exit (1);
	}
      if (ELF32_ST_BIND (sym->st_info) != STB_GLOBAL
	  || ELF32_ST_VISIBILITY (sym->st_other) != STV_DEFAULT)
	{
	  fprintf (out, "bind %d visibility %d\n",
		   (int) ELF32_ST_BIND (sym->st_info),
		   (int) ELF32_ST_VISIBILITY (sym->st_other));
	  exit (1);
	}
    }

  dlclose (handle);

  fputs ("leaving modstatic2.c (test)\n", out);
  return a + a;
}
コード例 #9
0
/*
 * Get the linkmap from the dynlinker.  Try to load kernel modules
 * from all objects in the linkmap.
 */
void
rumpuser_dl_bootstrap(rump_modinit_fn domodinit,
	rump_symload_fn symload, rump_compload_fn compload)
{
	struct link_map *map, *origmap, *mainmap;
	void *mainhandle;
	int error;

	mainhandle = dlopen(NULL, RTLD_NOW);
	/* Will be null if statically linked so just return */
	if (mainhandle == NULL)
		return;
	if (dlinfo(mainhandle, RTLD_DI_LINKMAP, &mainmap) == -1) {
		fprintf(stderr, "warning: rumpuser module bootstrap "
		    "failed: %s\n", dlerror());
		return;
	}
	origmap = mainmap;

	/*
	 * Use a heuristic to determine if we are static linked.
	 * A dynamically linked binary should always have at least
	 * two objects: itself and ld.so.
	 *
	 * In a statically linked binary with glibc the linkmap
	 * contains some "info" that leads to a segfault.  Since we
	 * can't really do anything useful in here without ld.so, just
	 * simply bail and let the symbol references in librump do the
	 * right things.
	 */
	if (origmap->l_next == NULL && origmap->l_prev == NULL) {
		dlclose(mainhandle);
		return;
	}

	/*
	 * Process last->first because that's the most probable
	 * order for dependencies
	 */
	for (; origmap->l_next; origmap = origmap->l_next)
		continue;

	/*
	 * Build symbol table to hand to the rump kernel.  Do this by
	 * iterating over all rump libraries and collecting symbol
	 * addresses and relocation info.
	 */
	error = 0;
	for (map = origmap; map && !error; map = map->l_prev) {
		if (strstr(map->l_name, "librump") != NULL || map == mainmap)
			error = getsymbols(map, map == mainmap);
	}

	if (error == 0) {
		void *trimmedsym, *trimmedstr;

		/*
		 * Allocate optimum-sized memory for storing tables
		 * and feed to kernel.  If memory allocation fails,
		 * just give the ones with extra context (although
		 * I'm pretty sure we'll die moments later due to
		 * memory running out).
		 */
		if ((trimmedsym = malloc(symtaboff)) != NULL) {
			memcpy(trimmedsym, symtab, symtaboff);
		} else {
			trimmedsym = symtab;
			symtab = NULL;
		}
		if ((trimmedstr = malloc(strtaboff)) != NULL) {
			memcpy(trimmedstr, strtab, strtaboff);
		} else {
			trimmedstr = strtab;
			strtab = NULL;
		}
		symload(trimmedsym, symtaboff, trimmedstr, strtaboff);
	}
	free(symtab);
	free(strtab);

	/*
	 * Next, load modules and components.
	 *
	 * Simply loop through all objects, ones unrelated to rump kernels
	 * will not contain link_set_rump_components (well, not including
	 * "sabotage", but that needs to be solved at another level anyway).
	 */
	for (map = origmap; map; map = map->l_prev) {
		void *handle;

		if (map == mainmap) {
			handle = mainhandle;
		} else {
			handle = dlopen(map->l_name, RTLD_LAZY);
			if (handle == NULL)
				continue;
		}
		process_object(handle, domodinit, compload);
		if (map != mainmap)
			dlclose(handle);
	}
}
コード例 #10
0
ファイル: drti.c プロジェクト: goroutines/rumprun
static void
dtrace_dof_init(void)
{
	dof_hdr_t *dof = &__SUNW_dof;
#ifdef _LP64
	Elf64_Ehdr *elf;
#else
	Elf32_Ehdr *elf;
#endif
	dof_helper_t dh;
	Link_map *lmp = NULL;
#ifdef illumos
	Lmid_t lmid;
#else
	u_long lmid = 0;
#endif
	int fd;
	const char *p;

	if (getenv("DTRACE_DOF_INIT_DISABLE") != NULL)
		return;

	if (getenv("DTRACE_DOF_INIT_DEBUG") != NULL)
		dof_init_debug = B_TRUE;

	if (dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &lmp) == -1 || lmp == NULL) {
		dprintf(1, "couldn't discover module name or address\n");
		return;
	}

#ifdef illumos
	if (dlinfo(RTLD_SELF, RTLD_DI_LMID, &lmid) == -1) {
		dprintf(1, "couldn't discover link map ID\n");
		return;
	}
#endif

	if ((modname = strrchr(lmp->l_name, '/')) == NULL)
		modname = lmp->l_name;
	else
		modname++;

	if (dof->dofh_ident[DOF_ID_MAG0] != DOF_MAG_MAG0 ||
	    dof->dofh_ident[DOF_ID_MAG1] != DOF_MAG_MAG1 ||
	    dof->dofh_ident[DOF_ID_MAG2] != DOF_MAG_MAG2 ||
	    dof->dofh_ident[DOF_ID_MAG3] != DOF_MAG_MAG3) {
		dprintf(0, ".SUNW_dof section corrupt\n");
		return;
	}

	elf = (void *)lmp->l_addr;

	dh.dofhp_dof = (uintptr_t)dof;
	dh.dofhp_addr = elf->e_type == ET_DYN ? (uintptr_t) lmp->l_addr : 0;
#if defined(__FreeBSD__) || defined(__NetBSD__)
	dh.dofhp_pid = getpid();
#endif

	if (lmid == 0) {
		(void) snprintf(dh.dofhp_mod, sizeof (dh.dofhp_mod),
		    "%s", modname);
	} else {
		(void) snprintf(dh.dofhp_mod, sizeof (dh.dofhp_mod),
		    "LM%lu`%s", lmid, modname);
	}

	if ((p = getenv("DTRACE_DOF_INIT_DEVNAME")) != NULL)
		devnamep = p;

	if ((fd = open64(devnamep, O_RDWR)) < 0) {
		dprintf(1, "failed to open helper device %s", devnamep);
#ifdef illumos
		/*
		 * If the device path wasn't explicitly set, try again with
		 * the old device path.
		 */
		if (p != NULL)
			return;

		devnamep = olddevname;

		if ((fd = open64(devnamep, O_RDWR)) < 0) {
			dprintf(1, "failed to open helper device %s", devnamep);
			return;
		}
#else
		return;
#endif
	}
	if ((gen = ioctl(fd, DTRACEHIOC_ADDDOF, &dh)) == -1)
		dprintf(1, "DTrace ioctl failed for DOF at %p", dof);
	else {
		dprintf(1, "DTrace ioctl succeeded for DOF at %p\n", dof);
#if defined(__FreeBSD__) || defined(__NetBSD__)
		gen = dh.dofhp_gen;
#endif
	}

	(void) close(fd);
}