bin/142258: [patch] Add ability to log or print rtld errors

Peter Jeremy peterjeremy at acm.org
Sun Jan 3 07:10:01 UTC 2010


>Number:         142258
>Category:       bin
>Synopsis:       [patch] Add ability to log or print rtld errors
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Jan 03 07:10:00 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     Peter Jeremy
>Release:        FreeBSD 8.0-STABLE amd64
>Organization:
n/a
>Environment:
System: FreeBSD server.vk2pj.dyndns.org 8.0-STABLE FreeBSD 8.0-STABLE #11: Mon Nov 30 16:36:34 EST 2009 root at server.vk2pj.dyndns.org:/var/obj/usr/src/sys/server amd64

>Description:
	ld-elf.so.1 records errors via _rtld_error() and can return the
	latest error to the application via dlerror().  If the application
	doesn't choose to report the error to the user, it can be almost
	impossible to determine why a program is failing - eg if a symbol
	if undefined.  The attached patch provides two mechanisms to
	access error messages independent of the application:
	1) A new environment variable LD_PRINT_ERROR causes _rtld_error()
	   to automatically log any message.
	2) Messages logged via _rtld_error() are passed to utrace() if
	   tracing is enabled (via LD_UTRACE).

>How-To-Repeat:

With the patch in place:
server% LD_PRINT_ERROR=x sh -c 'ls ~fred'
RTLD Error: Shared object "nss_files.so.1" not found, required by "sh"
RTLD Error: Shared object "nss_files.so.1" not found, required by "sh"
RTLD Error: Shared object "nss_dns.so.1" not found, required by "sh"
RTLD Error: Shared object "nss_dns.so.1" not found, required by "sh"
RTLD Error: Shared object "nss_dns.so.1" not found, required by "sh"
RTLD Error: Undefined symbol "_nss_cache_cycle_prevention_function"
ls: ~fred: No such file or directory
server%

(Note that the duplicated messages appear to be caused by multiple
identical calls to _rtld_error()).

>Fix:

Index: rtld.1
===================================================================
RCS file: /usr/ncvs/src/libexec/rtld-elf/rtld.1,v
retrieving revision 1.49.2.1
diff -u -r1.49.2.1 rtld.1
--- rtld.1	3 Aug 2009 08:13:06 -0000	1.49.2.1
+++ rtld.1	3 Jan 2010 06:15:22 -0000
@@ -154,6 +154,11 @@
 will be searched first
 followed by the set of built-in standard directories.
 This variable is unset for set-user-ID and set-group-ID programs.
+.It Ev LD_PRINT_ERROR
+When set to a nonempty string, causes
+.Nm
+to print any error messages that would be available to the application via
+.Xr dlopen 3 .
 .It Ev LD_BIND_NOW
 When set to a nonempty string, causes
 .Nm
Index: rtld.c
===================================================================
RCS file: /usr/ncvs/src/libexec/rtld-elf/rtld.c,v
retrieving revision 1.139.2.2
diff -u -r1.139.2.2 rtld.c
--- rtld.c	20 Oct 2009 13:26:58 -0000	1.139.2.2
+++ rtld.c	3 Jan 2010 06:24:14 -0000
@@ -164,6 +164,7 @@
 static char *ld_elf_hints_path;	/* Environment variable for alternative hints path */
 static char *ld_tracing;	/* Called from ldd to print libs */
 static char *ld_utrace;		/* Use utrace() to log events. */
+static char *ld_printerror;	/* Report _rtld_error() messages to stdout */
 static Obj_Entry *obj_list;	/* Head of linked list of shared objects */
 static Obj_Entry **obj_tail;	/* Link field of last object in list */
 static Obj_Entry *obj_main;	/* The main program shared object */
@@ -244,6 +245,10 @@
     (dlp)->num_alloc = obj_count,				\
     (dlp)->num_used = 0)
 
+/*
+ * The following macros and struct utrace_rtld must be kept aligned with
+ * the equivalent code in kdump.c
+ */
 #define	UTRACE_DLOPEN_START		1
 #define	UTRACE_DLOPEN_STOP		2
 #define	UTRACE_DLCLOSE_START		3
@@ -254,6 +259,7 @@
 #define	UTRACE_PRELOAD_FINISHED		8
 #define	UTRACE_INIT_CALL		9
 #define	UTRACE_FINI_CALL		10
+#define	UTRACE_RTLD_ERROR		11
 
 struct utrace_rtld {
 	char sig[4];			/* 'RTLD' */
@@ -384,6 +390,7 @@
 	(ld_elf_hints_path != NULL);
     ld_tracing = getenv(LD_ "TRACE_LOADED_OBJECTS");
     ld_utrace = getenv(LD_ "UTRACE");
+    ld_printerror = getenv(LD_ "PRINT_ERROR");
 
     if ((ld_elf_hints_path == NULL) || strlen(ld_elf_hints_path) == 0)
 	ld_elf_hints_path = _PATH_ELF_HINTS;
@@ -612,6 +619,9 @@
     vsnprintf(buf, sizeof buf, fmt, ap);
     error_message = buf;
     va_end(ap);
+    if (ld_printerror != NULL && ld_printerror != '\0')
+	printf("RTLD Error: %s\n", error_message);
+    LD_UTRACE(UTRACE_RTLD_ERROR, NULL, NULL, 0, 0, error_message);
 }
 
 /*
Index: kdump.c
===================================================================
RCS file: /usr/ncvs/src/usr.bin/kdump/kdump.c,v
retrieving revision 1.45.2.2
diff -u -r1.45.2.2 kdump.c
--- kdump.c	22 Nov 2009 16:13:16 -0000	1.45.2.2
+++ kdump.c	3 Jan 2010 06:21:51 -0000
@@ -1009,6 +1009,10 @@
 		cs->user ? "user" : "kernel");
 }
 
+/*
+ * The following macros and struct utrace_rtld must be kept aligned with
+ * the equivalent code in rtld.c
+ */
 #define	UTRACE_DLOPEN_START		1
 #define	UTRACE_DLOPEN_STOP		2
 #define	UTRACE_DLCLOSE_START		3
@@ -1019,6 +1023,7 @@
 #define	UTRACE_PRELOAD_FINISHED		8
 #define	UTRACE_INIT_CALL		9
 #define	UTRACE_FINI_CALL		10
+#define	UTRACE_RTLD_ERROR		11
 
 struct utrace_rtld {
 	char sig[4];				/* 'RTLD' */
@@ -1097,6 +1102,10 @@
 		printf("RTLD: fini %p for %p (%s)\n", ut->mapbase, ut->handle,
 		    ut->name);
 		break;
+	case UTRACE_RTLD_ERROR:
+		printf("RTLD: error: %s\n", ut->name);
+		break;
+
 	default:
 		p += 4;
 		len -= 4;
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list