History

(merge) macOS11+ dynamic linker support

Sushant Pandurangi committed 5 years ago

Commit 588d64c2 parents c4a2c52 cca4ece3 files · +160 −22Browse files

Unified · Split

3 files
  1. libtcc.c +45 −6
  2. tcc.h +10 −0
  3. tccmacho.c +105 −16
libtcc.c+45−6
@@ -855,6 +855,29 @@ LIBTCCAPI void tcc_delete(TCCState *s1) · 854 unmodified lines
855855 #endif
856856 }
857857
858+/* Looks for the active developer SDK set by xcode-select (or the default
859+ one set during installation.) */
860+#define SZPAIR(s) s "", sizeof(s)-1
861+ST_FUNC int tcc_add_macos_sdkpath(TCCState* s)
862+{
863+ char *sdkroot = NULL, *pos = NULL;
864+ void* xcs = dlopen("libxcselect.dylib", RTLD_GLOBAL | RTLD_LAZY);
865+ CString path = {};
866+ int (*f)(unsigned int, char**) = dlsym(xcs, "xcselect_host_sdk_path");
867+
868+ if (f) f(1, &sdkroot);
869+ if (!sdkroot) return -1;
870+ pos = strstr(sdkroot,"SDKs/MacOSX");
871+ if (!pos) return -1;
872+ cstr_cat(&path, sdkroot, pos-sdkroot);
873+ cstr_cat(&path, SZPAIR("SDKs/MacOSX.sdk/usr/lib\0") );
874+ tcc_add_library_path(s, (char*)path.data);
875+ cstr_free(&path);
876+ tcc_free(sdkroot);
877+ return 0;
878+}
879+#undef SZPAIR
880+
858881 LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
859882 {
860883 s->output_type = output_type;
@@ -881,7 +904,11 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) · 20 unmodified lines
881904 }
882905
883906 tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);
884−
907+#ifdef TCC_TARGET_MACHO
908+ if (tcc_add_macos_sdkpath(s) != 0) {
909+ tcc_add_library_path(s, CONFIG_OSX_SDK_FALLBACK);
910+ }
911+#endif
885912 #ifdef TCC_TARGET_PE
886913 # ifdef _WIN32
887914 if (!s->nostdlib && output_type != TCC_OUTPUT_OBJ)
@@ -979,6 +1006,10 @@ static int tcc_glob_so(TCCState *s1, const char *pattern, char *buf, int size) · 91 unmodified lines
9791006 }
9801007 #endif
9811008
1009+#ifdef TCC_TARGET_MACHO
1010+ST_FUNC const char* macho_tbd_soname(const char* filename);
1011+#endif
1012+
9821013 ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9831014 {
9841015 int fd, ret = -1;
@@ -1006,7 +1037,9 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) · 21 unmodified lines
10061037 lseek(fd, 0, SEEK_SET);
10071038
10081039 #ifdef TCC_TARGET_MACHO
1009− if (0 == obj_type && 0 == strcmp(tcc_fileextension(filename), ".dylib"))
1040+ if (0 == obj_type
1041+ && (0 == strcmp(tcc_fileextension(filename), ".dylib")
1042+ || 0 == strcmp(tcc_fileextension(filename), ".tbd")))
10101043 obj_type = AFF_BINTYPE_DYN;
10111044 #endif
10121045
@@ -1027,9 +1060,15 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) · 14 unmodified lines
10271060 case AFF_BINTYPE_DYN:
10281061 if (s1->output_type == TCC_OUTPUT_MEMORY) {
10291062 #ifdef TCC_IS_NATIVE
1030− void *dl = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
1063+ void* dl;
1064+ const char* soname = filename;
1065+# ifdef TCC_TARGET_MACHO
1066+ if (!strcmp(tcc_fileextension(filename), ".tbd"))
1067+ soname = macho_tbd_soname(filename);
1068+# endif
1069+ dl = dlopen(soname, RTLD_GLOBAL | RTLD_LAZY);
10311070 if (dl) {
1032− tcc_add_dllref(s1, filename)->handle = dl;
1071+ tcc_add_dllref(s1, soname)->handle = dl;
10331072 ret = 0;
10341073 }
10351074 #endif
@@ -1142,8 +1181,8 @@ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname) · 106 unmodified lines
11421181 static const char * const libs[] = { "%s/%s.def", "%s/lib%s.def", "%s/%s.dll", "%s/lib%s.dll", "%s/lib%s.a", NULL };
11431182 const char * const *pp = s->static_link ? libs + 4 : libs;
11441183 #elif defined TCC_TARGET_MACHO
1145− static const char * const libs[] = { "%s/lib%s.dylib", "%s/lib%s.a", NULL };
1146− const char * const *pp = s->static_link ? libs + 1 : libs;
1184+ static const char * const libs[] = { "%s/lib%s.dylib", "%s/lib%s.tbd", "%s/lib%s.a", NULL };
1185+ const char * const *pp = s->static_link ? libs + 2 : libs;
11471186 #elif defined TARGETOS_OpenBSD
11481187 static const char * const libs[] = { "%s/lib%s.so.*", "%s/lib%s.a", NULL };
11491188 const char * const *pp = s->static_link ? libs + 1 : libs;
tcc.h+10−0
@@ -42,6 +42,7 @@ · 41 unmodified lines
4242 #ifndef _WIN32
4343 # include <unistd.h>
4444 # include <sys/time.h>
45+# include <sys/stat.h>
4546 # ifndef CONFIG_TCC_STATIC
4647 # include <dlfcn.h>
4748 # endif
@@ -278,6 +279,15 @@ extern long double strtold (const char *__nptr, char **__endptr); · 230 unmodified lines
278279 ALSO_TRIPLET(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR) \
279280 ":" ALSO_TRIPLET(CONFIG_SYSROOT "/" CONFIG_LDDIR) \
280281 ":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR)
282+# ifdef TCC_TARGET_MACHO
283+# define CONFIG_OSX_SDK1 \
284+ "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk"
285+# define CONFIG_OSX_SDK2 \
286+ "/Applications/Xcode.app/Developer/SDKs/MacOSX.sdk"
287+# define CONFIG_OSX_SDK_FALLBACK \
288+ ALSO_TRIPLET(CONFIG_OSX_SDK1 "/usr/" CONFIG_LDDIR) \
289+ ":" ALSO_TRIPLET(CONFIG_OSX_SDK2 "/usr/" CONFIG_LDDIR)
290+# endif
281291 # endif
282292 #endif
283293
tccmacho.c+105−16
@@ -837,7 +837,102 @@ static uint32_t macho_swap32(uint32_t x) · 836 unmodified lines
837837 }
838838 #define SWAP(x) (swap ? macho_swap32(x) : (x))
839839
840−ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev)
840+ST_FUNC int macho_add_dllref(TCCState* s1, int lev, const char* soname)
841+{
842+ /* if the dll is already loaded, do not load it */
843+ DLLReference *dllref;
844+ int i;
845+ for(i = 0; i < s1->nb_loaded_dlls; i++) {
846+ dllref = s1->loaded_dlls[i];
847+ if (!strcmp(soname, dllref->name)) {
848+ /* but update level if needed */
849+ if (lev < dllref->level)
850+ dllref->level = lev;
851+ return -1;
852+ }
853+ }
854+ dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
855+ dllref->level = lev;
856+ strcpy(dllref->name, soname);
857+ dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
858+ return 0;
859+}
860+
861+#define tbd_parse_movepast(s) \
862+ (pos = (pos = strstr(pos, s)) ? pos + strlen(s) : NULL)
863+#define tbd_parse_movetoany(cs) (pos = strpbrk(pos, cs))
864+#define tbd_parse_skipws while (*pos && (*pos==' '||*pos=='\n')) ++pos
865+#define tbd_parse_tramplequote if(*pos=='\''||*pos=='"') tbd_parse_trample
866+#define tbd_parse_tramplespace if(*pos==' ') tbd_parse_trample
867+#define tbd_parse_trample *pos++=0
868+
869+ST_FUNC const char* macho_tbd_soname(const char* filename) {
870+ char *soname, *data, *pos, *ret;
871+ struct stat sb;
872+ int fd = open(filename,O_RDONLY);
873+ if (fd<0) return filename;
874+ fstat(fd,&sb);
875+ data = load_data(fd, 0, sb.st_size+1);
876+ data[sb.st_size]=0;
877+ pos = data;
878+
879+ if (!tbd_parse_movepast("install-name: ")) return filename;
880+ tbd_parse_skipws;
881+ tbd_parse_tramplequote;
882+ soname = pos;
883+ if (!tbd_parse_movetoany("\n \"'")) return filename;
884+ tbd_parse_trample;
885+ ret = tcc_mallocz(strlen(soname)+1);
886+ strcpy(ret, soname);
887+ // soname = strdup(soname);
888+ tcc_free(data);
889+ return ret;
890+}
891+
892+ST_FUNC int macho_load_tbd(TCCState* s1, int fd, const char* filename, int lev)
893+{
894+ char *soname, *data, *pos;
895+
896+ struct stat sb;
897+ fstat(fd,&sb);
898+ data = load_data(fd, 0, sb.st_size+1);
899+ data[sb.st_size]=0;
900+ pos = data;
901+
902+ if (!tbd_parse_movepast("install-name: ")) return -1;
903+ tbd_parse_skipws;
904+ tbd_parse_tramplequote;
905+ soname = pos;
906+ if (!tbd_parse_movetoany("\n \"'")) return -1;
907+ tbd_parse_trample;
908+ if (macho_add_dllref(s1, lev, soname) != 0) goto the_end;
909+
910+ while(pos) {
911+ char* sym = NULL;
912+ int cont = 1;
913+ if (!tbd_parse_movepast("symbols: ")) break;
914+ if (!tbd_parse_movepast("[")) break;
915+ while (cont) {
916+ tbd_parse_skipws;
917+ tbd_parse_tramplequote;
918+ sym = pos;
919+ if (!tbd_parse_movetoany(",] \"'")) break;
920+ tbd_parse_tramplequote;
921+ tbd_parse_tramplespace;
922+ tbd_parse_skipws;
923+ if (*pos==0||*pos==']') cont=0;
924+ tbd_parse_trample;
925+ set_elf_sym(s1->dynsymtab_section, 0, 0,
926+ ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, SHN_UNDEF, sym);
927+ }
928+ }
929+
930+the_end:
931+ tcc_free(data);
932+ return 0;
933+}
934+
935+ST_FUNC int macho_load_dylib(TCCState * s1, int fd, const char* filename, int lev)
841936 {
842937 unsigned char buf[sizeof(struct mach_header_64)];
843938 void *buf2;
@@ -853,7 +948,6 @@ ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev) · 9 unmodified lines
853948 uint32_t strsize = 0;
854949 uint32_t iextdef = 0;
855950 uint32_t nextdef = 0;
856− DLLReference *dllref;
857951
858952 again:
859953 if (full_read(fd, buf, sizeof(buf)) != sizeof(buf))
@@ -934,20 +1028,8 @@ ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev) · 74 unmodified lines
9341028 lc = (struct load_command*) ((char*)lc + lc->cmdsize);
9351029 }
9361030
937− /* if the dll is already loaded, do not load it */
938− for(i = 0; i < s1->nb_loaded_dlls; i++) {
939− dllref = s1->loaded_dlls[i];
940− if (!strcmp(soname, dllref->name)) {
941− /* but update level if needed */
942− if (lev < dllref->level)
943− dllref->level = lev;
944− goto the_end;
945− }
946− }
947− dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
948− dllref->level = lev;
949− strcpy(dllref->name, soname);
950− dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
1031+ if (0 != macho_add_dllref(s1, lev, soname))
1032+ goto the_end;
9511033
9521034 if (!nsyms || !nextdef)
9531035 tcc_warning("%s doesn't export any symbols?", filename);
@@ -972,3 +1054,10 @@ ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev) · 18 unmodified lines
9721054 tcc_free(buf2);
9731055 return 0;
9741056 }
1057+
1058+ST_FUNC int macho_load_dll(TCCState * s1, int fd, const char* filename, int lev)
1059+{
1060+ return strcmp(tcc_fileextension(filename), ".tbd") == 0
1061+ ? macho_load_tbd(s1, fd, filename, lev)
1062+ : macho_load_dylib(s1, fd, filename, lev);
1063+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t