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
855#endif855#endif
856}856}
857 857
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
861ST_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
858LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)881LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
859{882{
860 s->output_type = output_type;883 s->output_type = output_type;
@@ -881,7 +904,11 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) · 20 unmodified lines
881 }904 }
882 905
883 tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);906 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
885#ifdef TCC_TARGET_PE912#ifdef TCC_TARGET_PE
886# ifdef _WIN32913# ifdef _WIN32
887 if (!s->nostdlib && output_type != TCC_OUTPUT_OBJ)914 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
979}1006}
980#endif1007#endif
981 1008
1009#ifdef TCC_TARGET_MACHO
1010ST_FUNC const char* macho_tbd_soname(const char* filename);
1011#endif
1012
982ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)1013ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
983{1014{
984 int fd, ret = -1;1015 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
1006 lseek(fd, 0, SEEK_SET);1037 lseek(fd, 0, SEEK_SET);
1007 1038
1008#ifdef TCC_TARGET_MACHO1039#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")))
1010 obj_type = AFF_BINTYPE_DYN;1043 obj_type = AFF_BINTYPE_DYN;
1011#endif1044#endif
1012 1045
@@ -1027,9 +1060,15 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) · 14 unmodified lines
1027 case AFF_BINTYPE_DYN:1060 case AFF_BINTYPE_DYN:
1028 if (s1->output_type == TCC_OUTPUT_MEMORY) {1061 if (s1->output_type == TCC_OUTPUT_MEMORY) {
1029#ifdef TCC_IS_NATIVE1062#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);
1031 if (dl) {1070 if (dl) {
1032 tcc_add_dllref(s1, filename)->handle = dl;1071 tcc_add_dllref(s1, soname)->handle = dl;
1033 ret = 0;1072 ret = 0;
1034 }1073 }
1035#endif1074#endif
@@ -1142,8 +1181,8 @@ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname) · 106 unmodified lines
1142 static const char * const libs[] = { "%s/%s.def", "%s/lib%s.def", "%s/%s.dll", "%s/lib%s.dll", "%s/lib%s.a", NULL };1181 static const char * const libs[] = { "%s/%s.def", "%s/lib%s.def", "%s/%s.dll", "%s/lib%s.dll", "%s/lib%s.a", NULL };
1143 const char * const *pp = s->static_link ? libs + 4 : libs;1182 const char * const *pp = s->static_link ? libs + 4 : libs;
1144#elif defined TCC_TARGET_MACHO1183#elif defined TCC_TARGET_MACHO
1145 static const char * const libs[] = { "%s/lib%s.dylib", "%s/lib%s.a", NULL };1184 static const char * const libs[] = { "%s/lib%s.dylib", "%s/lib%s.tbd", "%s/lib%s.a", NULL };
1146 const char * const *pp = s->static_link ? libs + 1 : libs;1185 const char * const *pp = s->static_link ? libs + 2 : libs;
1147#elif defined TARGETOS_OpenBSD1186#elif defined TARGETOS_OpenBSD
1148 static const char * const libs[] = { "%s/lib%s.so.*", "%s/lib%s.a", NULL };1187 static const char * const libs[] = { "%s/lib%s.so.*", "%s/lib%s.a", NULL };
1149 const char * const *pp = s->static_link ? libs + 1 : libs;1188 const char * const *pp = s->static_link ? libs + 1 : libs;
tcc.h+10−0
@@ -42,6 +42,7 @@ · 41 unmodified lines
42#ifndef _WIN3242#ifndef _WIN32
43# include <unistd.h>43# include <unistd.h>
44# include <sys/time.h>44# include <sys/time.h>
45# include <sys/stat.h>
45# ifndef CONFIG_TCC_STATIC46# ifndef CONFIG_TCC_STATIC
46# include <dlfcn.h>47# include <dlfcn.h>
47# endif48# endif
@@ -278,6 +279,15 @@ extern long double strtold (const char *__nptr, char **__endptr); · 230 unmodified lines
278 ALSO_TRIPLET(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR) \279 ALSO_TRIPLET(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR) \
279 ":" ALSO_TRIPLET(CONFIG_SYSROOT "/" CONFIG_LDDIR) \280 ":" ALSO_TRIPLET(CONFIG_SYSROOT "/" CONFIG_LDDIR) \
280 ":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR)281 ":" 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
281# endif291# endif
282#endif292#endif
283 293
tccmacho.c+105−16
@@ -837,7 +837,102 @@ static uint32_t macho_swap32(uint32_t x) · 836 unmodified lines
837}837}
838#define SWAP(x) (swap ? macho_swap32(x) : (x))838#define SWAP(x) (swap ? macho_swap32(x) : (x))
839 839
840ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev)840ST_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
869ST_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
892ST_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
930the_end:
931 tcc_free(data);
932 return 0;
933}
934
935ST_FUNC int macho_load_dylib(TCCState * s1, int fd, const char* filename, int lev)
841{936{
842 unsigned char buf[sizeof(struct mach_header_64)];937 unsigned char buf[sizeof(struct mach_header_64)];
843 void *buf2;938 void *buf2;
@@ -853,7 +948,6 @@ ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev) · 9 unmodified lines
853 uint32_t strsize = 0;948 uint32_t strsize = 0;
854 uint32_t iextdef = 0;949 uint32_t iextdef = 0;
855 uint32_t nextdef = 0;950 uint32_t nextdef = 0;
856 DLLReference *dllref;
857 951
858 again:952 again:
859 if (full_read(fd, buf, sizeof(buf)) != sizeof(buf))953 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
934 lc = (struct load_command*) ((char*)lc + lc->cmdsize);1028 lc = (struct load_command*) ((char*)lc + lc->cmdsize);
935 }1029 }
936 1030
937 /* if the dll is already loaded, do not load it */1031 if (0 != macho_add_dllref(s1, lev, soname))
938 for(i = 0; i < s1->nb_loaded_dlls; i++) {1032 goto the_end;
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);
951 1033
952 if (!nsyms || !nextdef)1034 if (!nsyms || !nextdef)
953 tcc_warning("%s doesn't export any symbols?", filename);1035 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
972 tcc_free(buf2);1054 tcc_free(buf2);
973 return 0;1055 return 0;
974}1056}
1057
1058ST_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