Browse Source

Teach ldd to act just the glibc provided one (relying on the
shared lib loader to do the work) when it is possible to do
so, and only go poking about through the ELF headers when that
fails so we can still use 'ldd' on cross compiled stuff.
-Erik

Eric Andersen 21 years ago
parent
commit
23b0e13d2e
3 changed files with 106 additions and 37 deletions
  1. 13 30
      ldso/ldso/ldso.c
  2. 6 2
      ldso/util/Makefile
  3. 87 5
      ldso/util/ldd.c

+ 13 - 30
ldso/ldso/ldso.c

@@ -931,21 +931,18 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 #ifdef __LDSO_LDD_SUPPORT__
 					if (_dl_trace_loaded_objects)
 						_dl_dprintf(1, "\t%s => not found\n", str);
-					else {
+					else 
 #endif
-						_dl_dprintf(2, "%s: can't load "
-								"library '%s'\n", _dl_progname, str);
+					{
+						_dl_dprintf(2, "%s: can't load " "library '%s'\n", _dl_progname, str);
 						_dl_exit(15);
-#ifdef __LDSO_LDD_SUPPORT__
 					}
-#endif
 				} else {
 #ifdef __SUPPORT_LD_DEBUG_EARLY__
 					_dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
 #endif
 #ifdef __LDSO_LDD_SUPPORT__
-					if (_dl_trace_loaded_objects
-							&& tpnt1->usage_count==1) {
+					if (_dl_trace_loaded_objects && tpnt1->usage_count==1) {
 						/* this is a real hack to make ldd not print 
 						 * the library itself when run on a library. */
 						if (_dl_strcmp(_dl_progname, str) != 0)
@@ -1010,21 +1007,18 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 #ifdef __LDSO_LDD_SUPPORT__
 							if (_dl_trace_loaded_objects)
 								_dl_dprintf(1, "\t%s => not found\n", cp2);
-							else {
+							else 
 #endif
-								_dl_dprintf(2, "%s: can't load library '%s'\n", 
-										_dl_progname, cp2);
+							{
+								_dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, cp2);
 								_dl_exit(15);
-#ifdef __LDSO_LDD_SUPPORT__
 							}
-#endif
 						} else {
 #ifdef __SUPPORT_LD_DEBUG_EARLY__
 							_dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
 #endif
 #ifdef __LDSO_LDD_SUPPORT__
-							if (_dl_trace_loaded_objects
-									&& tpnt1->usage_count==1) {
+							if (_dl_trace_loaded_objects && tpnt1->usage_count==1) {
 								_dl_dprintf(1, "\t%s => %s (0x%x)\n", cp2, 
 										tpnt1->libname, (unsigned) tpnt1->loadaddr);
 							}
@@ -1086,13 +1080,12 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 #ifdef __LDSO_LDD_SUPPORT__
 					if (_dl_trace_loaded_objects)
 						_dl_dprintf(1, "\t%s => not found\n", lpntstr);
-					else {
+					else 
 #endif
+					{
 						_dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, lpntstr);
 						_dl_exit(16);
-#ifdef __LDSO_LDD_SUPPORT__
 					}
-#endif
 				} else {
 #ifdef __SUPPORT_LD_DEBUG_EARLY__
 					_dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
@@ -1111,15 +1104,6 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 #ifdef USE_CACHE
 	_dl_unmap_cache();
 #endif
-	/* ldd uses uses this.  I am not sure how you pick up the other flags */
-#ifdef __LDSO_LDD_SUPPORT__
-	if (_dl_trace_loaded_objects) {
-		char *_dl_warn = 0;
-		_dl_warn = _dl_getenv("LD_WARN", envp);
-		if (!_dl_warn)
-			_dl_exit(0);
-	}
-#endif
 
 	/*
 	 * If the program interpreter is not in the module chain, add it.  This will
@@ -1154,7 +1138,9 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 		rpnt->dyn = tpnt;
 		tpnt = NULL;
 	}
+
 #ifdef __LDSO_LDD_SUPPORT__
+	/* End of the line for ldd.... */
 	if (_dl_trace_loaded_objects) {
 		_dl_dprintf(1, "\t%s => %s (0x%x)\n", rpnt->dyn->libname + (_dl_strlen(_dl_ldsopath)) + 1, 
 				rpnt->dyn->libname, rpnt->dyn->loadaddr);  
@@ -1162,6 +1148,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 	}
 #endif
 
+
 #ifdef __mips__
 	/*
 	 * Relocation of the GOT entries for MIPS have to be done
@@ -1190,10 +1177,6 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 #endif
 	if (_dl_symbol_tables)
 		goof += _dl_copy_fixups(_dl_symbol_tables);
-#ifdef __LDSO_LDD_SUPPORT__
-	if (goof || _dl_trace_loaded_objects)
-		_dl_exit(0);
-#endif
 
 	/* OK, at this point things are pretty much ready to run.  Now we
 	   need to touch up a few items that are required, and then

+ 6 - 2
ldso/util/Makefile

@@ -33,6 +33,10 @@ TARGETS += ldconfig
 endif
 all: $(TARGETS)
 
+ifeq ($(strip $(LDSO_LDD_SUPPORT)),y)
+XXFLAGS=-D__LDSO_LDD_SUPPORT
+endif
+
 elf_header:
 	ln -fs $(TOPDIR)include/elf.h
 
@@ -58,7 +62,7 @@ ldconfig: ldconfig.o readsoname.o
 	strip -x -R .note -R .comment $@
 
 ldd: ldd.c
-	$(HOSTCC) $(HOSTCFLAGS) -DUCLIBC_TARGET_PREFIX=\"$(TARGET_PREFIX)\" \
+	$(HOSTCC) $(HOSTCFLAGS) $(XXFLAGS) -DUCLIBC_TARGET_PREFIX=\"$(TARGET_PREFIX)\" \
 		-DUCLIBC_DEVEL_PREFIX=\"$(DEVEL_PREFIX)\" \
 		-DUCLIBC_BUILD_DIR=\"$(shell cd $(TOPDIR) && pwd)\" \
 		-DUCLIBC_LDSO=\"$(UCLIBC_LDSO)\" -I . \
@@ -66,7 +70,7 @@ ldd: ldd.c
 	strip -x -R .note -R .comment $@
 
 ldd.target: ldd.c
-	$(TARGET_CC) $(CFLAGS) -Wl,-s -DUCLIBC_TARGET_PREFIX=\"$(TARGET_PREFIX)\" \
+	$(TARGET_CC) $(CFLAGS) $(XXFLAGS) -Wl,-s -DUCLIBC_TARGET_PREFIX=\"$(TARGET_PREFIX)\" \
 		-DUCLIBC_DEVEL_PREFIX=\"$(DEVEL_PREFIX)\" \
 		-DUCLIBC_BUILD_DIR=\"$(shell cd $(TOPDIR) && pwd)\" \
 		-DUCLIBC_LDSO=\"$(UCLIBC_LDSO)\" \

+ 87 - 5
ldso/util/ldd.c

@@ -49,6 +49,59 @@
 #include <dmalloc.h>
 #endif
 
+#if defined(__arm__)
+#define MATCH_MACHINE(x) (x == EM_ARM)
+#define ELFCLASSM	ELFCLASS32
+#endif
+
+#if defined(__s390__)
+#define MATCH_MACHINE(x) (x == EM_S390)
+#define ELFCLASSM	ELFCLASS32
+#endif
+
+#if defined(__i386__)
+#ifndef EM_486
+#define MATCH_MACHINE(x) (x == EM_386)
+#else
+#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
+#endif
+#define ELFCLASSM	ELFCLASS32
+#endif
+
+#if defined(__mc68000__) 
+#define MATCH_MACHINE(x) (x == EM_68K)
+#define ELFCLASSM	ELFCLASS32
+#endif
+
+#if defined(__mips__)
+#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
+#define ELFCLASSM	ELFCLASS32
+#endif
+
+#if defined(__powerpc__)
+#define MATCH_MACHINE(x) (x == EM_PPC)
+#define ELFCLASSM	ELFCLASS32
+#endif
+
+#if defined(__sh__)
+#define MATCH_MACHINE(x) (x == EM_SH)
+#endif
+
+#if defined (__v850e__)
+#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
+#define ELFCLASSM	ELFCLASS32
+#endif
+
+#ifndef MATCH_MACHINE
+#warning "You really should add a MATCH_MACHINE() macro for your architecture"
+#endif
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define ELFDATAM	ELFDATA2LSB
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define ELFDATAM	ELFDATA2MSB
+#endif
+
 struct library {
 	char *name;
 	int resolved;
@@ -132,6 +185,7 @@ int check_elf_header(Elf32_Ehdr *const ehdr)
 	}
 #elif __BYTE_ORDER == __BIG_ENDIAN
 	if (ehdr->e_ident[5] == ELFDATA2LSB) {
+		/* Ick -- we will have to byte-swap everything */
 		byteswap = 1;
 	}
 #else
@@ -347,13 +401,14 @@ static void find_needed_libraries(Elf32_Ehdr* ehdr, Elf32_Dyn* dynamic, char *st
 	}
 }
     
-static void find_elf_interpreter(Elf32_Ehdr* ehdr, Elf32_Dyn* dynamic, char *strtab, int is_setuid)
+static struct library * 
+find_elf_interpreter(Elf32_Ehdr* ehdr, Elf32_Dyn* dynamic, char *strtab, int is_setuid)
 {
 	static int been_there_done_that=0;
 	Elf32_Phdr *phdr;
 
 	if (been_there_done_that==1)
-		return;
+		return NULL;
 	been_there_done_that=1;
 	phdr = elf_find_phdr_type(PT_INTERP, ehdr);
 	if (phdr) {
@@ -383,13 +438,13 @@ static void find_elf_interpreter(Elf32_Ehdr* ehdr, Elf32_Dyn* dynamic, char *str
 				newlib = cur;
 				free(newlib->name);
 				free(newlib->path);
-				return;
+				return NULL;
 			}
 		}
 		if (newlib == NULL)
 			newlib = malloc(sizeof(struct library));
 		if (!newlib)
-			return;
+			return NULL;
 		newlib->name = malloc(strlen(s)+1);
 		strcpy(newlib->name, s);
 		newlib->path = newlib->name;
@@ -405,7 +460,9 @@ static void find_elf_interpreter(Elf32_Ehdr* ehdr, Elf32_Dyn* dynamic, char *str
 			cur->next = newlib;
 		}
 #endif
+		return newlib;
 	}
+	return NULL;
 }
 
 /* map the .so, and locate interesting pieces */
@@ -418,6 +475,7 @@ int find_dependancies(char* filename)
 	Elf32_Ehdr *ehdr = NULL;
 	Elf32_Shdr *dynsec = NULL;
 	Elf32_Dyn *dynamic = NULL;
+	struct library *interp;
 
 	if (filename == not_found)
 		return 0;
@@ -464,7 +522,31 @@ foo:
 	}
 
 	dynsec = elf_find_section_type(SHT_DYNAMIC, ehdr);
