Unified · Split
| @@ -855,6 +855,29 @@ LIBTCCAPI void tcc_delete(TCCState *s1) · 854 unmodified lines | |||
| 855 | #endif | 855 | #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 | ||
| 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 | |||
| 858 | LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) | 881 | LIBTCCAPI 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_PE | 912 | #ifdef TCC_TARGET_PE |
| 886 | # ifdef _WIN32 | 913 | # 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 | #endif | 1007 | #endif |
| 981 | 1008 | ||
| 1009 | #ifdef TCC_TARGET_MACHO | ||
| 1010 | ST_FUNC const char* macho_tbd_soname(const char* filename); | ||
| 1011 | #endif | ||
| 1012 | |||
| 982 | ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) | 1013 | ST_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_MACHO | 1039 | #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 | #endif | 1044 | #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_NATIVE | 1062 | #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 | #endif | 1074 | #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_MACHO | 1183 | #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_OpenBSD | 1186 | #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; |
| @@ -42,6 +42,7 @@ · 41 unmodified lines | |||
| 42 | #ifndef _WIN32 | 42 | #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_STATIC | 46 | # ifndef CONFIG_TCC_STATIC |
| 46 | # include <dlfcn.h> | 47 | # include <dlfcn.h> |
| 47 | # endif | 48 | # 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 | # endif | 291 | # endif |
| 282 | #endif | 292 | #endif |
| 283 | 293 | ||
| @@ -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 | ||
| 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) | ||
| 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 | |||
| 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 | } | ||