--- main.d/scratchbox-utils-84/ldd.c	2005-06-07 10:44:08.000000000 +0300
+++ main.d/scratchbox-utils-84/ldd.c	2005-06-07 10:43:28.000000000 +0300
@@ -96,6 +96,11 @@
 #define ELFCLASSM    ELFCLASS32
 #endif
 
+/* This is just for getting ldd to compile */
+#if defined(__x86_64__)
+#define MATCH_MACHINE(x) (x == EM_X86_64)
+#define ELFCLASSM      ELFCLASS64
+#endif
 
 #ifndef MATCH_MACHINE
 #warning "You really should add a MATCH_MACHINE() macro for your architecture"
@@ -119,6 +124,7 @@
 char *interp_dir = NULL;
 int byteswap;
 static int interpreter_already_found=0;
+char *error_string = NULL;
 
 static inline uint32_t byteswap32_to_host(uint32_t value)
 {
@@ -129,7 +135,14 @@
 	}
 }
 
-
+static inline uint64_t byteswap64_to_host(uint64_t value)
+{
+	if (byteswap==1) {
+		return(bswap_64(value));
+	} else {
+		return(value);
+	}
+}
 
 static Elf32_Shdr * elf_find_section_type( int key, Elf32_Ehdr *ehdr)
 {
@@ -144,6 +157,19 @@
 	return NULL;
 }
 
+static Elf64_Shdr * elf_find_section_type64(int key, Elf64_Ehdr *ehdr)
+{
+	int j;
+	Elf64_Shdr *shdr;
+	shdr = (Elf64_Shdr *)(ehdr->e_shoff + (char *)ehdr);
+	for (j = ehdr->e_shnum; --j>=0; ++shdr) {
+		if (key==(int)byteswap32_to_host(shdr->sh_type)) {
+			return shdr;
+		}
+	}
+	return NULL;
+}
+
 static Elf32_Phdr * elf_find_phdr_type( int type, Elf32_Ehdr *ehdr)
 {
 	int j;
@@ -156,6 +182,18 @@
 	return NULL;
 }
 
+static Elf64_Phdr * elf_find_phdr_type64(int type, Elf64_Ehdr *ehdr)
+{
+	int j;
+	Elf64_Phdr *phdr = (Elf64_Phdr *)(ehdr->e_phoff + (char *)ehdr);
+	for (j = ehdr->e_phnum; --j>=0; ++phdr) {
+		if (type==(int)byteswap32_to_host(phdr->p_type)) {
+			return phdr;
+		}
+	}
+	return NULL;
+}
+
 /* Returns value if return_val==1, ptr otherwise */ 
 static void * elf_find_dynamic(int const key, Elf32_Dyn *dynp, 
 	Elf32_Ehdr *ehdr, int return_val)
@@ -173,6 +211,22 @@
 	return NULL;
 }
 
