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