-	find_elf_interpreter(ehdr, dynamic, dynstr, is_suid);
+	interp = find_elf_interpreter(ehdr, dynamic, dynstr, is_suid);
+			
+#ifdef __LDSO_LDD_SUPPORT
+	if (interp && ehdr->e_ident[EI_CLASS] == ELFCLASSM && ehdr->e_ident[EI_DATA] == ELFDATAM
+		&& ehdr->e_ident[EI_VERSION] == EV_CURRENT && MATCH_MACHINE(ehdr->e_machine)) 
+	{
+		struct stat statbuf;
+		if (stat(interp->path, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) {
+			static const char * const environment[] = {
+				"PATH=/usr/bin:/bin:/usr/sbin:/sbin",
+				"SHELL=/bin/sh",
+				"LD_TRACE_LOADED_OBJECTS=1",
+				NULL
+			};
+			/* Cool, it looks like we should be able to actually 
+			 * run this puppy.  Do so now... */
+			execle(filename, filename, NULL, environment);
+
+			/* If the exec failed, we fall through to trying to find
+			 * all the needed libraries ourselves by rummaging about
+			 * in the ELF headers... */
+		}
+	}
+#endif
+
 	if (dynsec) {
 		dynamic = (Elf32_Dyn*)(byteswap32_to_host(dynsec->sh_offset) + (intptr_t)ehdr);
 		dynstr = (char *)elf_find_dynamic(DT_STRTAB, dynamic, ehdr, 0);