+static void * elf_find_dynamic64(int const key, Elf64_Dyn *dynp, 
+	Elf64_Ehdr *ehdr, int return_val)
+{
+	Elf64_Phdr *pt_text = elf_find_phdr_type64(PT_LOAD, ehdr);
+	unsigned tx_reloc = byteswap64_to_host(pt_text->p_vaddr) - byteswap64_to_host(pt_text->p_offset);
+	for (; DT_NULL!=byteswap64_to_host(dynp->d_tag); ++dynp) {
+		if (key == (int)byteswap64_to_host(dynp->d_tag)) {
+			if (return_val == 1)
+				return (void *)(intptr_t)byteswap64_to_host(dynp->d_un.d_val);
+			else
+				return (void *)(byteswap64_to_host(dynp->d_un.d_ptr) - tx_reloc + (char *)ehdr );
+		}
+	}
+	return NULL;
+}
+
 static int check_elf_header(Elf32_Ehdr *const ehdr)
 {
 	if (! ehdr || strncmp((void *)ehdr, ELFMAG, SELFMAG) != 0 ||  
@@ -210,6 +264,44 @@
 	return 0;
 }
 
+
+static int check_elf_header64(Elf64_Ehdr *const ehdr)
+{
+	if (! ehdr || strncmp((void *)ehdr, ELFMAG, SELFMAG) != 0 ||  
+			ehdr->e_ident[EI_CLASS] != ELFCLASS64 ||
+			ehdr->e_ident[EI_VERSION] != EV_CURRENT) 
+	{
+		return 1;
+	}
+
+	/* Check if the target endianness matches the host's endianness */
+	byteswap = 0;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+	if (ehdr->e_ident[5] == ELFDATA2MSB) {
+		/* Ick -- we will have to byte-swap everything */
+		byteswap = 1;
+	}
+#elif __BYTE_ORDER == __BIG_ENDIAN
+	if (ehdr->e_ident[5] == ELFDATA2LSB) {
+		/* Ick -- we will have to byte-swap everything */
+		byteswap = 1;
+	}
+#else
+#error Unknown host byte order!
+#endif
+	
+	/* Be vary lazy, and only byteswap the stuff we use */
+	if (byteswap==1) {
+		ehdr->e_type=bswap_16(ehdr->e_type);
+		ehdr->e_phoff=bswap_64(ehdr->e_phoff);
+		ehdr->e_shoff=bswap_64(ehdr->e_shoff);
+		ehdr->e_phnum=bswap_16(ehdr->e_phnum);
+		ehdr->e_shnum=bswap_16(ehdr->e_shnum);
+	}
+
+	return 0;
+}
+
 /* This function's behavior must exactly match that 
  * in uClibc/ldso/ldso/readelflib1.c */
 static void search_for_named_library(char *name, char *result, const char *path_list)
@@ -329,6 +421,81 @@
 	}
 }
 
+static void locate_library_file64(Elf64_Ehdr* ehdr, Elf64_Dyn* dynamic, int is_suid, struct library *lib)
+{
+	char *buf;
+	char *path;
+	struct stat filestat;
+	
+	/* If this is a fully resolved name, our job is easy */
+	if (stat (lib->name, &filestat) == 0) {
+		lib->path = lib->name;
+		return;
+	}
+
+	/* We need some elbow room here.  Make some room...*/
+	buf = malloc(1024);
+	if (!buf) {
+		fprintf(stderr, "Out of memory!\n");
+		exit(EXIT_FAILURE);
+	}
+
+	/* This function must match the behavior of _dl_load_shared_library
+	 * in readelflib1.c or things won't work out as expected... */
+
+	/* The ABI specifies that RPATH is searched first, so do that now.  */
+	path = (char *)elf_find_dynamic64(DT_RPATH, dynamic, ehdr, 0);
+	if (path) {
+		search_for_named_library(lib->name, buf, path);
+		if (*buf != '\0') {
+			lib->path = buf;
+			return;
+		}
+	}
+
+	/* Next check LD_{ELF_}LIBRARY_PATH if specified and allowed.
+	 * Since this app doesn't actually run an executable I will skip
+	 * the suid check, and just use LD_{ELF_}LIBRARY_PATH if set */
+	if (is_suid==1)
+		path = NULL;
+	else
+		path = getenv("LD_LIBRARY_PATH");
+	if (path) {
+		search_for_named_library(lib->name, buf, path);
+		if (*buf != '\0') {
+			lib->path = buf;
+			return;
+		}
+	}
+
+#ifdef USE_CACHE
+	/* FIXME -- add code to check the Cache here */ 
+#endif
+
+
+	/* Next look for libraries wherever the shared library 
+	 * loader was installed -- this is usually where we
+	 * should find things... */
+	if (interp_dir) {
+		search_for_named_library(lib->name, buf, interp_dir);
+		if (*buf != '\0') {
+			lib->path = buf;
+			return;
+		}
+	}
+
+	/* Lastly, search the standard list of paths for the library.
+	   This list must exactly match the list in uClibc/ldso/ldso/readelflib1.c */
+	path =	"/usr/X11R6/lib:/usr/lib:/lib";
+	search_for_named_library(lib->name, buf, path);
+	if (*buf != '\0') {
+		lib->path = buf;
+	} else { 
+		free(buf);
+		lib->path = not_found;
+	}
+}
+
 static int add_library(Elf32_Ehdr* ehdr, Elf32_Dyn* dynamic, int is_setuid, char *s)
 {
 	char *tmp, *tmp1, *tmp2;
@@ -390,6 +557,66 @@
 }
 
 
