svn commit: r232388 - in stable/9/lib/libc: gen include

Konstantin Belousov kib at FreeBSD.org
Fri Mar 2 11:47:35 UTC 2012


Author: kib
Date: Fri Mar  2 11:47:34 2012
New Revision: 232388
URL: http://svn.freebsd.org/changeset/base/232388

Log:
  MFC r231868:
  Fetch the aux vector for the static libc, and use the entries to
  initialize the cache of the system information as it was done for the
  dynamic libc. This removes several sysctls from the static binary
  startup.
  
  Use the aux vector to fill the single struct dl_phdr_info describing
  the static binary itself, to implement dl_iterate_phdr(3) for the
  static binaries.

Modified:
  stable/9/lib/libc/gen/aux.c
  stable/9/lib/libc/gen/dlfcn.c
  stable/9/lib/libc/include/libc_private.h
Directory Properties:
  stable/9/lib/libc/   (props changed)

Modified: stable/9/lib/libc/gen/aux.c
==============================================================================
--- stable/9/lib/libc/gen/aux.c	Fri Mar  2 11:32:47 2012	(r232387)
+++ stable/9/lib/libc/gen/aux.c	Fri Mar  2 11:47:34 2012	(r232388)
@@ -1,5 +1,5 @@
 /*-
- * Copyright 2010 Konstantin Belousov <kib at FreeBSD.ORG>.
+ * Copyright 2010, 2012 Konstantin Belousov <kib at FreeBSD.ORG>.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,10 +36,34 @@ __FBSDID("$FreeBSD$");
 #include "un-namespace.h"
 #include "libc_private.h"
 
-Elf_Auxinfo *__elf_aux_vector;
+extern char **environ;
+extern int _DYNAMIC;
+#pragma weak _DYNAMIC
 
-static pthread_once_t aux_once = PTHREAD_ONCE_INIT;
+void *__elf_aux_vector;
+static pthread_once_t aux_vector_once = PTHREAD_ONCE_INIT;
+
+static void
+init_aux_vector_once(void)
+{
+	Elf_Addr *sp;
+
+	sp = (Elf_Addr *)environ;
+	while (*sp++ != 0)
+		;
+	__elf_aux_vector = (Elf_Auxinfo *)sp;
+}
 
+void
+__init_elf_aux_vector(void)
+{
+
+	if (&_DYNAMIC != NULL)
+		return;
+	_once(&aux_vector_once, init_aux_vector_once);
+}
+
+static pthread_once_t aux_once = PTHREAD_ONCE_INIT;
 static int pagesize, osreldate, canary_len, ncpus, pagesizes_len;
 static char *canary, *pagesizes;
 
@@ -86,6 +110,7 @@ _elf_aux_info(int aux, void *buf, int bu
 {
 	int res;
 
+	__init_elf_aux_vector();
 	if (__elf_aux_vector == NULL)
 		return (ENOSYS);
 	_once(&aux_once, init_aux);

Modified: stable/9/lib/libc/gen/dlfcn.c
==============================================================================
--- stable/9/lib/libc/gen/dlfcn.c	Fri Mar  2 11:32:47 2012	(r232387)
+++ stable/9/lib/libc/gen/dlfcn.c	Fri Mar  2 11:47:34 2012	(r232388)
@@ -34,6 +34,10 @@ __FBSDID("$FreeBSD$");
 #include <dlfcn.h>
 #include <link.h>
 #include <stddef.h>
+#include "namespace.h"
+#include <pthread.h>
+#include "un-namespace.h"
+#include "libc_private.h"
 
 static char sorry[] = "Service unavailable";
 
@@ -138,13 +142,58 @@ _rtld_thread_init(void * li)
 	_rtld_error(sorry);
 }
 
+static pthread_once_t dl_phdr_info_once = PTHREAD_ONCE_INIT;
+static struct dl_phdr_info phdr_info;
+
+static void
+dl_init_phdr_info(void)
+{
+	Elf_Auxinfo *auxp;
+	size_t phent;
+	unsigned int i;
+
+	phent = 0;
+	for (auxp = __elf_aux_vector; auxp->a_type != AT_NULL; auxp++) {
+		switch (auxp->a_type) {
+		case AT_BASE:
+			phdr_info.dlpi_addr = (Elf_Addr)auxp->a_un.a_ptr;
+			break;
+		case AT_EXECPATH:
+			phdr_info.dlpi_name = (const char *)auxp->a_un.a_ptr;
+			break;
+		case AT_PHDR:
+			phdr_info.dlpi_phdr =
+			    (const Elf_Phdr *)auxp->a_un.a_ptr;
+			break;
+		case AT_PHENT:
+			phent = auxp->a_un.a_val;
+			break;
+		case AT_PHNUM:
+			phdr_info.dlpi_phnum = (Elf_Half)auxp->a_un.a_val;
+			break;
+		}
+	}
+	for (i = 0; i < phdr_info.dlpi_phnum; i++) {
+		if (phdr_info.dlpi_phdr[i].p_type == PT_TLS) {
+			phdr_info.dlpi_tls_modid = 1;
+			phdr_info.dlpi_tls_data =
+			    (void*)phdr_info.dlpi_phdr[i].p_vaddr;
+		}
+	}
+	phdr_info.dlpi_adds = 1;
+}
+
 #pragma weak dl_iterate_phdr
 int
 dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *),
     void *data)
 {
-	_rtld_error(sorry);
-	return 0;
+
+	__init_elf_aux_vector();
+	if (__elf_aux_vector == NULL)
+		return (1);
+	_once(&dl_phdr_info_once, dl_init_phdr_info);
+	return (callback(&phdr_info, sizeof(phdr_info), data));
 }
 
 #pragma weak fdlopen

Modified: stable/9/lib/libc/include/libc_private.h
==============================================================================
--- stable/9/lib/libc/include/libc_private.h	Fri Mar  2 11:32:47 2012	(r232387)
+++ stable/9/lib/libc/include/libc_private.h	Fri Mar  2 11:47:34 2012	(r232388)
@@ -44,6 +44,15 @@
 extern int	__isthreaded;
 
 /*
+ * Elf_Auxinfo *__elf_aux_vector, the pointer to the ELF aux vector
+ * provided by kernel. Either set for us by rtld, or found at runtime
+ * on stack for static binaries.
+ *
+ * Type is void to avoid polluting whole libc with ELF types.
+ */
+extern void	*__elf_aux_vector;
+
+/*
  * libc should use libc_dlopen internally, which respects a global
  * flag where loading of new shared objects can be restricted.
  */
@@ -229,6 +238,7 @@ int _execvpe(const char *, char * const 
 int _elf_aux_info(int aux, void *buf, int buflen);
 struct dl_phdr_info;
 int __elf_phdr_match_addr(struct dl_phdr_info *, void *);
+void __init_elf_aux_vector(void);
 
 void	_pthread_cancel_enter(int);
 void	_pthread_cancel_leave(int);


More information about the svn-src-stable-9 mailing list