Unified · Split
| @@ -2795,59 +2795,78 @@ typedef struct ArchiveHeader { · 2794 unmodified lines | |||
| 2795 | char ar_fmag[2]; /* should contain ARFMAG */ | 2795 | char ar_fmag[2]; /* should contain ARFMAG */ |
| 2796 | } ArchiveHeader; | 2796 | } ArchiveHeader; |
| 2797 | 2797 | ||
| 2798 | static int get_be32(const uint8_t *b) | 2798 | #define ARFMAG "`\n" |
| 2799 | |||
| 2800 | static unsigned long long get_be(const uint8_t *b, int n) | ||
| 2799 | { | 2801 | { |
| 2800 | return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24); | 2802 | unsigned long long ret = 0; |
| 2803 | while (n) | ||
| 2804 | ret = (ret << 8) | *b++, --n; | ||
| 2805 | return ret; | ||
| 2801 | } | 2806 | } |
| 2802 | 2807 | ||
| 2803 | static long get_be64(const uint8_t *b) | 2808 | static int read_ar_header(int fd, int offset, ArchiveHeader *hdr) |
| 2804 | { | 2809 | { |
| 2805 | long long ret = get_be32(b); | 2810 | char *p, *e; |
| 2806 | ret = (ret << 32) | (unsigned)get_be32(b+4); | 2811 | int len; |
| 2807 | return (long)ret; | 2812 | lseek(fd, offset, SEEK_SET); |
| 2813 | len = full_read(fd, hdr, sizeof(ArchiveHeader)); | ||
| 2814 | if (len != sizeof(ArchiveHeader)) | ||
| 2815 | return len ? -1 : 0; | ||
| 2816 | p = hdr->ar_name; | ||
| 2817 | for (e = p + sizeof hdr->ar_name; e > p && e[-1] == ' ';) | ||
| 2818 | --e; | ||
| 2819 | *e = '\0'; | ||
| 2820 | hdr->ar_size[sizeof hdr->ar_size-1] = 0; | ||
| 2821 | return len; | ||
| 2808 | } | 2822 | } |
| 2809 | 2823 | ||
| 2810 | /* load only the objects which resolve undefined symbols */ | 2824 | /* load only the objects which resolve undefined symbols */ |
| 2811 | static int tcc_load_alacarte(TCCState *s1, int fd, int size, int entrysize) | 2825 | static int tcc_load_alacarte(TCCState *s1, int fd, int size, int entrysize) |
| 2812 | { | 2826 | { |
| 2813 | long i, bound, nsyms, sym_index, off, ret; | 2827 | int i, bound, nsyms, sym_index, len, ret = -1; |
| 2828 | unsigned long long off; | ||
| 2814 | uint8_t *data; | 2829 | uint8_t *data; |
| 2815 | const char *ar_names, *p; | 2830 | const char *ar_names, *p; |
| 2816 | const uint8_t *ar_index; | 2831 | const uint8_t *ar_index; |
| 2817 | ElfW(Sym) *sym; | 2832 | ElfW(Sym) *sym; |
| 2818 | Section *s; | 2833 | ArchiveHeader hdr; |
| 2819 | 2834 | ||
| 2820 | data = tcc_malloc(size); | 2835 | data = tcc_malloc(size); |
| 2821 | if (full_read(fd, data, size) != size) | 2836 | if (full_read(fd, data, size) != size) |
| 2822 | goto fail; | 2837 | goto the_end; |
| 2823 | nsyms = entrysize == 4 ? get_be32(data) : get_be64(data); | 2838 | nsyms = get_be(data, entrysize); |
| 2824 | ar_index = data + entrysize; | 2839 | ar_index = data + entrysize; |
| 2825 | ar_names = (char *) ar_index + nsyms * entrysize; | 2840 | ar_names = (char *) ar_index + nsyms * entrysize; |
| 2826 | 2841 | ||
| 2827 | do { | 2842 | do { |
| 2828 | bound = 0; | 2843 | bound = 0; |
| 2829 | for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) { | 2844 | for (p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) { |
| 2830 | s = symtab_section; | 2845 | Section *s = symtab_section; |
| 2831 | sym_index = find_elf_sym(s, p); | 2846 | sym_index = find_elf_sym(s, p); |
| 2832 | if(sym_index == 0) { | 2847 | #ifdef TCC_TARGET_PE /* windows DLL's don't have UNDEF syms */ |
| 2848 | if (sym_index == 0) { | ||
| 2833 | s = s1->dynsymtab_section; | 2849 | s = s1->dynsymtab_section; |
| 2834 | sym_index = find_elf_sym(s, p); | 2850 | sym_index = find_elf_sym(s, p); |
| 2835 | } | 2851 | } |
| 2836 | if(sym_index) { | 2852 | #endif |
| 2837 | sym = &((ElfW(Sym) *)s->data)[sym_index]; | 2853 | if (!sym_index) |
| 2838 | if(sym->st_shndx == SHN_UNDEF) { | 2854 | continue; |
| 2839 | off = (entrysize == 4 | 2855 | sym = &((ElfW(Sym) *)s->data)[sym_index]; |
| 2840 | ? get_be32(ar_index + i * 4) | 2856 | if(sym->st_shndx != SHN_UNDEF) |
| 2841 | : get_be64(ar_index + i * 8)) | 2857 | continue; |
| 2842 | + sizeof(ArchiveHeader); | 2858 | off = get_be(ar_index + i * entrysize, entrysize); |
| 2843 | ++bound; | 2859 | len = read_ar_header(fd, off, &hdr); |
| 2844 | if(tcc_load_object_file(s1, fd, off) < 0) { | 2860 | if (len <= 0 || memcmp(hdr.ar_fmag, ARFMAG, 2)) { |
| 2845 | fail: | 2861 | tcc_error_noabort("invalid archive"); |
| 2846 | ret = -1; | 2862 | goto the_end; |
| 2847 | goto the_end; | ||
| 2848 | } | ||
| 2849 | } | ||
| 2850 | } | 2863 | } |
| 2864 | off += len; | ||
| 2865 | if (s1->verbose == 2) | ||
| 2866 | printf(" -> %s\n", hdr.ar_name); | ||
| 2867 | if (tcc_load_object_file(s1, fd, off) < 0) | ||
| 2868 | goto the_end; | ||
| 2869 | ++bound; | ||
| 2851 | } | 2870 | } |
| 2852 | } while(bound); | 2871 | } while(bound); |
| 2853 | ret = 0; | 2872 | ret = 0; |
| @@ -2860,52 +2879,41 @@ static int tcc_load_alacarte(TCCState *s1, int fd, int size, int entrysize) · 6 unmodified lines | |||
| 2860 | ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte) | 2879 | ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte) |
| 2861 | { | 2880 | { |
| 2862 | ArchiveHeader hdr; | 2881 | ArchiveHeader hdr; |
| 2863 | char ar_size[11]; | 2882 | /* char magic[8]; */ |
| 2864 | char ar_name[17]; | 2883 | int size, len; |
| 2865 | char magic[8]; | ||
| 2866 | int size, len, i; | ||
| 2867 | unsigned long file_offset; | 2884 | unsigned long file_offset; |
| 2885 | ElfW(Ehdr) ehdr; | ||
| 2868 | 2886 | ||
| 2869 | /* skip magic which was already checked */ | 2887 | /* skip magic which was already checked */ |
| 2870 | full_read(fd, magic, sizeof(magic)); | 2888 | /* full_read(fd, magic, sizeof(magic)); */ |
| 2889 | file_offset = sizeof ARMAG - 1; | ||
| 2871 | 2890 | ||
| 2872 | for(;;) { | 2891 | for(;;) { |
| 2873 | len = full_read(fd, &hdr, sizeof(hdr)); | 2892 | len = read_ar_header(fd, file_offset, &hdr); |
| 2874 | if (len == 0) | 2893 | if (len == 0) |
| 2875 | break; | 2894 | return 0; |
| 2876 | if (len != sizeof(hdr)) { | 2895 | if (len < 0) { |
| 2877 | tcc_error_noabort("invalid archive"); | 2896 | tcc_error_noabort("invalid archive"); |
| 2878 | return -1; | 2897 | return -1; |
| 2879 | } | 2898 | } |
| 2880 | memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size)); | 2899 | file_offset += len; |
| 2881 | ar_size[sizeof(hdr.ar_size)] = '\0'; | 2900 | size = strtol(hdr.ar_size, NULL, 0); |
| 2882 | size = strtol(ar_size, NULL, 0); | ||
| 2883 | memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name)); | ||
| 2884 | for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) { | ||
| 2885 | if (ar_name[i] != ' ') | ||
| 2886 | break; | ||
| 2887 | } | ||
| 2888 | ar_name[i + 1] = '\0'; | ||
| 2889 | file_offset = lseek(fd, 0, SEEK_CUR); | ||
| 2890 | /* align to even */ | 2901 | /* align to even */ |
| 2891 | size = (size + 1) & ~1; | 2902 | size = (size + 1) & ~1; |
| 2892 | if (!strcmp(ar_name, "/")) { | 2903 | if (alacarte) { |
| 2893 | /* coff symbol table : we handle it */ | 2904 | /* coff symbol table : we handle it */ |
| 2894 | if (alacarte) | 2905 | if (!strcmp(hdr.ar_name, "/")) |
| 2895 | return tcc_load_alacarte(s1, fd, size, 4); | 2906 | return tcc_load_alacarte(s1, fd, size, 4); |
| 2896 | } else if (!strcmp(ar_name, "/SYM64/")) { | 2907 | if (!strcmp(hdr.ar_name, "/SYM64/")) |
| 2897 | if (alacarte) | ||
| 2898 | return tcc_load_alacarte(s1, fd, size, 8); | 2908 | return tcc_load_alacarte(s1, fd, size, 8); |
| 2899 | } else { | 2909 | } else if (tcc_object_type(fd, &ehdr) == AFF_BINTYPE_REL) { |
| 2900 | ElfW(Ehdr) ehdr; | 2910 | if (s1->verbose == 2) |
| 2901 | if (tcc_object_type(fd, &ehdr) == AFF_BINTYPE_REL) { | 2911 | printf(" -> %s\n", hdr.ar_name); |
| 2902 | if (tcc_load_object_file(s1, fd, file_offset) < 0) | 2912 | if (tcc_load_object_file(s1, fd, file_offset) < 0) |
| 2903 | return -1; | 2913 | return -1; |
| 2904 | } | ||
| 2905 | } | 2914 | } |
| 2906 | lseek(fd, file_offset + size, SEEK_SET); | 2915 | file_offset += size; |
| 2907 | } | 2916 | } |
| 2908 | return 0; | ||
| 2909 | } | 2917 | } |
| 2910 | 2918 | ||
| 2911 | #ifndef ELF_OBJ_ONLY | 2919 | #ifndef ELF_OBJ_ONLY |