+static int add_library64(Elf64_Ehdr* ehdr, Elf64_Dyn* dynamic, int is_setuid, char *s)
+{
+	char *tmp, *tmp1, *tmp2;
+	struct library *cur, *newlib=lib_list;
+
+	if (!s || !strlen(s))
+		return 1;
+
+	tmp = s; 
+	while (*tmp) {
+		if (*tmp == '/')
+			s = tmp + 1;
+		tmp++;
+	}
+
+	/* We add libc.so.0 elsewhere */
+	if (interpreter_already_found && (tmp=strrchr(interp, '/')) != NULL)
+	{
+		int len = strlen(interp_dir);
+		if (strcmp(s, interp+1+len)==0)
+			return 1;
+	}
+
+	for (cur = lib_list; cur; cur=cur->next) {
+		/* Check if this library is already in the list */
+		tmp1 = tmp2 = cur->name; 
+		while (*tmp1) {
+			if (*tmp1 == '/')
+				tmp2 = tmp1 + 1;
+			tmp1++;
+		}
+		if(strcmp(tmp2, s)==0) {
+			//printf("find_elf_interpreter is skipping '%s' (already in list)\n", cur->name);
+			return 0;
+		}
+	}
+
+	/* Ok, this lib needs to be added to the list */
+	newlib = malloc(sizeof(struct library));
+	if (!newlib)
+		return 1;
+	newlib->name = malloc(strlen(s)+1);
+	strcpy(newlib->name, s);
+	newlib->resolved = 0;
+	newlib->path = NULL;
+	newlib->next = NULL;
+
+	/* Now try and locate where this library might be living... */
+	locate_library_file64(ehdr, dynamic, is_setuid, newlib);
+
+	//printf("add_library is adding '%s' to '%s'\n", newlib->name, newlib->path);
+	if (!lib_list) {
+		lib_list = newlib;
+	} else {
+		for (cur = lib_list;  cur->next; cur=cur->next); /* nothing */
+		cur->next = newlib;
+	}
+	return 0;
+}
+
 static void find_needed_libraries(Elf32_Ehdr* ehdr, Elf32_Dyn* dynamic, char *strtab, int is_setuid)
 {
 	Elf32_Dyn  *dyns;
@@ -400,8 +627,20 @@
 					(char*)strtab + byteswap32_to_host(dyns->d_un.d_val));
 		}
 	}
+}  
+
+static void find_needed_libraries64(Elf64_Ehdr* ehdr, Elf64_Dyn* dynamic, char *strtab, int is_setuid)
+{
+	Elf64_Dyn  *dyns;
+
+	for (dyns=dynamic; byteswap64_to_host(dyns->d_tag)!=DT_NULL; ++dyns) {
+		if (DT_NEEDED == byteswap64_to_host(dyns->d_tag)) {
+			add_library64(ehdr, dynamic, is_setuid, 
+					(char*)strtab + byteswap64_to_host(dyns->d_un.d_val));
+		}
+	}
 }
-    
+
 static struct library * find_elf_interpreter(Elf32_Ehdr* ehdr)
 {
 	Elf32_Phdr *phdr;
@@ -464,6 +703,69 @@
 	return NULL;
 }
 
