changeset 223:7076f551faf5

- dynload mach-o handling fixes for 64bit platforms - dynload test code improvements - dynload(3) clarification
author Tassilo Philipp
date Sat, 15 Apr 2017 15:21:37 +0200
parents 700c67984c08
children 61fff73dbff8
files dynload/dynload.3 dynload/dynload_syms_mach-o.c test/dynload_plain/dynload_plain.c
diffstat 3 files changed, 35 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/dynload/dynload.3	Fri Apr 14 21:23:22 2017 +0200
+++ b/dynload/dynload.3	Sat Apr 15 15:21:37 2017 +0200
@@ -53,7 +53,7 @@
 .Ar pSymbolName
 in the library with handle
 .Ar pLib ,
-or returns a null pointer if the symbol cannot be found.
+or returns a null pointer if the symbol cannot be found. The name is specified as it would appear in C source code (mangled if C++, etc.).
 .Sh SEE ALSO
 .Xr dyncall 3 ,
 .Xr dyncallback 3
--- a/dynload/dynload_syms_mach-o.c	Fri Apr 14 21:23:22 2017 +0200
+++ b/dynload/dynload_syms_mach-o.c	Sat Apr 15 15:21:37 2017 +0200
@@ -45,12 +45,16 @@
 
 #if defined(ARCH_X64) || defined(ARCH_PPC64) || defined(ARCH_ARM64) /*@@@ use dyncall_macros.h*/
 #define MACH_HEADER_TYPE mach_header_64
+#define MACH_HEADER_MAGIC_NR MH_MAGIC_64
+#define SEGMEND_COMMAND_ID LC_SEGMENT_64
 #define SEGMENT_COMMAND segment_command_64
 #define NLIST_TYPE nlist_64
 #else
 #define MACH_HEADER_TYPE mach_header
+#define MACH_HEADER_MAGIC_NR MH_MAGIC
+#define SEGMEND_COMMAND_ID LC_SEGMENT
+#define SEGMENT_COMMAND segment_command
 #define NLIST_TYPE nlist
-#define SEGMENT_COMMAND segment_command
 #endif
 
 
@@ -66,10 +70,11 @@
 DLSyms* dlSymsInit(const char* libPath)
 {
 	DLLib* pLib;
-	DLSyms* pSyms;
+	DLSyms* pSyms = NULL;
 	uint32_t i, n;
 	struct stat st0;
 	const struct MACH_HEADER_TYPE* pHeader = NULL;
+	const struct dysymtab_command* dysymtab_cmd = NULL;
 
 	if(stat(libPath, &st0) == -1)
 		return NULL;
@@ -96,7 +101,7 @@
 		}
 	}
 
-	if(pHeader && (pHeader->filetype == MH_DYLIB) && !(pHeader->flags & MH_SPLIT_SEGS))
+	if(pHeader && (pHeader->magic == MACH_HEADER_MAGIC_NR) && (pHeader->filetype == MH_DYLIB) && !(pHeader->flags & MH_SPLIT_SEGS))
 	{
 		const char* pBase = (const char*)pHeader;
 		uintptr_t slide = 0;
@@ -104,7 +109,7 @@
 
 		for(i = 0, n = pHeader->ncmds; i < n; ++i, cmd = (const struct load_command*)((const char*)cmd + cmd->cmdsize))
 		{
-			if(cmd->cmd == LC_SEGMENT)
+			if(cmd->cmd == SEGMEND_COMMAND_ID)
 			{
 				const struct SEGMENT_COMMAND* seg = (struct SEGMENT_COMMAND*)cmd;
 				if((seg->fileoff == 0) && (seg->filesize != 0)) /* Count segment sizes to slide over...@@@? */
@@ -112,7 +117,7 @@
 				if(strcmp(seg->segname, "__LINKEDIT") == 0)
 					pBase = (const char*)(seg->vmaddr - seg->fileoff + slide); /* Adjust pBase depending on __LINKEDIT segment */
 			}
-			else if(cmd->cmd == LC_SYMTAB)
+			else if(cmd->cmd == LC_SYMTAB && !pSyms/* only init once - just safety check */)
 			{
 				const struct symtab_command* scmd = (const struct symtab_command*)cmd;
 
@@ -125,13 +130,29 @@
 				pSyms->pStringTable = pBase + scmd->stroff;
 				pSyms->pSymbolTable = (struct NLIST_TYPE*)(pBase + scmd->symoff);
 				pSyms->pLib         = pLib;
-
-				return pSyms;
+			}
+			else if(cmd->cmd == LC_DYSYMTAB)
+			{
+				dysymtab_cmd = (const struct dysymtab_command*)cmd;
+				/*@@@ check if(cmd->cmdsize != sizeof(struct dysymtab_command)) {
+					dlFreeMem....
+					break;
+				}*/
 			}
-            /*@@@ handle also LC_DYSYMTAB */
 		}
 	}
 
+	/* Got symbol table? */
+	if(pSyms) {
+		/* Alter symtable info if we got symbols organized in local/defined/undefined groups. */
+		/* Only use local ones in that case. */
+		/*@@@ don't restrict to only local symbols if(dysymtab_cmd) {
+			pSyms->pSymbolTable += dysymtab_cmd->ilocalsym;
+			pSyms->symbolCount = dysymtab_cmd->nlocalsym;
+		}*/
+		return pSyms;
+	}
+
 	/* Couldn't init syms, so free lib and return error. */
 	dlFreeLibrary(pLib);
 	return NULL;
--- a/test/dynload_plain/dynload_plain.c	Fri Apr 14 21:23:22 2017 +0200
+++ b/test/dynload_plain/dynload_plain.c	Sat Apr 15 15:21:37 2017 +0200
@@ -46,14 +46,17 @@
     "/lib32/libc.so",
     "/lib32/libc.so.6",
     "/lib32/libc.so.7",
+	"/usr/lib/system/libsystem_c.dylib",
     "/usr/lib/libc.dylib",
     "C:\\Windows\\system32\\msvcrt.dll"
   };
 
 
   for(i=0; i<(sizeof(clibs)/sizeof(const char*)); ++i) {
-    if(access(clibs[i], F_OK) != -1)
+    if(access(clibs[i], F_OK) != -1) {
       path = clibs[i];
+      break;
+    }
   }
 
   if(path) {
@@ -100,7 +103,7 @@
       }
       printf("printf symbol found by iteration: %d\n", i<n);
 
-      name = dlSymsName(pSyms, i);
+      name = (i<n) ? dlSymsName(pSyms, i) : NULL;
       r += (name && strcmp(name, "printf") == 0); // check if we can lookup "printf" by index
       printf("printf symbol name by index: %s\n", name?name:"");