| @@ -259,6 +259,7 @@ ST_FUNC int add_elf_sym(Section *s, uplong value, unsigned long size, · 258 unmodified lines |
| 259 | do_patch: | 259 | do_patch: |
| 260 | esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type); | 260 | esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type); |
| 261 | esym->st_shndx = sh_num; | 261 | esym->st_shndx = sh_num; |
| | 262 | new_undef_sym = 1; |
| 262 | esym->st_value = value; | 263 | esym->st_value = value; |
| 263 | esym->st_size = size; | 264 | esym->st_size = size; |
| 264 | esym->st_other = other; | 265 | esym->st_other = other; |
| @@ -2808,9 +2809,77 @@ static int ld_next(TCCState *s1, char *name, int name_size) · 2543 unmodified lines |
| 2808 | return c; | 2809 | return c; |
| 2809 | } | 2810 | } |
| 2810 | | 2811 | |
| | 2812 | /* |
| | 2813 | * Extract the library name from the file name |
| | 2814 | * Return 0 if the file isn't a library |
| | 2815 | * |
| | 2816 | * /!\ No test on filename capacity, be careful |
| | 2817 | */ |
| | 2818 | static int filename_to_libname(TCCState *s1, char filename[], char libname[]) |
| | 2819 | { |
| | 2820 | char *ext, *base; |
| | 2821 | int libprefix; |
| | 2822 | |
| | 2823 | /* already converted to library name */ |
| | 2824 | if (filename[0] == '\0') |
| | 2825 | return 1; |
| | 2826 | base = tcc_basename(filename); |
| | 2827 | if (base != filename) |
| | 2828 | return 0; |
| | 2829 | ext = strrchr(base, '.'); |
| | 2830 | if (ext == NULL) |
| | 2831 | return 0; |
| | 2832 | ext++; |
| | 2833 | libprefix = !strncmp(filename, "lib", 3); |
| | 2834 | if (!s1->static_link) { |
| | 2835 | #ifdef TCC_TARGET_PE |
| | 2836 | if (!strncmp(ext, "def", 3)) { |
| | 2837 | *(--ext) = '\0'; |
| | 2838 | strcpy(libname, filename); |
| | 2839 | *ext = '.'; |
| | 2840 | return 1; |
| | 2841 | } |
| | 2842 | #else |
| | 2843 | if (libprefix && (!strncmp(ext, "so", 2))) { |
| | 2844 | *(--ext) = '\0'; |
| | 2845 | strcpy(libname, filename + 3); |
| | 2846 | *ext = '.'; |
| | 2847 | return 1; |
| | 2848 | } |
| | 2849 | #endif |
| | 2850 | } else { |
| | 2851 | if (libprefix && (!strncmp(ext, "a", 1))) { |
| | 2852 | *(--ext) = '\0'; |
| | 2853 | strcpy(libname, filename + 3); |
| | 2854 | *ext = '.'; |
| | 2855 | return 1; |
| | 2856 | } |
| | 2857 | } |
| | 2858 | return 0; |
| | 2859 | } |
| | 2860 | |
| | 2861 | /* |
| | 2862 | * Extract the file name from the library name |
| | 2863 | * |
| | 2864 | * /!\ No test on filename capacity, be careful |
| | 2865 | */ |
| | 2866 | static void libname_to_filename(TCCState *s1, char libname[], char filename[]) |
| | 2867 | { |
| | 2868 | if (!s1->static_link) { |
| | 2869 | #ifdef TCC_TARGET_PE |
| | 2870 | snprintf(filename, strlen(libname) + 5, "%s.def", libname); |
| | 2871 | #else |
| | 2872 | snprintf(filename, strlen(libname) + 7, "lib%s.so", libname); |
| | 2873 | #endif |
| | 2874 | } else { |
| | 2875 | snprintf(filename, strlen(libname) + 6, "lib%s.a", libname); |
| | 2876 | } |
| | 2877 | } |
| | 2878 | |
| 2811 | static int ld_add_file_list(TCCState *s1, int as_needed) | 2879 | static int ld_add_file_list(TCCState *s1, int as_needed) |
| 2812 | { | 2880 | { |
| 2813 | char filename[1024]; | 2881 | char filename[1024]; |
| | 2882 | char libname[1024]; |
| 2814 | int t, ret; | 2883 | int t, ret; |
| 2815 | | 2884 | |
| 2816 | t = ld_next(s1, filename, sizeof(filename)); | 2885 | t = ld_next(s1, filename, sizeof(filename)); |
| @@ -2818,11 +2887,20 @@ static int ld_add_file_list(TCCState *s1, int as_needed) · 1 unmodified line |
| 2818 | expect("("); | 2887 | expect("("); |
| 2819 | t = ld_next(s1, filename, sizeof(filename)); | 2888 | t = ld_next(s1, filename, sizeof(filename)); |
| 2820 | for(;;) { | 2889 | for(;;) { |
| | 2890 | libname[0] = '\0'; |
| 2821 | if (t == LD_TOK_EOF) { | 2891 | if (t == LD_TOK_EOF) { |
| 2822 | error_noabort("unexpected end of file"); | 2892 | error_noabort("unexpected end of file"); |
| 2823 | return -1; | 2893 | return -1; |
| 2824 | } else if (t == ')') { | 2894 | } else if (t == ')') { |
| 2825 | break; | 2895 | break; |
| | 2896 | } else if (t == '-') { |
| | 2897 | t = ld_next(s1, filename, sizeof(filename)); |
| | 2898 | if ((t != LD_TOK_NAME) || (filename[0] != 'l')) { |
| | 2899 | error_noabort("library name expected"); |
| | 2900 | return -1; |
| | 2901 | } |
| | 2902 | strcpy(libname, &filename[1]); |
| | 2903 | libname_to_filename(s1, libname, filename); |
| 2826 | } else if (t != LD_TOK_NAME) { | 2904 | } else if (t != LD_TOK_NAME) { |
| 2827 | error_noabort("filename expected"); | 2905 | error_noabort("filename expected"); |
| 2828 | return -1; | 2906 | return -1; |
| @@ -2833,8 +2911,15 @@ static int ld_add_file_list(TCCState *s1, int as_needed) · 4 unmodified lines |
| 2833 | return ret; | 2911 | return ret; |
| 2834 | } else { | 2912 | } else { |
| 2835 | /* TODO: Implement AS_NEEDED support. Ignore it for now */ | 2913 | /* TODO: Implement AS_NEEDED support. Ignore it for now */ |
| 2836 | if (!as_needed) | 2914 | if (!as_needed) { |
| 2837 | tcc_add_file(s1, filename); | 2915 | ret = tcc_add_file_internal(s1, filename, 0); |
| | 2916 | if (ret) { |
| | 2917 | if (filename_to_libname(s1, filename, libname)) |
| | 2918 | ret = tcc_add_library(s1, libname); |
| | 2919 | if (ret) |
| | 2920 | return ret; |
| | 2921 | } |
| | 2922 | } |
| 2838 | } | 2923 | } |
| 2839 | t = ld_next(s1, filename, sizeof(filename)); | 2924 | t = ld_next(s1, filename, sizeof(filename)); |
| 2840 | if (t == ',') { | 2925 | if (t == ',') { |
| @@ -2844,6 +2929,14 @@ static int ld_add_file_list(TCCState *s1, int as_needed) · 3 unmodified lines |
| 2844 | return 0; | 2929 | return 0; |
| 2845 | } | 2930 | } |
| 2846 | | 2931 | |
| | 2932 | static int new_undef_syms(void) |
| | 2933 | { |
| | 2934 | int ret = 0; |
| | 2935 | ret = new_undef_sym; |
| | 2936 | new_undef_sym = 0; |
| | 2937 | return ret; |
| | 2938 | } |
| | 2939 | |
| 2847 | /* interpret a subset of GNU ldscripts to handle the dummy libc.so | 2940 | /* interpret a subset of GNU ldscripts to handle the dummy libc.so |
| 2848 | files */ | 2941 | files */ |
| 2849 | ST_FUNC int tcc_load_ldscript(TCCState *s1) | 2942 | ST_FUNC int tcc_load_ldscript(TCCState *s1) |
| @@ -2862,7 +2955,24 @@ ST_FUNC int tcc_load_ldscript(TCCState *s1) · 12 unmodified lines |
| 2862 | return -1; | 2955 | return -1; |
| 2863 | if (!strcmp(cmd, "INPUT") || | 2956 | if (!strcmp(cmd, "INPUT") || |
| 2864 | !strcmp(cmd, "GROUP")) { | 2957 | !strcmp(cmd, "GROUP")) { |
| 2865 | ret = ld_add_file_list(s1, 0); | 2958 | if (!strcmp(cmd, "GROUP")) { |
| | 2959 | BufferedFile *buf_state; |
| | 2960 | int off; |
| | 2961 | |
| | 2962 | buf_state = tcc_save_buffer_state(&off); |
| | 2963 | new_undef_syms(); |
| | 2964 | ret = ld_add_file_list(s1, 0); |
| | 2965 | if (ret) |
| | 2966 | goto free_bufstate; |
| | 2967 | while (!ret && new_undef_syms()) { |
| | 2968 | tcc_load_buffer_state(buf_state, off); |
| | 2969 | ret = ld_add_file_list(s1, 0); |
| | 2970 | } |
| | 2971 | free_bufstate: |
| | 2972 | tcc_free_buffer_state(buf_state); |
| | 2973 | } else { |
| | 2974 | ret = ld_add_file_list(s1, 0); |
| | 2975 | } |
| 2866 | if (ret) | 2976 | if (ret) |
| 2867 | return ret; | 2977 | return ret; |
| 2868 | } else if (!strcmp(cmd, "OUTPUT_FORMAT") || | 2978 | } else if (!strcmp(cmd, "OUTPUT_FORMAT") || |