+
+static struct library * find_elf_interpreter64(Elf64_Ehdr* ehdr)
+{
+	Elf64_Phdr *phdr;
+
+	if (interpreter_already_found==1)
+		return NULL;
+	phdr = elf_find_phdr_type64(PT_INTERP, ehdr);
+	if (phdr) {
+		struct library *cur, *newlib=NULL;
+		char *s = (char*)ehdr + byteswap64_to_host(phdr->p_offset);
+	
+		char *tmp, *tmp1;
+		interp = strdup(s);
+		interp_dir = strdup(s);
+		tmp = strrchr(interp_dir, '/');
+		if (*tmp)
+			*tmp = '\0';
+		else {
+			free(interp_dir);
+			interp_dir = interp;
+		}
+		tmp1 = tmp = s;
+		while (*tmp) {
+			if (*tmp == '/')
+				tmp1 = tmp + 1;
+			tmp++;
+		}
+		for (cur = lib_list; cur; cur=cur->next) {
+			/* Check if this library is already in the list */
+			if(strcmp(cur->name, tmp1)==0) {
+				//printf("find_elf_interpreter is replacing '%s' (already in list)\n", cur->name);
+				newlib = cur;
+				free(newlib->name);
+				free(newlib->path);
+				return NULL;
+			}
+		}
+		if (newlib == NULL)
+			newlib = malloc(sizeof(struct library));
+		if (!newlib)
+			return NULL;
+		newlib->name = malloc(strlen(s)+1);
+		strcpy(newlib->name, s);
+		newlib->path = newlib->name;
+		newlib->resolved = 1;
+		newlib->next = NULL;
+	
+#if 0
+		//printf("find_elf_interpreter is adding '%s' to '%s'\n", newlib->name, newlib->path);
+		if (!lib_list) {
+			lib_list = newlib;
+		} else {
+			for (cur = lib_list;  cur->next; cur=cur->next); /* nothing */
+			cur->next = newlib;
+		}
+#endif
+		interpreter_already_found=1;
+		return newlib;
+	}
+	return NULL;
+}
+
 /* map the .so, and locate interesting pieces */
 int find_dependancies(char* filename)
 {
@@ -475,7 +777,7 @@
 	Elf32_Shdr *dynsec = NULL;
 	Elf32_Dyn *dynamic = NULL;
 	struct library *interp;
-
+	
 	if (filename == not_found)
 		return 0;
 
@@ -499,18 +801,20 @@
 		goto foo;
 
 	/* mmap the file to make reading stuff from it effortless */
-	ehdr = (Elf32_Ehdr *)mmap(0, statbuf.st_size, 
+    ehdr = (Elf32_Ehdr *) mmap(0, statbuf.st_size, 
 			PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(thefile), 0);
 
 foo:
 	/* Check if this looks like a legit ELF file */
 	if (check_elf_header(ehdr)) {
-		fprintf(stderr, "%s: not an ELF file.\n", filename);
+		error_string = strdup("%s: not an ELF file.\n");
+		/*fprintf(stderr, "%s: not an ELF file.\n", filename);*/
 		return -1;
 	}
 	/* Check if this is the right kind of ELF file */
 	if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) {
-		fprintf(stderr, "%s: not a dynamic executable\n", filename);
+		error_string = strdup("%s: not a dynamic executable\n");
+		/*fprintf(stderr, "%s: not a dynamic executable\n", filename);*/
 		return -1;
 	}
 	if (ehdr->e_type == ET_EXEC) {
@@ -575,6 +879,121 @@
 }
 
 
+/* map the .so, and locate interesting pieces */
+int find_dependancies64(char* filename)
+{
+	int is_suid = 0;
+	FILE *thefile;
+	struct stat statbuf;
+	char *dynstr=NULL;
+	Elf64_Ehdr *ehdr = NULL;
+	Elf64_Shdr *dynsec = NULL;
+	Elf64_Dyn *dynamic = NULL;
+	struct library *interp;
+
+	if (filename == not_found)
+		return 0;
+
+	if (!filename) {
+		fprintf(stderr, "No filename specified.\n");
+		return -1;
+	}
+	if (!(thefile = fopen(filename, "r"))) {
+		perror(filename);
+		return -1;
+	}
+	if (fstat(fileno(thefile), &statbuf) < 0) {
+		perror(filename);
+		return -1;
+	}
+
+	if ((size_t)statbuf.st_size < sizeof(Elf64_Ehdr))
+		goto foo;
+
+	if (!S_ISREG(statbuf.st_mode))
+		goto foo;
+
+	/* mmap the file to make reading stuff from it effortless */
+    ehdr = (Elf64_Ehdr *) mmap(0, statbuf.st_size, 
+			PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(thefile), 0);
+
+foo:
+	/* Check if this looks like a legit ELF file */
+	if (check_elf_header64(ehdr)) {
+		if (error_string)
+			fprintf(stderr, error_string, filename);
+		else
+			fprintf(stderr, "%s: not an ELF file.\n", filename);	
+		return -1;
+	}
+	/* Check if this is the right kind of ELF file */
+	if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) {
+		if (error_string)
+			fprintf(stderr, error_string, filename);
+		else
+			fprintf(stderr, "%s: not a dynamic executable\n", filename);
+		return -1;
+	}
+	if (ehdr->e_type == ET_EXEC) {
+		if (statbuf.st_mode & S_ISUID)
+			is_suid = 1;
+		if ((statbuf.st_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))
+			is_suid = 1;
+#if 0
+		/* FIXME */
+		if (is_suid)
+			fprintf(stderr, "%s: is setuid\n", filename);
+#endif
+	}
+
+	interpreter_already_found=0;
+	interp = find_elf_interpreter64(ehdr);
+			
+#if 1
+	if (interp && ehdr->e_type == ET_EXEC && 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)) {
+			pid_t pid;
+			int status;
+			static const char * const environment[] = {
+				"PATH=/usr/bin:/bin:/usr/sbin:/sbin",
+				"SHELL=/bin/sh",
+				"LD_TRACE_LOADED_OBJECTS=1",
+				NULL
+			};
+
+			if ((pid = fork()) == 0) {
+				/* Cool, it looks like we should be able to actually 
+				 * run this puppy.  Do so now... */
+				execle(filename, filename, NULL, environment);
+				_exit(0xdead);
+			}
+
+			/* Wait till it returns */
+			waitpid(pid, &status, 0);
+			if (WIFEXITED(status) && WEXITSTATUS(status)==0) {
+				return 1;
+			}
+
+			/* If the exec failed, we fall through to trying to find
+			 * all the needed libraries ourselves by rummaging about
+			 * in the ELF headers... */
+		}
+	}
+#endif
+
+	dynsec = elf_find_section_type64(SHT_DYNAMIC, ehdr);
+	if (dynsec) {
+		dynamic = (Elf64_Dyn*)(byteswap64_to_host(dynsec->sh_offset) + (intptr_t)ehdr);
+		dynstr = (char *)elf_find_dynamic64(DT_STRTAB, dynamic, ehdr, 0);
+		find_needed_libraries64(ehdr, dynamic, dynstr, is_suid);
+	}
+	
+	return 0;
+}
 
 int main( int argc, char** argv)
 {
@@ -582,6 +1001,7 @@
 	int got_em_all=1;
 	char *filename = NULL;
 	struct library *cur;
+	int bin64 = 0;
 
 	if (argc < 2) {
 		fprintf(stderr, "ldd: missing file arguments\n");
@@ -617,8 +1037,13 @@
 		}
 
 		if (find_dependancies(filename)!=0)
-			continue;
-
+		{
+		    if (find_dependancies64(filename)!=0)
+			    continue;
+		    else
+				bin64 = 1;
+		}
+		
 		while(got_em_all) {
 			got_em_all=0;
 			/* Keep walking the list till everybody is resolved */
@@ -626,7 +1051,10 @@
 				if (cur->resolved == 0 && cur->path) {
 					got_em_all=1;
 					//printf("checking sub-depends for '%s\n", cur->path);
-					find_dependancies(cur->path);
+					if (bin64)
+						find_dependancies64(cur->path);
+					else
+					    find_dependancies(cur->path);
 					cur->resolved = 1;
 				}
 			}
@@ -654,6 +1082,9 @@
 		lib_list=NULL;
 	}
 
+	if (error_string)
+		free(error_string);
+	
 	return 0;
 }
 
