| @@ -837,7 +837,78 @@ 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 | for(int i = 0; i < s1->nb_loaded_dlls; i++) { |
| | 845 | dllref = s1->loaded_dlls[i]; |
| | 846 | if (!strcmp(soname, dllref->name)) { |
| | 847 | /* but update level if needed */ |
| | 848 | if (lev < dllref->level) |
| | 849 | dllref->level = lev; |
| | 850 | return -1; |
| | 851 | } |
| | 852 | } |
| | 853 | dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname)); |
| | 854 | dllref->level = lev; |
| | 855 | strcpy(dllref->name, soname); |
| | 856 | dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref); |
| | 857 | return 0; |
| | 858 | } |
| | 859 | |
| | 860 | #define tbd_parse_movepast(s) \ |
| | 861 | (pos = (pos = strstr(pos, s)) ? pos + strlen(s) : NULL) |
| | 862 | #define tbd_parse_movetoany(cs) (pos = strpbrk(pos, cs)) |
| | 863 | #define tbd_parse_skipws while (*pos && (*pos==' '||*pos=='\n')) ++pos |
| | 864 | #define tbd_parse_tramplequote if(*pos=='\''||*pos=='"') tbd_parse_trample |
| | 865 | #define tbd_parse_tramplespace if(*pos==' ') tbd_parse_trample |
| | 866 | #define tbd_parse_trample *pos++=0 |
| | 867 | |
| | 868 | ST_FUNC int macho_load_tbd(TCCState* s1, int fd, const char* filename, int lev) |
| | 869 | { |
| | 870 | char* soname; |
| | 871 | |
| | 872 | struct stat sb; |
| | 873 | fstat(fd,&sb); |
| | 874 | char* data = load_data(fd, 0, sb.st_size+1); |
| | 875 | data[sb.st_size]=0; |
| | 876 | char* pos = data; |
| | 877 | |
| | 878 | if (!tbd_parse_movepast("install-name: ")) return -1; |
| | 879 | tbd_parse_skipws; |
| | 880 | tbd_parse_tramplequote; |
| | 881 | soname = pos; |
| | 882 | if (!tbd_parse_movetoany("\n \"'")) return -1; |
| | 883 | tbd_parse_trample; |
| | 884 | if (macho_add_dllref(s1, lev, soname) != 0) goto the_end; |
| | 885 | |
| | 886 | while(pos) { |
| | 887 | char* sym = NULL; |
| | 888 | if (!tbd_parse_movepast("symbols: ")) break; |
| | 889 | if (!tbd_parse_movepast("[")) break; |
| | 890 | int cont = 1; |
| | 891 | while (cont) { |
| | 892 | tbd_parse_skipws; |
| | 893 | tbd_parse_tramplequote; |
| | 894 | sym = pos; |
| | 895 | if (!tbd_parse_movetoany(",] \"'")) break; |
| | 896 | tbd_parse_tramplequote; |
| | 897 | tbd_parse_tramplespace; |
| | 898 | tbd_parse_skipws; |
| | 899 | if (*pos==0||*pos==']') cont=0; |
| | 900 | tbd_parse_trample; |
| | 901 | set_elf_sym(s1->dynsymtab_section, 0, 0, |
| | 902 | ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, SHN_UNDEF, sym); |
| | 903 | } |
| | 904 | } |
| | 905 | |
| | 906 | the_end: |
| | 907 | tcc_free(data); |
| | 908 | return 0; |
| | 909 | } |
| | 910 | |
| | 911 | ST_FUNC int macho_load_dylib(TCCState * s1, int fd, const char* filename, int lev) |
| 841 | { | 912 | { |
| 842 | unsigned char buf[sizeof(struct mach_header_64)]; | 913 | unsigned char buf[sizeof(struct mach_header_64)]; |
| 843 | void *buf2; | 914 | void *buf2; |
| @@ -853,7 +924,6 @@ ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev) · 9 unmodified lines |
| 853 | uint32_t strsize = 0; | 924 | uint32_t strsize = 0; |
| 854 | uint32_t iextdef = 0; | 925 | uint32_t iextdef = 0; |
| 855 | uint32_t nextdef = 0; | 926 | uint32_t nextdef = 0; |
| 856 | DLLReference *dllref; | | |
| 857 | | 927 | |
| 858 | again: | 928 | again: |
| 859 | if (full_read(fd, buf, sizeof(buf)) != sizeof(buf)) | 929 | if (full_read(fd, buf, sizeof(buf)) != sizeof(buf)) |
| @@ -934,20 +1004,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); | 1004 | lc = (struct load_command*) ((char*)lc + lc->cmdsize); |
| 935 | } | 1005 | } |
| 936 | | 1006 | |
| 937 | /* if the dll is already loaded, do not load it */ | 1007 | if (0 != macho_add_dllref(s1, lev, soname)) |
| 938 | for(i = 0; i < s1->nb_loaded_dlls; i++) { | 1008 | 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 | | 1009 | |
| 952 | if (!nsyms || !nextdef) | 1010 | if (!nsyms || !nextdef) |
| 953 | tcc_warning("%s doesn't export any symbols?", filename); | 1011 | tcc_warning("%s doesn't export any symbols?", filename); |
| @@ -972,3 +1030,10 @@ ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev) · 18 unmodified lines |
| 972 | tcc_free(buf2); | 1030 | tcc_free(buf2); |
| 973 | return 0; | 1031 | return 0; |
| 974 | } | 1032 | } |
| | 1033 | |
| | 1034 | ST_FUNC int macho_load_dll(TCCState * s1, int fd, const char* filename, int lev) |
| | 1035 | { |
| | 1036 | return strcmp(tcc_fileextension(filename), ".tbd") == 0 |
| | 1037 | ? macho_load_tbd(s1, fd, filename, lev) |
| | 1038 | : macho_load_dylib(s1, fd, filename, lev); |
| | 1039 | } |