| @@ -837,7 +837,78 @@ static uint32_t macho_swap32(uint32_t x) · 836 unmodified lines |
| 837 | 837 | } |
| 838 | 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 | 913 | unsigned char buf[sizeof(struct mach_header_64)]; |
| 843 | 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 | 924 | uint32_t strsize = 0; |
| 854 | 925 | uint32_t iextdef = 0; |
| 855 | 926 | uint32_t nextdef = 0; |
| 856 | | − DLLReference *dllref; |
| 857 | 927 | |
| 858 | 928 | again: |
| 859 | 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 | 1004 | lc = (struct load_command*) ((char*)lc + lc->cmdsize); |
| 935 | 1005 | } |
| 936 | 1006 | |
| 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); |
| 1007 | + if (0 != macho_add_dllref(s1, lev, soname)) |
| 1008 | + goto the_end; |
| 951 | 1009 | |
| 952 | 1010 | if (!nsyms || !nextdef) |
| 953 | 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 | 1030 | tcc_free(buf2); |
| 973 | 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 | +} |