Unified · Split
| @@ -43,26 +43,26 @@ typedef int RegArgs; · 42 unmodified lines | |||
| 43 | /* a register can belong to several classes. The classes must be | 43 | /* a register can belong to several classes. The classes must be |
| 44 | sorted from more general to more precise (see gv2() code which does | 44 | sorted from more general to more precise (see gv2() code which does |
| 45 | assumptions on it). */ | 45 | assumptions on it). */ |
| 46 | #define RC_INT 0x0001 /* generic integer register */ | 46 | #define RC_INT 0x0001 /* generic integer register */ |
| 47 | #define RC_FLOAT 0x0002 /* generic float register */ | 47 | #define RC_FLOAT 0x0002 /* generic float register */ |
| 48 | #define RC_R0 0x0004 | 48 | #define RC_R0 0x0004 |
| 49 | #define RC_R1 0x0008 | 49 | #define RC_R1 0x0008 |
| 50 | #define RC_R2 0x0010 | 50 | #define RC_R2 0x0010 |
| 51 | #define RC_R3 0x0020 | 51 | #define RC_R3 0x0020 |
| 52 | #define RC_R12 0x0040 | 52 | #define RC_R12 0x0040 |
| 53 | #define RC_F0 0x0080 | 53 | #define RC_F0 0x0080 |
| 54 | #define RC_F1 0x0100 | 54 | #define RC_F1 0x0100 |
| 55 | #define RC_F2 0x0200 | 55 | #define RC_F2 0x0200 |
| 56 | #define RC_F3 0x0400 | 56 | #define RC_F3 0x0400 |
| 57 | #ifdef TCC_ARM_VFP | 57 | #ifdef TCC_ARM_VFP |
| 58 | #define RC_F4 0x0800 | 58 | #define RC_F4 0x0800 |
| 59 | #define RC_F5 0x1000 | 59 | #define RC_F5 0x1000 |
| 60 | #define RC_F6 0x2000 | 60 | #define RC_F6 0x2000 |
| 61 | #define RC_F7 0x4000 | 61 | #define RC_F7 0x4000 |
| 62 | #endif | 62 | #endif |
| 63 | #define RC_IRET RC_R0 /* function return: integer register */ | 63 | #define RC_IRET RC_R0 /* function return: integer register */ |
| 64 | #define RC_LRET RC_R1 /* function return: second integer register */ | 64 | #define RC_LRET RC_R1 /* function return: second integer register */ |
| 65 | #define RC_FRET RC_F0 /* function return: float register */ | 65 | #define RC_FRET RC_F0 /* function return: float register */ |
| 66 | 66 | ||
| 67 | /* pretty names for the registers */ | 67 | /* pretty names for the registers */ |
| 68 | enum { | 68 | enum { |
| @@ -1716,12 +1716,12 @@ void gen_opf(int op) · 1647 unmodified lines | |||
| 1716 | } | 1716 | } |
| 1717 | if (is_zero(-1)) { | 1717 | if (is_zero(-1)) { |
| 1718 | vswap(); | 1718 | vswap(); |
| 1719 | switch(op) { | 1719 | switch(op) { |
| 1720 | case TOK_LT: op = TOK_GT; break; | 1720 | case TOK_LT: op = TOK_GT; break; |
| 1721 | case TOK_GE: op = TOK_ULE; break; | 1721 | case TOK_GE: op = TOK_ULE; break; |
| 1722 | case TOK_LE: op = TOK_GE; break; | 1722 | case TOK_LE: op = TOK_GE; break; |
| 1723 | case TOK_GT: op = TOK_ULT; break; | 1723 | case TOK_GT: op = TOK_ULT; break; |
| 1724 | } | 1724 | } |
| 1725 | } | 1725 | } |
| 1726 | x |= 0xB40040; /* fcmpX */ | 1726 | x |= 0xB40040; /* fcmpX */ |
| 1727 | if (op != TOK_EQ && op != TOK_NE) | 1727 | if (op != TOK_EQ && op != TOK_NE) |
| @@ -1738,12 +1738,12 @@ void gen_opf(int op) · 10 unmodified lines | |||
| 1738 | } | 1738 | } |
| 1739 | o(0xEEF1FA10); /* fmstat */ | 1739 | o(0xEEF1FA10); /* fmstat */ |
| 1740 | 1740 | ||
| 1741 | switch(op) { | 1741 | switch(op) { |
| 1742 | case TOK_LE: op = TOK_ULE; break; | 1742 | case TOK_LE: op = TOK_ULE; break; |
| 1743 | case TOK_LT: op = TOK_ULT; break; | 1743 | case TOK_LT: op = TOK_ULT; break; |
| 1744 | case TOK_UGE: op = TOK_GE; break; | 1744 | case TOK_UGE: op = TOK_GE; break; |
| 1745 | case TOK_UGT: op = TOK_GT; break; | 1745 | case TOK_UGT: op = TOK_GT; break; |
| 1746 | } | 1746 | } |
| 1747 | 1747 | ||
| 1748 | vtop->r = VT_CMP; | 1748 | vtop->r = VT_CMP; |
| 1749 | vtop->c.i = op; | 1749 | vtop->c.i = op; |
| @@ -672,7 +672,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section, · 671 unmodified lines | |||
| 672 | } | 672 | } |
| 673 | #else | 673 | #else |
| 674 | if (! (sym->type.t & VT_STATIC)) | 674 | if (! (sym->type.t & VT_STATIC)) |
| 675 | other = (sym->type.t & VT_VIS_MASK) >> VT_VIS_SHIFT; | 675 | other = (sym->type.t & VT_VIS_MASK) >> VT_VIS_SHIFT; |
| 676 | #endif | 676 | #endif |
| 677 | if (tcc_state->leading_underscore && can_add_underscore) { | 677 | if (tcc_state->leading_underscore && can_add_underscore) { |
| 678 | buf1[0] = '_'; | 678 | buf1[0] = '_'; |
| @@ -2257,7 +2257,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) · 1578 unmodified lines | |||
| 2257 | tcc_set_options(s, "-lpthread"); | 2257 | tcc_set_options(s, "-lpthread"); |
| 2258 | 2258 | ||
| 2259 | if (s->output_type == TCC_OUTPUT_EXE) | 2259 | if (s->output_type == TCC_OUTPUT_EXE) |
| 2260 | tcc_set_linker(s, (const char *)linker_arg.data); | 2260 | tcc_set_linker(s, (const char *)linker_arg.data); |
| 2261 | cstr_free(&linker_arg); | 2261 | cstr_free(&linker_arg); |
| 2262 | 2262 | ||
| 2263 | return optind; | 2263 | return optind; |
| @@ -492,25 +492,25 @@ static void asm_parse_directive(TCCState *s1) · 491 unmodified lines | |||
| 492 | case TOK_ASM_global: | 492 | case TOK_ASM_global: |
| 493 | case TOK_ASM_weak: | 493 | case TOK_ASM_weak: |
| 494 | case TOK_ASM_hidden: | 494 | case TOK_ASM_hidden: |
| 495 | tok1 = tok; | 495 | tok1 = tok; |
| 496 | do { | 496 | do { |
| 497 | Sym *sym; | 497 | Sym *sym; |
| 498 | 498 | ||
| 499 | next(); | 499 | next(); |
| 500 | sym = label_find(tok); | 500 | sym = label_find(tok); |
| 501 | if (!sym) { | 501 | if (!sym) { |
| 502 | sym = label_push(&s1->asm_labels, tok, 0); | 502 | sym = label_push(&s1->asm_labels, tok, 0); |
| 503 | sym->type.t = VT_VOID; | 503 | sym->type.t = VT_VOID; |
| 504 | } | 504 | } |
| 505 | if (tok1 != TOK_ASM_hidden) | 505 | if (tok1 != TOK_ASM_hidden) |
| 506 | sym->type.t &= ~VT_STATIC; | 506 | sym->type.t &= ~VT_STATIC; |
| 507 | if (tok1 == TOK_ASM_weak) | 507 | if (tok1 == TOK_ASM_weak) |
| 508 | sym->type.t |= VT_WEAK; | 508 | sym->type.t |= VT_WEAK; |
| 509 | else if (tok1 == TOK_ASM_hidden) | 509 | else if (tok1 == TOK_ASM_hidden) |
| 510 | sym->type.t |= STV_HIDDEN << VT_VIS_SHIFT; | 510 | sym->type.t |= STV_HIDDEN << VT_VIS_SHIFT; |
| 511 | next(); | 511 | next(); |
| 512 | } while (tok == ','); | 512 | } while (tok == ','); |
| 513 | break; | 513 | break; |
| 514 | case TOK_ASM_string: | 514 | case TOK_ASM_string: |
| 515 | case TOK_ASM_ascii: | 515 | case TOK_ASM_ascii: |
| 516 | case TOK_ASM_asciz: | 516 | case TOK_ASM_asciz: |
| @@ -536,12 +536,12 @@ static void asm_parse_directive(TCCState *s1) · 19 unmodified lines | |||
| 536 | break; | 536 | break; |
| 537 | } | 537 | } |
| 538 | } | 538 | } |
| 539 | } | 539 | } |
| 540 | break; | 540 | break; |
| 541 | case TOK_ASM_text: | 541 | case TOK_ASM_text: |
| 542 | case TOK_ASM_data: | 542 | case TOK_ASM_data: |
| 543 | case TOK_ASM_bss: | 543 | case TOK_ASM_bss: |
| 544 | { | 544 | { |
| 545 | char sname[64]; | 545 | char sname[64]; |
| 546 | tok1 = tok; | 546 | tok1 = tok; |
| 547 | n = 0; | 547 | n = 0; |
| @@ -552,8 +552,8 @@ static void asm_parse_directive(TCCState *s1) · 4 unmodified lines | |||
| 552 | } | 552 | } |
| 553 | sprintf(sname, (n?".%s%d":".%s"), get_tok_str(tok1, NULL), n); | 553 | sprintf(sname, (n?".%s%d":".%s"), get_tok_str(tok1, NULL), n); |
| 554 | use_section(s1, sname); | 554 | use_section(s1, sname); |
| 555 | } | 555 | } |
| 556 | break; | 556 | break; |
| 557 | case TOK_ASM_file: | 557 | case TOK_ASM_file: |
| 558 | { | 558 | { |
| 559 | char filename[512]; | 559 | char filename[512]; |
| @@ -21,9 +21,9 @@ · 20 unmodified lines | |||
| 21 | 21 | ||
| 22 | #include "tcc.h" | 22 | #include "tcc.h" |
| 23 | 23 | ||
| 24 | #define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */ | 24 | #define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */ |
| 25 | #define MAX_STR_TABLE 1000000 | 25 | #define MAX_STR_TABLE 1000000 |
| 26 | AOUTHDR o_filehdr; /* OPTIONAL (A.OUT) FILE HEADER */ | 26 | AOUTHDR o_filehdr; /* OPTIONAL (A.OUT) FILE HEADER */ |
| 27 | 27 | ||
| 28 | SCNHDR section_header[MAXNSCNS]; | 28 | SCNHDR section_header[MAXNSCNS]; |
| 29 | 29 | ||
| @@ -94,21 +94,21 @@ ST_FUNC int tcc_output_coff(TCCState* s1, FILE* f) · 64 unmodified lines | |||
| 94 | nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym); | 94 | nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym); |
| 95 | coff_nb_syms = FindCoffSymbolIndex("XXXXXXXXXX1"); | 95 | coff_nb_syms = FindCoffSymbolIndex("XXXXXXXXXX1"); |
| 96 | 96 | ||
| 97 | file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */ | 97 | file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */ |
| 98 | file_hdr.f_timdat = 0; /* time & date stamp */ | 98 | file_hdr.f_timdat = 0; /* time & date stamp */ |
| 99 | file_hdr.f_opthdr = sizeof(AOUTHDR); /* sizeof(optional hdr) */ | 99 | file_hdr.f_opthdr = sizeof(AOUTHDR); /* sizeof(optional hdr) */ |
| 100 | file_hdr.f_flags = 0x1143; /* flags (copied from what code composer does) */ | 100 | file_hdr.f_flags = 0x1143; /* flags (copied from what code composer does) */ |
| 101 | file_hdr.f_TargetID = 0x99; /* for C6x = 0x0099 */ | 101 | file_hdr.f_TargetID = 0x99; /* for C6x = 0x0099 */ |
| 102 | 102 | ||
| 103 | o_filehdr.magic = 0x0108; /* see magic.h */ | 103 | o_filehdr.magic = 0x0108; /* see magic.h */ |
| 104 | o_filehdr.vstamp = 0x0190; /* version stamp */ | 104 | o_filehdr.vstamp = 0x0190; /* version stamp */ |
| 105 | o_filehdr.tsize = | 105 | o_filehdr.tsize = |
| 106 | stext->data_offset; /* text size in bytes, padded to FW bdry */ | 106 | stext->data_offset; /* text size in bytes, padded to FW bdry */ |
| 107 | o_filehdr.dsize = sdata->data_offset; /* initialized data " " */ | 107 | o_filehdr.dsize = sdata->data_offset; /* initialized data " " */ |
| 108 | o_filehdr.bsize = sbss->data_offset; /* uninitialized data " " */ | 108 | o_filehdr.bsize = sbss->data_offset; /* uninitialized data " " */ |
| 109 | o_filehdr.entrypt = C67_main_entry_point; /* entry pt. */ | 109 | o_filehdr.entrypt = C67_main_entry_point; /* entry pt. */ |
| 110 | o_filehdr.text_start = stext->sh_addr; /* base of text used for this file */ | 110 | o_filehdr.text_start = stext->sh_addr; /* base of text used for this file */ |
| 111 | o_filehdr.data_start = sdata->sh_addr; /* base of data used for this file */ | 111 | o_filehdr.data_start = sdata->sh_addr; /* base of data used for this file */ |
| 112 | 112 | ||
| 113 | // create all the section headers | 113 | // create all the section headers |
| 114 | 114 | ||
| @@ -451,7 +451,7 @@ ST_FUNC void relocate_syms(TCCState *s1, int do_resolve) · 450 unmodified lines | |||
| 451 | if (addr) { | 451 | if (addr) { |
| 452 | sym->st_value = (addr_t)addr; | 452 | sym->st_value = (addr_t)addr; |
| 453 | #ifdef DEBUG_RELOC | 453 | #ifdef DEBUG_RELOC |
| 454 | printf ("relocate_sym: %s -> 0x%lx\n", name, sym->st_value); | 454 | printf ("relocate_sym: %s -> 0x%lx\n", name, sym->st_value); |
| 455 | #endif | 455 | #endif |
| 456 | goto found; | 456 | goto found; |
| 457 | } | 457 | } |
| @@ -580,10 +580,10 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 122 unmodified lines | |||
| 580 | { | 580 | { |
| 581 | int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko; | 581 | int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko; |
| 582 | x = (*(int *) ptr) & 0xffffff; | 582 | x = (*(int *) ptr) & 0xffffff; |
| 583 | if (sym->st_shndx == SHN_UNDEF) | 583 | if (sym->st_shndx == SHN_UNDEF) |
| 584 | val = s1->plt->sh_addr; | 584 | val = s1->plt->sh_addr; |
| 585 | #ifdef DEBUG_RELOC | 585 | #ifdef DEBUG_RELOC |
| 586 | printf ("reloc %d: x=0x%x val=0x%x ", type, x, val); | 586 | printf ("reloc %d: x=0x%x val=0x%x ", type, x, val); |
| 587 | #endif | 587 | #endif |
| 588 | (*(int *)ptr) &= 0xff000000; | 588 | (*(int *)ptr) &= 0xff000000; |
| 589 | if (x & 0x800000) | 589 | if (x & 0x800000) |
| @@ -595,8 +595,8 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 5 unmodified lines | |||
| 595 | is_call = (type == R_ARM_CALL || (type == R_ARM_PC24 && is_bl)); | 595 | is_call = (type == R_ARM_CALL || (type == R_ARM_PC24 && is_bl)); |
| 596 | x += val - addr; | 596 | x += val - addr; |
| 597 | #ifdef DEBUG_RELOC | 597 | #ifdef DEBUG_RELOC |
| 598 | printf (" newx=0x%x name=%s\n", x, | 598 | printf (" newx=0x%x name=%s\n", x, |
| 599 | (char *) symtab_section->link->data + sym->st_name); | 599 | (char *) symtab_section->link->data + sym->st_name); |
| 600 | #endif | 600 | #endif |
| 601 | h = x & 2; | 601 | h = x & 2; |
| 602 | th_ko = (x & 3) && (!blx_avail || !is_call); | 602 | th_ko = (x & 3) && (!blx_avail || !is_call); |
| @@ -801,17 +801,17 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 198 unmodified lines | |||
| 801 | if we really need a PLT slot. */ | 801 | if we really need a PLT slot. */ |
| 802 | if (sym->st_shndx == SHN_UNDEF) | 802 | if (sym->st_shndx == SHN_UNDEF) |
| 803 | /* We've put the PLT slot offset into r_addend when generating | 803 | /* We've put the PLT slot offset into r_addend when generating |
| 804 | it, and that's what we must use as relocation value (adjusted | 804 | it, and that's what we must use as relocation value (adjusted |
| 805 | by section offset of course). */ | 805 | by section offset of course). */ |
| 806 | val = s1->plt->sh_addr + rel->r_addend; | 806 | val = s1->plt->sh_addr + rel->r_addend; |
| 807 | #ifdef DEBUG_RELOC | 807 | #ifdef DEBUG_RELOC |
| 808 | printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, val, | 808 | printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, val, |
| 809 | (char *) symtab_section->link->data + sym->st_name); | 809 | (char *) symtab_section->link->data + sym->st_name); |
| 810 | #endif | 810 | #endif |
| 811 | if (((val - addr) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc) | 811 | if (((val - addr) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc) |
| 812 | { | 812 | { |
| 813 | tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed (val=%lx, addr=%lx)", addr, val); | 813 | tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed (val=%lx, addr=%lx)", addr, val); |
| 814 | } | 814 | } |
| 815 | *(uint32_t *)ptr = 0x14000000 | (type == R_AARCH64_CALL26) << 31 | | 815 | *(uint32_t *)ptr = 0x14000000 | (type == R_AARCH64_CALL26) << 31 | |
| 816 | ((val - addr) >> 2 & 0x3ffffff); | 816 | ((val - addr) >> 2 & 0x3ffffff); |
| 817 | break; | 817 | break; |
| @@ -836,9 +836,9 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 18 unmodified lines | |||
| 836 | case R_AARCH64_JUMP_SLOT: | 836 | case R_AARCH64_JUMP_SLOT: |
| 837 | /* They don't need addend */ | 837 | /* They don't need addend */ |
| 838 | #ifdef DEBUG_RELOC | 838 | #ifdef DEBUG_RELOC |
| 839 | printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, | 839 | printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, |
| 840 | val - rel->r_addend, | 840 | val - rel->r_addend, |
| 841 | (char *) symtab_section->link->data + sym->st_name); | 841 | (char *) symtab_section->link->data + sym->st_name); |
| 842 | #endif | 842 | #endif |
| 843 | *(addr_t *)ptr = val - rel->r_addend; | 843 | *(addr_t *)ptr = val - rel->r_addend; |
| 844 | break; | 844 | break; |
| @@ -879,12 +879,12 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 34 unmodified lines | |||
| 879 | qrel->r_offset = rel->r_offset; | 879 | qrel->r_offset = rel->r_offset; |
| 880 | if (esym_index) { | 880 | if (esym_index) { |
| 881 | qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_64); | 881 | qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_64); |
| 882 | qrel->r_addend = rel->r_addend; | 882 | qrel->r_addend = rel->r_addend; |
| 883 | qrel++; | 883 | qrel++; |
| 884 | break; | 884 | break; |
| 885 | } else { | 885 | } else { |
| 886 | qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE); | 886 | qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE); |
| 887 | qrel->r_addend = *(long long *)ptr + val; | 887 | qrel->r_addend = *(long long *)ptr + val; |
| 888 | qrel++; | 888 | qrel++; |
| 889 | } | 889 | } |
| 890 | } | 890 | } |
| @@ -917,21 +917,21 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 26 unmodified lines | |||
| 917 | goto plt32pc32; | 917 | goto plt32pc32; |
| 918 | 918 | ||
| 919 | case R_X86_64_PLT32: | 919 | case R_X86_64_PLT32: |
| 920 | /* We've put the PLT slot offset into r_addend when generating | 920 | /* We've put the PLT slot offset into r_addend when generating |
| 921 | it, and that's what we must use as relocation value (adjusted | 921 | it, and that's what we must use as relocation value (adjusted |
| 922 | by section offset of course). */ | 922 | by section offset of course). */ |
| 923 | val = s1->plt->sh_addr + rel->r_addend; | 923 | val = s1->plt->sh_addr + rel->r_addend; |
| 924 | /* fallthrough. */ | 924 | /* fallthrough. */ |
| 925 | 925 | ||
| 926 | plt32pc32: | 926 | plt32pc32: |
| 927 | { | 927 | { |
| 928 | long long diff; | 928 | long long diff; |
| 929 | diff = (long long)val - addr; | 929 | diff = (long long)val - addr; |
| 930 | if (diff < -2147483648LL || diff > 2147483647LL) { | 930 | if (diff < -2147483648LL || diff > 2147483647LL) { |
| 931 | tcc_error("internal error: relocation failed"); | 931 | tcc_error("internal error: relocation failed"); |
| 932 | } | ||
| 933 | *(int *)ptr += diff; | ||
| 932 | } | 934 | } |
| 933 | *(int *)ptr += diff; | ||
| 934 | } | ||
| 935 | break; | 935 | break; |
| 936 | case R_X86_64_GLOB_DAT: | 936 | case R_X86_64_GLOB_DAT: |
| 937 | case R_X86_64_JUMP_SLOT: | 937 | case R_X86_64_JUMP_SLOT: |
| @@ -1080,8 +1080,8 @@ static void build_got(TCCState *s1) · 142 unmodified lines | |||
| 1080 | and 'info' can be modifed if more precise info comes from the DLL. | 1080 | and 'info' can be modifed if more precise info comes from the DLL. |
| 1081 | Returns offset of GOT or PLT slot. */ | 1081 | Returns offset of GOT or PLT slot. */ |
| 1082 | static unsigned long put_got_entry(TCCState *s1, | 1082 | static unsigned long put_got_entry(TCCState *s1, |
| 1083 | int reloc_type, unsigned long size, int info, | 1083 | int reloc_type, unsigned long size, int info, |
| 1084 | int sym_index) | 1084 | int sym_index) |
| 1085 | { | 1085 | { |
| 1086 | int index, need_plt_entry; | 1086 | int index, need_plt_entry; |
| 1087 | const char *name; | 1087 | const char *name; |
| @@ -1107,18 +1107,18 @@ static unsigned long put_got_entry(TCCState *s1, · 19 unmodified lines | |||
| 1107 | #endif | 1107 | #endif |
| 1108 | 1108 | ||
| 1109 | if (need_plt_entry && !s1->plt) { | 1109 | if (need_plt_entry && !s1->plt) { |
| 1110 | /* add PLT */ | 1110 | /* add PLT */ |
| 1111 | s1->plt = new_section(s1, ".plt", SHT_PROGBITS, | 1111 | s1->plt = new_section(s1, ".plt", SHT_PROGBITS, |
| 1112 | SHF_ALLOC | SHF_EXECINSTR); | 1112 | SHF_ALLOC | SHF_EXECINSTR); |
| 1113 | s1->plt->sh_entsize = 4; | 1113 | s1->plt->sh_entsize = 4; |
| 1114 | } | 1114 | } |
| 1115 | 1115 | ||
| 1116 | /* If a got/plt entry already exists for that symbol, no need to add one */ | 1116 | /* If a got/plt entry already exists for that symbol, no need to add one */ |
| 1117 | if (sym_index < s1->nb_sym_attrs) { | 1117 | if (sym_index < s1->nb_sym_attrs) { |
| 1118 | if (need_plt_entry && s1->sym_attrs[sym_index].plt_offset) | 1118 | if (need_plt_entry && s1->sym_attrs[sym_index].plt_offset) |
| 1119 | return s1->sym_attrs[sym_index].plt_offset; | 1119 | return s1->sym_attrs[sym_index].plt_offset; |
| 1120 | else if (!need_plt_entry && s1->sym_attrs[sym_index].got_offset) | 1120 | else if (!need_plt_entry && s1->sym_attrs[sym_index].got_offset) |
| 1121 | return s1->sym_attrs[sym_index].got_offset; | 1121 | return s1->sym_attrs[sym_index].got_offset; |
| 1122 | } | 1122 | } |
| 1123 | 1123 | ||
| 1124 | symattr = alloc_sym_attr(s1, sym_index); | 1124 | symattr = alloc_sym_attr(s1, sym_index); |
| @@ -1135,7 +1135,7 @@ static unsigned long put_got_entry(TCCState *s1, · 10 unmodified lines | |||
| 1135 | Section *plt; | 1135 | Section *plt; |
| 1136 | uint8_t *p; | 1136 | uint8_t *p; |
| 1137 | int modrm; | 1137 | int modrm; |
| 1138 | unsigned long relofs; | 1138 | unsigned long relofs; |
| 1139 | 1139 | ||
| 1140 | #if defined(TCC_OUTPUT_DLL_WITH_PLT) | 1140 | #if defined(TCC_OUTPUT_DLL_WITH_PLT) |
| 1141 | modrm = 0x25; | 1141 | modrm = 0x25; |
| @@ -1160,10 +1160,10 @@ static unsigned long put_got_entry(TCCState *s1, · 18 unmodified lines | |||
| 1160 | put32(p + 8, PTR_SIZE * 2); | 1160 | put32(p + 8, PTR_SIZE * 2); |
| 1161 | } | 1161 | } |
| 1162 | 1162 | ||
| 1163 | /* The PLT slot refers to the relocation entry it needs | 1163 | /* The PLT slot refers to the relocation entry it needs |
| 1164 | via offset. The reloc entry is created below, so its | 1164 | via offset. The reloc entry is created below, so its |
| 1165 | offset is the current data_offset. */ | 1165 | offset is the current data_offset. */ |
| 1166 | relofs = s1->got->reloc ? s1->got->reloc->data_offset : 0; | 1166 | relofs = s1->got->reloc ? s1->got->reloc->data_offset : 0; |
| 1167 | symattr->plt_offset = plt->data_offset; | 1167 | symattr->plt_offset = plt->data_offset; |
| 1168 | p = section_ptr_add(plt, 16); | 1168 | p = section_ptr_add(plt, 16); |
| 1169 | p[0] = 0xff; /* jmp *(got + x) */ | 1169 | p[0] = 0xff; /* jmp *(got + x) */ |
| @@ -1171,20 +1171,20 @@ static unsigned long put_got_entry(TCCState *s1, · 1 unmodified line | |||
| 1171 | put32(p + 2, s1->got->data_offset); | 1171 | put32(p + 2, s1->got->data_offset); |
| 1172 | p[6] = 0x68; /* push $xxx */ | 1172 | p[6] = 0x68; /* push $xxx */ |
| 1173 | #ifdef TCC_TARGET_X86_64 | 1173 | #ifdef TCC_TARGET_X86_64 |
| 1174 | /* On x86-64, the relocation is referred to by _index_. */ | 1174 | /* On x86-64, the relocation is referred to by _index_. */ |
| 1175 | put32(p + 7, relofs / sizeof (ElfW_Rel)); | 1175 | put32(p + 7, relofs / sizeof (ElfW_Rel)); |
| 1176 | #else | 1176 | #else |
| 1177 | put32(p + 7, relofs); | 1177 | put32(p + 7, relofs); |
| 1178 | #endif | 1178 | #endif |
| 1179 | p[11] = 0xe9; /* jmp plt_start */ | 1179 | p[11] = 0xe9; /* jmp plt_start */ |
| 1180 | put32(p + 12, -(plt->data_offset)); | 1180 | put32(p + 12, -(plt->data_offset)); |
| 1181 | 1181 | ||
| 1182 | /* If this was an UNDEF symbol set the offset in the | 1182 | /* If this was an UNDEF symbol set the offset in the |
| 1183 | dynsymtab to the PLT slot, so that PC32 relocs to it | 1183 | dynsymtab to the PLT slot, so that PC32 relocs to it |
| 1184 | can be resolved. */ | 1184 | can be resolved. */ |
| 1185 | if (sym->st_shndx == SHN_UNDEF) | 1185 | if (sym->st_shndx == SHN_UNDEF) |
| 1186 | offset = plt->data_offset - 16; | 1186 | offset = plt->data_offset - 16; |
| 1187 | } | 1187 | } |
| 1188 | #elif defined(TCC_TARGET_ARM) | 1188 | #elif defined(TCC_TARGET_ARM) |
| 1189 | if (need_plt_entry) { | 1189 | if (need_plt_entry) { |
| 1190 | Section *plt; | 1190 | Section *plt; |
| @@ -1220,9 +1220,9 @@ static unsigned long put_got_entry(TCCState *s1, · 29 unmodified lines | |||
| 1220 | 1220 | ||
| 1221 | /* the symbol is modified so that it will be relocated to | 1221 | /* the symbol is modified so that it will be relocated to |
| 1222 | the PLT */ | 1222 | the PLT */ |
| 1223 | if (sym->st_shndx == SHN_UNDEF) | 1223 | if (sym->st_shndx == SHN_UNDEF) |
| 1224 | offset = plt->data_offset - 16; | 1224 | offset = plt->data_offset - 16; |
| 1225 | } | 1225 | } |
| 1226 | #elif defined(TCC_TARGET_ARM64) | 1226 | #elif defined(TCC_TARGET_ARM64) |
| 1227 | if (need_plt_entry) { | 1227 | if (need_plt_entry) { |
| 1228 | Section *plt; | 1228 | Section *plt; |
| @@ -1250,29 +1250,29 @@ static unsigned long put_got_entry(TCCState *s1, · 21 unmodified lines | |||
| 1250 | #error unsupported CPU | 1250 | #error unsupported CPU |
| 1251 | #endif | 1251 | #endif |
| 1252 | if (s1->dynsym) { | 1252 | if (s1->dynsym) { |
| 1253 | /* XXX This might generate multiple syms for name. */ | 1253 | /* XXX This might generate multiple syms for name. */ |
| 1254 | index = put_elf_sym(s1->dynsym, offset, | 1254 | index = put_elf_sym(s1->dynsym, offset, |
| 1255 | size, info, 0, sym->st_shndx, name); | 1255 | size, info, 0, sym->st_shndx, name); |
| 1256 | /* Create the relocation (it's against the GOT for PLT | 1256 | /* Create the relocation (it's against the GOT for PLT |
| 1257 | and GOT relocs). */ | 1257 | and GOT relocs). */ |
| 1258 | put_elf_reloc(s1->dynsym, s1->got, | 1258 | put_elf_reloc(s1->dynsym, s1->got, |
| 1259 | s1->got->data_offset, | 1259 | s1->got->data_offset, |
| 1260 | reloc_type, index); | 1260 | reloc_type, index); |
| 1261 | } else { | 1261 | } else { |
| 1262 | /* Without .dynsym (i.e. static link or memory output) we | 1262 | /* Without .dynsym (i.e. static link or memory output) we |
| 1263 | still need relocs against the generated got, so as to fill | 1263 | still need relocs against the generated got, so as to fill |
| 1264 | the entries with the symbol values (determined later). */ | 1264 | the entries with the symbol values (determined later). */ |
| 1265 | put_elf_reloc(symtab_section, s1->got, | 1265 | put_elf_reloc(symtab_section, s1->got, |
| 1266 | s1->got->data_offset, | 1266 | s1->got->data_offset, |
| 1267 | reloc_type, sym_index); | 1267 | reloc_type, sym_index); |
| 1268 | } | 1268 | } |
| 1269 | /* And now create the GOT slot itself. */ | 1269 | /* And now create the GOT slot itself. */ |
| 1270 | ptr = section_ptr_add(s1->got, PTR_SIZE); | 1270 | ptr = section_ptr_add(s1->got, PTR_SIZE); |
| 1271 | *ptr = 0; | 1271 | *ptr = 0; |
| 1272 | if (need_plt_entry) | 1272 | if (need_plt_entry) |
| 1273 | return symattr->plt_offset; | 1273 | return symattr->plt_offset; |
| 1274 | else | 1274 | else |
| 1275 | return symattr->got_offset; | 1275 | return symattr->got_offset; |
| 1276 | } | 1276 | } |
| 1277 | 1277 | ||
| 1278 | /* build GOT and PLT entries */ | 1278 | /* build GOT and PLT entries */ |
| @@ -1324,8 +1324,8 @@ ST_FUNC void build_got_entries(TCCState *s1) · 45 unmodified lines | |||
| 1324 | build_got(s1); | 1324 | build_got(s1); |
| 1325 | sym_index = ELFW(R_SYM)(rel->r_info); | 1325 | sym_index = ELFW(R_SYM)(rel->r_info); |
| 1326 | sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; | 1326 | sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; |
| 1327 | if (type != R_ARM_GOTOFF && type != R_ARM_GOTPC | 1327 | if (type != R_ARM_GOTOFF && type != R_ARM_GOTPC |
| 1328 | && sym->st_shndx == SHN_UNDEF) { | 1328 | && sym->st_shndx == SHN_UNDEF) { |
| 1329 | unsigned long ofs; | 1329 | unsigned long ofs; |
| 1330 | /* look at the symbol got offset. If none, then add one */ | 1330 | /* look at the symbol got offset. If none, then add one */ |
| 1331 | if (type == R_ARM_GOT32) | 1331 | if (type == R_ARM_GOT32) |
| @@ -1333,27 +1333,27 @@ ST_FUNC void build_got_entries(TCCState *s1) · 1 unmodified line | |||
| 1333 | else | 1333 | else |
| 1334 | reloc_type = R_ARM_JUMP_SLOT; | 1334 | reloc_type = R_ARM_JUMP_SLOT; |
| 1335 | ofs = put_got_entry(s1, reloc_type, sym->st_size, | 1335 | ofs = put_got_entry(s1, reloc_type, sym->st_size, |
| 1336 | sym->st_info, sym_index); | 1336 | sym->st_info, sym_index); |
| 1337 | #ifdef DEBUG_RELOC | 1337 | #ifdef DEBUG_RELOC |
| 1338 | printf ("maybegot: %s, %d, %d --> ofs=0x%x\n", | 1338 | printf("maybegot: %s, %d, %d --> ofs=0x%x\n", |
| 1339 | (char *) symtab_section->link->data + sym->st_name, | 1339 | (char *) symtab_section->link->data + sym->st_name, |
| 1340 | type, sym->st_shndx, ofs); | 1340 | type, sym->st_shndx, ofs); |
| 1341 | #endif | 1341 | #endif |
| 1342 | if (type != R_ARM_GOT32) { | 1342 | if (type != R_ARM_GOT32) { |
| 1343 | addr_t *ptr = (addr_t*)(s1->sections[s->sh_info]->data | 1343 | addr_t *ptr = (addr_t*)(s1->sections[s->sh_info]->data |
| 1344 | + rel->r_offset); | 1344 | + rel->r_offset); |
| 1345 | /* x must be signed! */ | 1345 | /* x must be signed! */ |
| 1346 | int x = *ptr & 0xffffff; | 1346 | int x = *ptr & 0xffffff; |
| 1347 | x = (x << 8) >> 8; | 1347 | x = (x << 8) >> 8; |
| 1348 | x <<= 2; | 1348 | x <<= 2; |
| 1349 | x += ofs; | 1349 | x += ofs; |
| 1350 | x >>= 2; | 1350 | x >>= 2; |
| 1351 | #ifdef DEBUG_RELOC | 1351 | #ifdef DEBUG_RELOC |
| 1352 | printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr, | 1352 | printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr, |
| 1353 | (*ptr & 0xff000000) | x, x); | 1353 | (*ptr & 0xff000000) | x, x); |
| 1354 | #endif | 1354 | #endif |
| 1355 | *ptr = (*ptr & 0xff000000) | x; | 1355 | *ptr = (*ptr & 0xff000000) | x; |
| 1356 | } | 1356 | } |
| 1357 | } | 1357 | } |
| 1358 | break; | 1358 | break; |
| 1359 | case R_ARM_THM_JUMP24: | 1359 | case R_ARM_THM_JUMP24: |
| @@ -1397,20 +1397,20 @@ ST_FUNC void build_got_entries(TCCState *s1) · 37 unmodified lines | |||
| 1397 | sym_index); | 1397 | sym_index); |
| 1398 | break; | 1398 | break; |
| 1399 | 1399 | ||
| 1400 | case R_AARCH64_JUMP26: | 1400 | case R_AARCH64_JUMP26: |
| 1401 | case R_AARCH64_CALL26: | 1401 | case R_AARCH64_CALL26: |
| 1402 | if (!s1->got) | 1402 | if (!s1->got) |
| 1403 | build_got(s1); | 1403 | build_got(s1); |
| 1404 | sym_index = ELFW(R_SYM)(rel->r_info); | 1404 | sym_index = ELFW(R_SYM)(rel->r_info); |
| 1405 | sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; | 1405 | sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; |
| 1406 | if (sym->st_shndx == SHN_UNDEF) { | 1406 | if (sym->st_shndx == SHN_UNDEF) { |
| 1407 | unsigned long ofs; | 1407 | unsigned long ofs; |
| 1408 | reloc_type = R_AARCH64_JUMP_SLOT; | 1408 | reloc_type = R_AARCH64_JUMP_SLOT; |
| 1409 | ofs = put_got_entry(s1, reloc_type, sym->st_size, | 1409 | ofs = put_got_entry(s1, reloc_type, sym->st_size, |
| 1410 | sym->st_info, sym_index); | 1410 | sym->st_info, sym_index); |
| 1411 | /* We store the place of the generated PLT slot | 1411 | /* We store the place of the generated PLT slot |
| 1412 | in our addend. */ | 1412 | in our addend. */ |
| 1413 | rel->r_addend += ofs; | 1413 | rel->r_addend += ofs; |
| 1414 | } | 1414 | } |
| 1415 | break; | 1415 | break; |
| 1416 | #elif defined(TCC_TARGET_C67) | 1416 | #elif defined(TCC_TARGET_C67) |
| @@ -1455,7 +1455,7 @@ ST_FUNC void build_got_entries(TCCState *s1) · 38 unmodified lines | |||
| 1455 | if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL) | 1455 | if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL) |
| 1456 | reloc_type = R_X86_64_GLOB_DAT; | 1456 | reloc_type = R_X86_64_GLOB_DAT; |
| 1457 | else | 1457 | else |
| 1458 | reloc_type = R_X86_64_JUMP_SLOT; | 1458 | reloc_type = R_X86_64_JUMP_SLOT; |
| 1459 | ofs = put_got_entry(s1, reloc_type, sym->st_size, | 1459 | ofs = put_got_entry(s1, reloc_type, sym->st_size, |
| 1460 | sym->st_info, sym_index); | 1460 | sym->st_info, sym_index); |
| 1461 | if (type == R_X86_64_PLT32) | 1461 | if (type == R_X86_64_PLT32) |
| @@ -1546,21 +1546,21 @@ static int tcc_add_support(TCCState *s1, const char *filename) · 84 unmodified lines | |||
| 1546 | snprintf(buf, sizeof(buf), "%s/%s/%s", s1->tcc_lib_path, | 1546 | snprintf(buf, sizeof(buf), "%s/%s/%s", s1->tcc_lib_path, |
| 1547 | /* an cpu specific path inside tcc_lib_path, mainly for keeping libtcc1.a */ | 1547 | /* an cpu specific path inside tcc_lib_path, mainly for keeping libtcc1.a */ |
| 1548 | #ifdef TCC_TARGET_I386 | 1548 | #ifdef TCC_TARGET_I386 |
| 1549 | "i386" | 1549 | "i386" |
| 1550 | #endif | 1550 | #endif |
| 1551 | #ifdef TCC_TARGET_X86_64 | 1551 | #ifdef TCC_TARGET_X86_64 |
| 1552 | "x86_64" | 1552 | "x86_64" |
| 1553 | #endif | 1553 | #endif |
| 1554 | #ifdef TCC_TARGET_ARM | 1554 | #ifdef TCC_TARGET_ARM |
| 1555 | "arm" | 1555 | "arm" |
| 1556 | #endif | 1556 | #endif |
| 1557 | #ifdef TCC_TARGET_ARM64 | 1557 | #ifdef TCC_TARGET_ARM64 |
| 1558 | "arm64" | 1558 | "arm64" |
| 1559 | #endif | 1559 | #endif |
| 1560 | #ifdef TCC_TARGET_C67 | 1560 | #ifdef TCC_TARGET_C67 |
| 1561 | "C67" | 1561 | "C67" |
| 1562 | #endif | 1562 | #endif |
| 1563 | ,filename); | 1563 | , filename); |
| 1564 | 1564 | ||
| 1565 | return tcc_add_file(s1, buf, TCC_FILETYPE_BINARY); | 1565 | return tcc_add_file(s1, buf, TCC_FILETYPE_BINARY); |
| 1566 | } | 1566 | } |
| @@ -1587,16 +1587,16 @@ ST_FUNC void tcc_add_bcheck(TCCState *s1) · 20 unmodified lines | |||
| 1587 | when __bound_ptr_add, __bound_new_region, | 1587 | when __bound_ptr_add, __bound_new_region, |
| 1588 | __bound_delete_region called */ | 1588 | __bound_delete_region called */ |
| 1589 | 1589 | ||
| 1590 | int sym_index = find_elf_sym(symtab_section, "__bound_init"); | 1590 | int sym_index = find_elf_sym(symtab_section, "__bound_init"); |
| 1591 | if (sym_index) { | 1591 | if (sym_index) { |
| 1592 | Section *init_section = find_section(s1, ".init"); | 1592 | Section *init_section = find_section(s1, ".init"); |
| 1593 | unsigned char *pinit = section_ptr_add(init_section, 5); | 1593 | unsigned char *pinit = section_ptr_add(init_section, 5); |
| 1594 | pinit[0] = 0xe8; | 1594 | pinit[0] = 0xe8; |
| 1595 | put32(pinit + 1, -4); | 1595 | put32(pinit + 1, -4); |
| 1596 | put_elf_reloc(symtab_section, init_section, | 1596 | put_elf_reloc(symtab_section, init_section, |
| 1597 | init_section->data_offset - 4, R_386_PC32, sym_index); | 1597 | init_section->data_offset - 4, R_386_PC32, sym_index); |
| 1598 | } | 1598 | } |
| 1599 | else | 1599 | else |
| 1600 | tcc_warning("__bound_init not defined"); | 1600 | tcc_warning("__bound_init not defined"); |
| 1601 | } | 1601 | } |
| 1602 | #endif | 1602 | #endif |
| @@ -1905,11 +1905,11 @@ static void export_global_syms(TCCState *s1) · 302 unmodified lines | |||
| 1905 | s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms); | 1905 | s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms); |
| 1906 | for_each_elem(symtab_section, 1, sym, ElfW(Sym)) { | 1906 | for_each_elem(symtab_section, 1, sym, ElfW(Sym)) { |
| 1907 | if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { | 1907 | if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { |
| 1908 | name = (char *) symtab_section->link->data + sym->st_name; | 1908 | name = (char *) symtab_section->link->data + sym->st_name; |
| 1909 | dynindex = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, | 1909 | dynindex = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, |
| 1910 | sym->st_info, 0, sym->st_shndx, name); | 1910 | sym->st_info, 0, sym->st_shndx, name); |
| 1911 | index = sym - (ElfW(Sym) *) symtab_section->data; | 1911 | index = sym - (ElfW(Sym) *) symtab_section->data; |
| 1912 | s1->symtab_to_dynsym[index] = dynindex; | 1912 | s1->symtab_to_dynsym[index] = dynindex; |
| 1913 | } | 1913 | } |
| 1914 | } | 1914 | } |
| 1915 | } | 1915 | } |
| @@ -2179,15 +2179,15 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 263 unmodified lines | |||
| 2179 | file_offset += s->sh_size; | 2179 | file_offset += s->sh_size; |
| 2180 | } | 2180 | } |
| 2181 | } | 2181 | } |
| 2182 | if (j == 0) { | 2182 | if (j == 0) { |
| 2183 | /* Make the first PT_LOAD segment include the program | 2183 | /* Make the first PT_LOAD segment include the program |
| 2184 | headers itself (and the ELF header as well), it'll | 2184 | headers itself (and the ELF header as well), it'll |
| 2185 | come out with same memory use but will make various | 2185 | come out with same memory use but will make various |
| 2186 | tools like binutils strip work better. */ | 2186 | tools like binutils strip work better. */ |
| 2187 | ph->p_offset &= ~(ph->p_align - 1); | 2187 | ph->p_offset &= ~(ph->p_align - 1); |
| 2188 | ph->p_vaddr &= ~(ph->p_align - 1); | 2188 | ph->p_vaddr &= ~(ph->p_align - 1); |
| 2189 | ph->p_paddr &= ~(ph->p_align - 1); | 2189 | ph->p_paddr &= ~(ph->p_align - 1); |
| 2190 | } | 2190 | } |
| 2191 | ph->p_filesz = file_offset - ph->p_offset; | 2191 | ph->p_filesz = file_offset - ph->p_offset; |
| 2192 | ph->p_memsz = addr - ph->p_vaddr; | 2192 | ph->p_memsz = addr - ph->p_vaddr; |
| 2193 | ph++; | 2193 | ph++; |
| @@ -2662,10 +2662,10 @@ static int elf_output_file(TCCState *s1, const char *filename) · 468 unmodified lines | |||
| 2662 | for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) { | 2662 | for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) { |
| 2663 | if (sym->st_shndx == SHN_UNDEF) { | 2663 | if (sym->st_shndx == SHN_UNDEF) { |
| 2664 | /* relocate to PLT if symbol corresponds to a PLT entry, | 2664 | /* relocate to PLT if symbol corresponds to a PLT entry, |
| 2665 | but not if it's a weak symbol */ | 2665 | but not if it's a weak symbol */ |
| 2666 | if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK) | 2666 | if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK) |
| 2667 | sym->st_value = 0; | 2667 | sym->st_value = 0; |
| 2668 | else if (sym->st_value) | 2668 | else if (sym->st_value) |
| 2669 | sym->st_value += s1->plt->sh_addr; | 2669 | sym->st_value += s1->plt->sh_addr; |
| 2670 | } else if (sym->st_shndx < SHN_LORESERVE) { | 2670 | } else if (sym->st_shndx < SHN_LORESERVE) { |
| 2671 | /* do symbol relocation */ | 2671 | /* do symbol relocation */ |
| @@ -2690,14 +2690,14 @@ static int elf_output_file(TCCState *s1, const char *filename) · 18 unmodified lines | |||
| 2690 | /* Create the ELF file with name 'filename' */ | 2690 | /* Create the ELF file with name 'filename' */ |
| 2691 | ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order); | 2691 | ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order); |
| 2692 | if (s1->do_strip) { | 2692 | if (s1->do_strip) { |
| 2693 | int rc; | 2693 | int rc; |
| 2694 | const char *strip_cmd = "sstrip "; // super strip utility from ELFkickers | 2694 | const char *strip_cmd = "sstrip "; // super strip utility from ELFkickers |
| 2695 | const char *null_dev = " 2> /dev/null"; | 2695 | const char *null_dev = " 2> /dev/null"; |
| 2696 | char buf[1050]; | 2696 | char buf[1050]; |
| 2697 | snprintf(buf, sizeof(buf), "%s%s%s", strip_cmd, filename, null_dev); | 2697 | snprintf(buf, sizeof(buf), "%s%s%s", strip_cmd, filename, null_dev); |
| 2698 | rc = system(buf); | 2698 | rc = system(buf); |
| 2699 | if (rc) | 2699 | if (rc) |
| 2700 | system(buf+1); // call a strip utility from binutils | 2700 | system(buf+1); // call a strip utility from binutils |
| 2701 | } | 2701 | } |
| 2702 | the_end: | 2702 | the_end: |
| 2703 | tcc_free(s1->symtab_to_dynsym); | 2703 | tcc_free(s1->symtab_to_dynsym); |
| @@ -1761,18 +1761,18 @@ ST_FUNC void gen_op(int op) · 1760 unmodified lines | |||
| 1761 | #if 0 | 1761 | #if 0 |
| 1762 | /* #ifdef CONFIG_TCC_BCHECK | 1762 | /* #ifdef CONFIG_TCC_BCHECK |
| 1763 | The main reason to removing this code: | 1763 | The main reason to removing this code: |
| 1764 | #include <stdio.h> | 1764 | #include <stdio.h> |
| 1765 | int main () | 1765 | int main () |
| 1766 | { | 1766 | { |
| 1767 | int v[10]; | 1767 | int v[10]; |
| 1768 | int i = 10; | 1768 | int i = 10; |
| 1769 | int j = 9; | 1769 | int j = 9; |
| 1770 | fprintf(stderr, "v+i-j = %p\n", v+i-j); | 1770 | fprintf(stderr, "v+i-j = %p\n", v+i-j); |
| 1771 | fprintf(stderr, "v+(i-j) = %p\n", v+(i-j)); | 1771 | fprintf(stderr, "v+(i-j) = %p\n", v+(i-j)); |
| 1772 | } | 1772 | } |
| 1773 | When this code is on. then the output looks like | 1773 | When this code is on. then the output looks like |
| 1774 | v+i-j = 0xfffffffe | 1774 | v+i-j = 0xfffffffe |
| 1775 | v+(i-j) = 0xbff84000 | 1775 | v+(i-j) = 0xbff84000 |
| 1776 | */ | 1776 | */ |
| 1777 | /* if evaluating constant expression, no code should be | 1777 | /* if evaluating constant expression, no code should be |
| 1778 | generated, so no bound check */ | 1778 | generated, so no bound check */ |
| @@ -2450,18 +2450,18 @@ static void gen_assign_cast(CType *dt) · 671 unmodified lines | |||
| 2450 | dbt = dt->t & VT_BTYPE; | 2450 | dbt = dt->t & VT_BTYPE; |
| 2451 | sbt = st->t & VT_BTYPE; | 2451 | sbt = st->t & VT_BTYPE; |
| 2452 | if (sbt == VT_VOID || dbt == VT_VOID) { | 2452 | if (sbt == VT_VOID || dbt == VT_VOID) { |
| 2453 | if (sbt == VT_VOID && dbt == VT_VOID) | 2453 | if (sbt == VT_VOID && dbt == VT_VOID) |
| 2454 | ; /* | 2454 | ; /* |
| 2455 | It is Ok if both are void | 2455 | It is Ok if both are void |
| 2456 | A test program: | 2456 | A test program: |
| 2457 | void func1() {} | 2457 | void func1() {} |
| 2458 | void func2() { | 2458 | void func2() { |
| 2459 | return func1(); | 2459 | return func1(); |
| 2460 | } | 2460 | } |
| 2461 | gcc accepts this program | 2461 | gcc accepts this program |
| 2462 | */ | 2462 | */ |
| 2463 | else | 2463 | else |
| 2464 | tcc_error("cannot cast from/to void"); | 2464 | tcc_error("cannot cast from/to void"); |
| 2465 | } | 2465 | } |
| 2466 | if (dt->t & VT_CONSTANT) | 2466 | if (dt->t & VT_CONSTANT) |
| 2467 | tcc_warning("assignment of read-only location"); | 2467 | tcc_warning("assignment of read-only location"); |
| @@ -2542,7 +2542,7 @@ ST_FUNC void vstore(void) · 74 unmodified lines | |||
| 2542 | dbt = ft & VT_BTYPE; | 2542 | dbt = ft & VT_BTYPE; |
| 2543 | if ((((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) || | 2543 | if ((((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) || |
| 2544 | (sbt == VT_INT && dbt == VT_SHORT)) | 2544 | (sbt == VT_INT && dbt == VT_SHORT)) |
| 2545 | && !(vtop->type.t & VT_BITFIELD)) { | 2545 | && !(vtop->type.t & VT_BITFIELD)) { |
| 2546 | /* optimize char/short casts */ | 2546 | /* optimize char/short casts */ |
| 2547 | delayed_cast = VT_MUSTCAST; | 2547 | delayed_cast = VT_MUSTCAST; |
| 2548 | vtop->type.t = ft & (VT_TYPE & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT))); | 2548 | vtop->type.t = ft & (VT_TYPE & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT))); |
| @@ -2764,20 +2764,20 @@ static void parse_attribute(AttributeDef *ad) · 215 unmodified lines | |||
| 2764 | next(); | 2764 | next(); |
| 2765 | skip(')'); | 2765 | skip(')'); |
| 2766 | break; | 2766 | break; |
| 2767 | case TOK_VISIBILITY1: | 2767 | case TOK_VISIBILITY1: |
| 2768 | case TOK_VISIBILITY2: | 2768 | case TOK_VISIBILITY2: |
| 2769 | skip('('); | 2769 | skip('('); |
| 2770 | if (tok != TOK_STR) | 2770 | if (tok != TOK_STR) |
| 2771 | expect("visibility(\"default|hidden|internal|protected\")"); | 2771 | expect("visibility(\"default|hidden|internal|protected\")"); |
| 2772 | if (!strcmp (tokc.cstr->data, "default")) | 2772 | if (!strcmp (tokc.cstr->data, "default")) |
| 2773 | ad->a.visibility = STV_DEFAULT; | 2773 | ad->a.visibility = STV_DEFAULT; |
| 2774 | else if (!strcmp (tokc.cstr->data, "hidden")) | 2774 | else if (!strcmp (tokc.cstr->data, "hidden")) |
| 2775 | ad->a.visibility = STV_HIDDEN; | 2775 | ad->a.visibility = STV_HIDDEN; |
| 2776 | else if (!strcmp (tokc.cstr->data, "internal")) | 2776 | else if (!strcmp (tokc.cstr->data, "internal")) |
| 2777 | ad->a.visibility = STV_INTERNAL; | 2777 | ad->a.visibility = STV_INTERNAL; |
| 2778 | else if (!strcmp (tokc.cstr->data, "protected")) | 2778 | else if (!strcmp (tokc.cstr->data, "protected")) |
| 2779 | ad->a.visibility = STV_PROTECTED; | 2779 | ad->a.visibility = STV_PROTECTED; |
| 2780 | else | 2780 | else |
| 2781 | expect("visibility(\"default|hidden|internal|protected\")"); | 2781 | expect("visibility(\"default|hidden|internal|protected\")"); |
| 2782 | next(); | 2782 | next(); |
| 2783 | skip(')'); | 2783 | skip(')'); |
| @@ -2973,8 +2973,8 @@ static void struct_decl(CType *type, int u, int tdef) · 189 unmodified lines | |||
| 2973 | while (tok != '}') { | 2973 | while (tok != '}') { |
| 2974 | parse_btype(&btype, &ad); | 2974 | parse_btype(&btype, &ad); |
| 2975 | while (1) { | 2975 | while (1) { |
| 2976 | if (flexible) | 2976 | if (flexible) |
| 2977 | tcc_error("flexible array member '%s' not at the end of struct", | 2977 | tcc_error("flexible array member '%s' not at the end of struct", |
| 2978 | get_tok_str(v, NULL)); | 2978 | get_tok_str(v, NULL)); |
| 2979 | bit_size = -1; | 2979 | bit_size = -1; |
| 2980 | v = 0; | 2980 | v = 0; |
| @@ -2990,14 +2990,14 @@ static void struct_decl(CType *type, int u, int tdef) · 9 unmodified lines | |||
| 2990 | if (tcc_state->ms_extensions == 0) | 2990 | if (tcc_state->ms_extensions == 0) |
| 2991 | expect("identifier"); | 2991 | expect("identifier"); |
| 2992 | } | 2992 | } |
| 2993 | } | 2993 | } |
| 2994 | } | 2994 | } |
| 2995 | if (type_size(&type1, &align) < 0) { | 2995 | if (type_size(&type1, &align) < 0) { |
| 2996 | if ((a == TOK_STRUCT) && (type1.t & VT_ARRAY) && c) | 2996 | if ((a == TOK_STRUCT) && (type1.t & VT_ARRAY) && c) |
| 2997 | flexible = 1; | 2997 | flexible = 1; |
| 2998 | else | 2998 | else |
| 2999 | tcc_error("field '%s' has incomplete type", | 2999 | tcc_error("field '%s' has incomplete type", |
| 3000 | get_tok_str(v, NULL)); | 3000 | get_tok_str(v, NULL)); |
| 3001 | } | 3001 | } |
| 3002 | if ((type1.t & VT_BTYPE) == VT_FUNC || | 3002 | if ((type1.t & VT_BTYPE) == VT_FUNC || |
| 3003 | (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE))) | 3003 | (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE))) |
| @@ -3807,11 +3807,11 @@ ST_FUNC void unary(void) · 803 unmodified lines | |||
| 3807 | gen_cast(&type); | 3807 | gen_cast(&type); |
| 3808 | } | 3808 | } |
| 3809 | } else if (tok == '{') { | 3809 | } else if (tok == '{') { |
| 3810 | /* | 3810 | /* |
| 3811 | if (nocode_wanted) | 3811 | if (nocode_wanted) |
| 3812 | tcc_error("statement expression in global scope"); */ | 3812 | tcc_error("statement expression in global scope"); */ |
| 3813 | /* this check breaks compilation of the linux 2.4.26 with the meesage: | 3813 | /* this check breaks compilation of the linux 2.4.26 with the meesage: |
| 3814 | linux/include/net/tcp.h:945: error: statement expression in global scope */ | 3814 | linux/include/net/tcp.h:945: error: statement expression in global scope */ |
| 3815 | 3815 | ||
| 3816 | /* save all registers */ | 3816 | /* save all registers */ |
| 3817 | save_regs(0); | 3817 | save_regs(0); |
| @@ -3872,12 +3872,12 @@ ST_FUNC void unary(void) · 54 unmodified lines | |||
| 3872 | if ((vtop->type.t & VT_BTYPE) == VT_PTR) | 3872 | if ((vtop->type.t & VT_BTYPE) == VT_PTR) |
| 3873 | tcc_error("pointer not accepted for unary plus"); | 3873 | tcc_error("pointer not accepted for unary plus"); |
| 3874 | /* In order to force cast, we add zero, except for floating point | 3874 | /* In order to force cast, we add zero, except for floating point |
| 3875 | where we really need an noop (otherwise -0.0 will be transformed | 3875 | where we really need an noop (otherwise -0.0 will be transformed |
| 3876 | into +0.0). */ | 3876 | into +0.0). */ |
| 3877 | if (!is_float(vtop->type.t)) { | 3877 | if (!is_float(vtop->type.t)) { |
| 3878 | vpushi(0); | 3878 | vpushi(0); |
| 3879 | gen_op('+'); | 3879 | gen_op('+'); |
| 3880 | } | 3880 | } |
| 3881 | break; | 3881 | break; |
| 3882 | case TOK_SIZEOF: | 3882 | case TOK_SIZEOF: |
| 3883 | case TOK_ALIGNOF1: | 3883 | case TOK_ALIGNOF1: |
| @@ -4050,20 +4050,20 @@ ST_FUNC void unary(void) · 166 unmodified lines | |||
| 4050 | next(); | 4050 | next(); |
| 4051 | unary(); | 4051 | unary(); |
| 4052 | t = vtop->type.t & VT_BTYPE; | 4052 | t = vtop->type.t & VT_BTYPE; |
| 4053 | if (is_float(t)) { | 4053 | if (is_float(t)) { |
| 4054 | /* In IEEE negate(x) isn't subtract(0,x), but rather | 4054 | /* In IEEE negate(x) isn't subtract(0,x), but rather |
| 4055 | subtract(-0, x). */ | 4055 | subtract(-0, x). */ |
| 4056 | vpush(&vtop->type); | 4056 | vpush(&vtop->type); |
| 4057 | if (t == VT_FLOAT) | 4057 | if (t == VT_FLOAT) |
| 4058 | vtop->c.f = -0.0f; | 4058 | vtop->c.f = -0.0f; |
| 4059 | else if (t == VT_DOUBLE) | 4059 | else if (t == VT_DOUBLE) |
| 4060 | vtop->c.d = -0.0; | 4060 | vtop->c.d = -0.0; |
| 4061 | else | 4061 | else |
| 4062 | vtop->c.ld = -0.0; | 4062 | vtop->c.ld = -0.0; |
| 4063 | } else | 4063 | } else |
| 4064 | vpushi(0); | 4064 | vpushi(0); |
| 4065 | vswap(); | 4065 | vswap(); |
| 4066 | gen_op('-'); | 4066 | gen_op('-'); |
| 4067 | break; | 4067 | break; |
| 4068 | case TOK_LAND: | 4068 | case TOK_LAND: |
| 4069 | if (!gnu_ext) | 4069 | if (!gnu_ext) |
| @@ -4142,7 +4142,7 @@ ST_FUNC void unary(void) · 72 unmodified lines | |||
| 4142 | /* if forward reference, we must point to s */ | 4142 | /* if forward reference, we must point to s */ |
| 4143 | if (vtop->r & VT_SYM) { | 4143 | if (vtop->r & VT_SYM) { |
| 4144 | vtop->sym = s; | 4144 | vtop->sym = s; |
| 4145 | vtop->c.ptr_offset = 0; | 4145 | vtop->c.ptr_offset = 0; |
| 4146 | } | 4146 | } |
| 4147 | break; | 4147 | break; |
| 4148 | } | 4148 | } |
| @@ -4312,10 +4312,10 @@ ST_FUNC void unary(void) · 163 unmodified lines | |||
| 4312 | 4312 | ||
| 4313 | 4313 | ||
| 4314 | size = type_size(&s->type, &align); | 4314 | size = type_size(&s->type, &align); |
| 4315 | /* We're writing whole regs often, make sure there's enough | 4315 | /* We're writing whole regs often, make sure there's enough |
| 4316 | space. Assume register size is power of 2. */ | 4316 | space. Assume register size is power of 2. */ |
| 4317 | if (regsize > align) | 4317 | if (regsize > align) |
| 4318 | align = regsize; | 4318 | align = regsize; |
| 4319 | loc = (loc - size) & -align; | 4319 | loc = (loc - size) & -align; |
| 4320 | addr = loc; | 4320 | addr = loc; |
| 4321 | #if defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_PE) | 4321 | #if defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_PE) |
| @@ -4610,16 +4610,16 @@ static void expr_cond(void) · 288 unmodified lines | |||
| 4610 | (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED)) | 4610 | (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED)) |
| 4611 | type.t |= VT_UNSIGNED; | 4611 | type.t |= VT_UNSIGNED; |
| 4612 | } else if (bt1 == VT_PTR || bt2 == VT_PTR) { | 4612 | } else if (bt1 == VT_PTR || bt2 == VT_PTR) { |
| 4613 | /* If one is a null ptr constant the result type | 4613 | /* If one is a null ptr constant the result type |
| 4614 | is the other. */ | 4614 | is the other. */ |
| 4615 | if (is_null_pointer (vtop)) | 4615 | if (is_null_pointer (vtop)) |
| 4616 | type = type1; | 4616 | type = type1; |
| 4617 | else if (is_null_pointer (&sv)) | 4617 | else if (is_null_pointer (&sv)) |
| 4618 | type = type2; | 4618 | type = type2; |
| 4619 | /* XXX: test pointer compatibility, C99 has more elaborate | 4619 | /* XXX: test pointer compatibility, C99 has more elaborate |
| 4620 | rules here. */ | 4620 | rules here. */ |
| 4621 | else | 4621 | else |
| 4622 | type = type1; | 4622 | type = type1; |
| 4623 | } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) { | 4623 | } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) { |
| 4624 | /* XXX: test function pointer compatibility */ | 4624 | /* XXX: test function pointer compatibility */ |
| 4625 | type = bt1 == VT_FUNC ? type1 : type2; | 4625 | type = bt1 == VT_FUNC ? type1 : type2; |
| @@ -4783,17 +4783,16 @@ static void label_or_decl(int l) · 157 unmodified lines | |||
| 4783 | int last_tok; | 4783 | int last_tok; |
| 4784 | 4784 | ||
| 4785 | /* fast test first */ | 4785 | /* fast test first */ |
| 4786 | if (tok >= TOK_UIDENT) | 4786 | if (tok >= TOK_UIDENT) { |
| 4787 | { | 4787 | /* no need to save tokc because tok is an identifier */ |
| 4788 | /* no need to save tokc because tok is an identifier */ | 4788 | last_tok = tok; |
| 4789 | last_tok = tok; | 4789 | next(); |
| 4790 | next(); | 4790 | if (tok == ':') { |
| 4791 | if (tok == ':') { | 4791 | unget_tok(last_tok); |
| 4792 | return; | ||
| 4793 | } | ||
| 4792 | unget_tok(last_tok); | 4794 | unget_tok(last_tok); |
| 4793 | return; | ||
| 4794 | } | 4795 | } |
| 4795 | unget_tok(last_tok); | ||
| 4796 | } | ||
| 4797 | decl(l); | 4796 | decl(l); |
| 4798 | } | 4797 | } |
| 4799 | 4798 | ||
| @@ -4891,10 +4890,10 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 91 unmodified lines | |||
| 4891 | Sym *p; | 4890 | Sym *p; |
| 4892 | switch(vtop->type.t & VT_BTYPE) { | 4891 | switch(vtop->type.t & VT_BTYPE) { |
| 4893 | /* case VT_PTR: */ | 4892 | /* case VT_PTR: */ |
| 4894 | /* this breaks a compilation of the linux kernel v2.4.26 */ | 4893 | /* this breaks a compilation of the linux kernel v2.4.26 */ |
| 4895 | /* pmd_t *new = ({ __asm__ __volatile__("ud2\n") ; ((pmd_t *)1); }); */ | 4894 | /* pmd_t *new = ({ __asm__ __volatile__("ud2\n") ; ((pmd_t *)1); }); */ |
| 4896 | /* Look a commit a80acab: Display error on statement expressions with complex return type */ | 4895 | /* Look a commit a80acab: Display error on statement expressions with complex return type */ |
| 4897 | /* A pointer is not a complex return type */ | 4896 | /* A pointer is not a complex return type */ |
| 4898 | case VT_STRUCT: | 4897 | case VT_STRUCT: |
| 4899 | case VT_ENUM: | 4898 | case VT_ENUM: |
| 4900 | case VT_FUNC: | 4899 | case VT_FUNC: |
| @@ -5642,38 +5641,38 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 741 unmodified lines | |||
| 5642 | AttributeDef ad1; | 5641 | AttributeDef ad1; |
| 5643 | CType type1; | 5642 | CType type1; |
| 5644 | next(); | 5643 | next(); |
| 5645 | if (tcc_state->old_struct_init_code) { | 5644 | if (tcc_state->old_struct_init_code) { |
| 5646 | /* an old version of struct initialization. | 5645 | /* an old version of struct initialization. |
| 5647 | It have a problems. But with a new version | 5646 | It have a problems. But with a new version |
| 5648 | linux 2.4.26 can't load ramdisk. | 5647 | linux 2.4.26 can't load ramdisk. |
| 5649 | */ | 5648 | */ |
| 5650 | while (tok == '(') { | 5649 | while (tok == '(') { |
| 5651 | par_count++; | 5650 | par_count++; |
| 5652 | next(); | 5651 | next(); |
| 5653 | } | 5652 | } |
| 5654 | if (!parse_btype(&type1, &ad1)) | ||
| 5655 | expect("cast"); | ||
| 5656 | type_decl(&type1, &ad1, &n, TYPE_ABSTRACT); | ||
| 5657 | #if 0 | ||
| 5658 | if (!is_assignable_types(type, &type1)) | ||
| 5659 | tcc_error("invalid type for cast"); | ||
| 5660 | #endif | ||
| 5661 | skip(')'); | ||
| 5662 | } | ||
| 5663 | else | ||
| 5664 | { | ||
| 5665 | if (tok != '(') { | ||
| 5666 | if (!parse_btype(&type1, &ad1)) | 5653 | if (!parse_btype(&type1, &ad1)) |
| 5654 | expect("cast"); | ||
| 5655 | type_decl(&type1, &ad1, &n, TYPE_ABSTRACT); | ||
| 5656 | #if 0 | ||
| 5657 | if (!is_assignable_types(type, &type1)) | ||
| 5658 | tcc_error("invalid type for cast"); | ||
| 5659 | #endif | ||
| 5660 | skip(')'); | ||
| 5661 | } | ||
| 5662 | else | ||
| 5663 | { | ||
| 5664 | if (tok != '(') { | ||
| 5665 | if (!parse_btype(&type1, &ad1)) | ||
| 5667 | expect("cast"); | 5666 | expect("cast"); |
| 5668 | type_decl(&type1, &ad1, &n, TYPE_ABSTRACT); | 5667 | type_decl(&type1, &ad1, &n, TYPE_ABSTRACT); |
| 5669 | #if 0 | 5668 | #if 0 |
| 5670 | if (!is_assignable_types(type, &type1)) | 5669 | if (!is_assignable_types(type, &type1)) |
| 5671 | tcc_error("invalid type for cast"); | 5670 | tcc_error("invalid type for cast"); |
| 5672 | #endif | 5671 | #endif |
| 5673 | skip(')'); | 5672 | skip(')'); |
| 5674 | } else | 5673 | } else |
| 5675 | unget_tok(tok); | 5674 | unget_tok(tok); |
| 5676 | } | 5675 | } |
| 5677 | } | 5676 | } |
| 5678 | 5677 | ||
| 5679 | no_oblock = 1; | 5678 | no_oblock = 1; |
| @@ -5699,28 +5698,28 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 19 unmodified lines | |||
| 5699 | 5698 | ||
| 5700 | /* gr: skip fields from same union - ugly. */ | 5699 | /* gr: skip fields from same union - ugly. */ |
| 5701 | while (f->next) { | 5700 | while (f->next) { |
| 5702 | int align = 0; | 5701 | int align = 0; |
| 5703 | int f_size = type_size(&f->type, &align); | 5702 | int f_size = type_size(&f->type, &align); |
| 5704 | int f_type = (f->type.t & VT_BTYPE); | 5703 | int f_type = (f->type.t & VT_BTYPE); |
| 5705 | 5704 | ||
| 5706 | ///printf("index: %2d %08x -- %2d %08x\n", f->c, f->type.t, f->next->c, f->next->type.t); | 5705 | ///printf("index: %2d %08x -- %2d %08x\n", f->c, f->type.t, f->next->c, f->next->type.t); |
| 5707 | /* test for same offset */ | 5706 | /* test for same offset */ |
| 5708 | if (f->next->c != f->c) | 5707 | if (f->next->c != f->c) |
| 5709 | break; | 5708 | break; |
| 5710 | if ((f_type == VT_STRUCT) && (f_size == 0)) { | 5709 | if ((f_type == VT_STRUCT) && (f_size == 0)) { |
| 5711 | /* | 5710 | /* |
| 5712 | Lets assume a structure of size 0 can't be a member of the union. | 5711 | Lets assume a structure of size 0 can't be a member of the union. |
| 5713 | This allow to compile the following code from a linux kernel v2.4.26 | 5712 | This allow to compile the following code from a linux kernel v2.4.26 |
| 5714 | typedef struct { } rwlock_t; | 5713 | typedef struct { } rwlock_t; |
| 5715 | struct fs_struct { | 5714 | struct fs_struct { |
| 5716 | int count; | 5715 | int count; |
| 5717 | rwlock_t lock; | 5716 | rwlock_t lock; |
| 5718 | int umask; | 5717 | int umask; |
| 5719 | }; | 5718 | }; |
| 5720 | struct fs_struct init_fs = { { (1) }, (rwlock_t) {}, 0022, }; | 5719 | struct fs_struct init_fs = { { (1) }, (rwlock_t) {}, 0022, }; |
| 5721 | tcc-0.9.23 can succesfully compile this version of the kernel. | 5720 | tcc-0.9.23 can succesfully compile this version of the kernel. |
| 5722 | gcc don't have problems with this code too. | 5721 | gcc don't have problems with this code too. |
| 5723 | */ | 5722 | */ |
| 5724 | break; | 5723 | break; |
| 5725 | } | 5724 | } |
| 5726 | /* if yes, test for bitfield shift */ | 5725 | /* if yes, test for bitfield shift */ |
| @@ -5760,21 +5759,21 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 33 unmodified lines | |||
| 5760 | /* just skip expression */ | 5759 | /* just skip expression */ |
| 5761 | parlevel = parlevel1 = 0; | 5760 | parlevel = parlevel1 = 0; |
| 5762 | while ((parlevel > 0 || parlevel1 > 0 || | 5761 | while ((parlevel > 0 || parlevel1 > 0 || |
| 5763 | (tok != '}' && tok != ',')) && tok != -1) { | 5762 | (tok != '}' && tok != ',')) && tok != -1) { |
| 5764 | if (tok == '(') | 5763 | if (tok == '(') |
| 5765 | parlevel++; | 5764 | parlevel++; |
| 5766 | else if (tok == ')') { | 5765 | else if (tok == ')') { |
| 5767 | if (parlevel == 0 && parlevel1 == 0) | 5766 | if (parlevel == 0 && parlevel1 == 0) |
| 5768 | break; | 5767 | break; |
| 5769 | parlevel--; | 5768 | parlevel--; |
| 5770 | } | 5769 | } |
| 5771 | else if (tok == '{') | 5770 | else if (tok == '{') |
| 5772 | parlevel1++; | 5771 | parlevel1++; |
| 5773 | else if (tok == '}') { | 5772 | else if (tok == '}') { |
| 5774 | if (parlevel == 0 && parlevel1 == 0) | 5773 | if (parlevel == 0 && parlevel1 == 0) |
| 5775 | break; | 5774 | break; |
| 5776 | parlevel1--; | 5775 | parlevel1--; |
| 5777 | } | 5776 | } |
| 5778 | next(); | 5777 | next(); |
| 5779 | } | 5778 | } |
| 5780 | } else { | 5779 | } else { |
| @@ -5995,12 +5994,12 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 214 unmodified lines | |||
| 5995 | } else { | 5994 | } else { |
| 5996 | /* push global reference */ | 5995 | /* push global reference */ |
| 5997 | sym = get_sym_ref(type, sec, addr, size); | 5996 | sym = get_sym_ref(type, sec, addr, size); |
| 5998 | vpushsym(type, sym); | 5997 | vpushsym(type, sym); |
| 5999 | } | 5998 | } |
| 6000 | /* patch symbol weakness */ | 5999 | /* patch symbol weakness */ |
| 6001 | if (type->t & VT_WEAK) | 6000 | if (type->t & VT_WEAK) |
| 6002 | weaken_symbol(sym); | 6001 | weaken_symbol(sym); |
| 6003 | apply_visibility(sym, type); | 6002 | apply_visibility(sym, type); |
| 6004 | #ifdef CONFIG_TCC_BCHECK | 6003 | #ifdef CONFIG_TCC_BCHECK |
| 6005 | /* handles bounds now because the symbol must be defined | 6004 | /* handles bounds now because the symbol must be defined |
| 6006 | before for the relocation */ | 6005 | before for the relocation */ |
| @@ -6236,11 +6235,11 @@ static int decl0(int l, int is_for_loop_init) · 229 unmodified lines | |||
| 6236 | if (((btype.t & VT_BTYPE) == VT_ENUM || | 6235 | if (((btype.t & VT_BTYPE) == VT_ENUM || |
| 6237 | (btype.t & VT_BTYPE) == VT_STRUCT) && | 6236 | (btype.t & VT_BTYPE) == VT_STRUCT) && |
| 6238 | tok == ';') { | 6237 | tok == ';') { |
| 6239 | if ((btype.t & VT_BTYPE) == VT_STRUCT) { | 6238 | if ((btype.t & VT_BTYPE) == VT_STRUCT) { |
| 6240 | int v = btype.ref->v; | 6239 | int v = btype.ref->v; |
| 6241 | if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) >= SYM_FIRST_ANOM) | 6240 | if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) >= SYM_FIRST_ANOM) |
| 6242 | tcc_warning("unnamed struct/union that defines no instances"); | 6241 | tcc_warning("unnamed struct/union that defines no instances"); |
| 6243 | } | 6242 | } |
| 6244 | next(); | 6243 | next(); |
| 6245 | continue; | 6244 | continue; |
| 6246 | } | 6245 | } |
| @@ -6286,7 +6285,7 @@ static int decl0(int l, int is_for_loop_init) · 39 unmodified lines | |||
| 6286 | if (ad.a.func_export) | 6285 | if (ad.a.func_export) |
| 6287 | type.t |= VT_EXPORT; | 6286 | type.t |= VT_EXPORT; |
| 6288 | #endif | 6287 | #endif |
| 6289 | type.t |= ad.a.visibility << VT_VIS_SHIFT; | 6288 | type.t |= ad.a.visibility << VT_VIS_SHIFT; |
| 6290 | 6289 | ||
| 6291 | if (tok == '{') { | 6290 | if (tok == '{') { |
| 6292 | if (l == VT_LOCAL) | 6291 | if (l == VT_LOCAL) |
| @@ -6327,10 +6326,10 @@ static int decl0(int l, int is_for_loop_init) · 34 unmodified lines | |||
| 6327 | if (sym->type.t & VT_STATIC) | 6326 | if (sym->type.t & VT_STATIC) |
| 6328 | type.t = (type.t & ~VT_EXTERN) | VT_STATIC; | 6327 | type.t = (type.t & ~VT_EXTERN) | VT_STATIC; |
| 6329 | 6328 | ||
| 6330 | /* If the definition has no visibility use the | 6329 | /* If the definition has no visibility use the |
| 6331 | one from prototype. */ | 6330 | one from prototype. */ |
| 6332 | if (! (type.t & VT_VIS_MASK)) | 6331 | if (! (type.t & VT_VIS_MASK)) |
| 6333 | type.t |= sym->type.t & VT_VIS_MASK; | 6332 | type.t |= sym->type.t & VT_VIS_MASK; |
| 6334 | 6333 | ||
| 6335 | if (!is_compatible_types(&sym->type, &type)) { | 6334 | if (!is_compatible_types(&sym->type, &type)) { |
| 6336 | func_error1: | 6335 | func_error1: |
| @@ -398,22 +398,22 @@ static int pe_find_import(TCCState * s1, ElfW(Sym) *sym) · 397 unmodified lines | |||
| 398 | s = pe_export_name(s1, sym); | 398 | s = pe_export_name(s1, sym); |
| 399 | if (n) { | 399 | if (n) { |
| 400 | /* second try: */ | 400 | /* second try: */ |
| 401 | if (sym->st_other & ST_PE_STDCALL) { | 401 | if (sym->st_other & ST_PE_STDCALL) { |
| 402 | /* try w/0 stdcall deco (windows API convention) */ | 402 | /* try w/0 stdcall deco (windows API convention) */ |
| 403 | p = strrchr(s, '@'); | 403 | p = strrchr(s, '@'); |
| 404 | if (!p || s[0] != '_') | 404 | if (!p || s[0] != '_') |
| 405 | break; | ||
| 406 | strcpy(buffer, s+1)[p-s-1] = 0; | ||
| 407 | } else if (s[0] != '_') { /* try non-ansi function */ | ||
| 408 | buffer[0] = '_', strcpy(buffer + 1, s); | ||
| 409 | } else if (0 == memcmp(s, "__imp__", 7)) { /* mingw 2.0 */ | ||
| 410 | strcpy(buffer, s + 6); | ||
| 411 | } else if (0 == memcmp(s, "_imp___", 7)) { /* mingw 3.7 */ | ||
| 412 | strcpy(buffer, s + 6); | ||
| 413 | } else { | ||
| 405 | break; | 414 | break; |
| 406 | strcpy(buffer, s+1)[p-s-1] = 0; | 415 | } |
| 407 | } else if (s[0] != '_') { /* try non-ansi function */ | 416 | s = buffer; |
| 408 | buffer[0] = '_', strcpy(buffer + 1, s); | ||
| 409 | } else if (0 == memcmp(s, "__imp__", 7)) { /* mingw 2.0 */ | ||
| 410 | strcpy(buffer, s + 6); | ||
| 411 | } else if (0 == memcmp(s, "_imp___", 7)) { /* mingw 3.7 */ | ||
| 412 | strcpy(buffer, s + 6); | ||
| 413 | } else { | ||
| 414 | break; | ||
| 415 | } | ||
| 416 | s = buffer; | ||
| 417 | } | 417 | } |
| 418 | sym_index = find_elf_sym(s1->dynsymtab_section, s); | 418 | sym_index = find_elf_sym(s1->dynsymtab_section, s); |
| 419 | // printf("find (%d) %d %s\n", n, sym_index, s); | 419 | // printf("find (%d) %d %s\n", n, sym_index, s); |
| @@ -565,9 +565,9 @@ static int pe_write(struct pe_info *pe) · 145 unmodified lines | |||
| 565 | #endif | 565 | #endif |
| 566 | /* NT additional fields. */ | 566 | /* NT additional fields. */ |
| 567 | #if defined(TCC_TARGET_ARM) | 567 | #if defined(TCC_TARGET_ARM) |
| 568 | 0x00100000, /*DWORD ImageBase; */ | 568 | 0x00100000, /*DWORD ImageBase; */ |
| 569 | #else | 569 | #else |
| 570 | 0x00400000, /*DWORD ImageBase; */ | 570 | 0x00400000, /*DWORD ImageBase; */ |
| 571 | #endif | 571 | #endif |
| 572 | 0x00001000, /*DWORD SectionAlignment; */ | 572 | 0x00001000, /*DWORD SectionAlignment; */ |
| 573 | 0x00000200, /*DWORD FileAlignment; */ | 573 | 0x00000200, /*DWORD FileAlignment; */ |
| @@ -30,13 +30,13 @@ typedef int RegArgs; · 29 unmodified lines | |||
| 30 | /* a register can belong to several classes. The classes must be | 30 | /* a register can belong to several classes. The classes must be |
| 31 | sorted from more general to more precise (see gv2() code which does | 31 | sorted from more general to more precise (see gv2() code which does |
| 32 | assumptions on it). */ | 32 | assumptions on it). */ |
| 33 | #define RC_INT 0x0001 /* generic integer register */ | 33 | #define RC_INT 0x0001 /* generic integer register */ |
| 34 | #define RC_FLOAT 0x0002 /* generic float register */ | 34 | #define RC_FLOAT 0x0002 /* generic float register */ |
| 35 | #define RC_EAX 0x0004 | 35 | #define RC_EAX 0x0004 |
| 36 | #define RC_ST0 0x0008 | 36 | #define RC_ST0 0x0008 |
| 37 | #define RC_ECX 0x0010 | 37 | #define RC_ECX 0x0010 |
| 38 | #define RC_EDX 0x0020 | 38 | #define RC_EDX 0x0020 |
| 39 | #define RC_INT_BSIDE 0x00000040 /* generic integer register on b side */ | 39 | #define RC_INT_BSIDE 0x00000040 /* generic integer register on b side */ |
| 40 | #define RC_C67_A4 0x00000100 | 40 | #define RC_C67_A4 0x00000100 |
| 41 | #define RC_C67_A5 0x00000200 | 41 | #define RC_C67_A5 0x00000200 |
| 42 | #define RC_C67_B4 0x00000400 | 42 | #define RC_C67_B4 0x00000400 |
| @@ -204,7 +204,7 @@ void C67_g(int c) · 161 unmodified lines | |||
| 204 | #endif | 204 | #endif |
| 205 | ind1 = ind + 4; | 205 | ind1 = ind + 4; |
| 206 | if (ind1 > (int) cur_text_section->data_allocated) | 206 | if (ind1 > (int) cur_text_section->data_allocated) |
| 207 | section_realloc(cur_text_section, ind1); | 207 | section_realloc(cur_text_section, ind1); |
| 208 | cur_text_section->data[ind] = c & 0xff; | 208 | cur_text_section->data[ind] = c & 0xff; |
| 209 | cur_text_section->data[ind + 1] = (c >> 8) & 0xff; | 209 | cur_text_section->data[ind + 1] = (c >> 8) & 0xff; |
| 210 | cur_text_section->data[ind + 2] = (c >> 16) & 0xff; | 210 | cur_text_section->data[ind + 2] = (c >> 16) & 0xff; |
| @@ -218,26 +218,26 @@ void gsym_addr(int t, int a) · 7 unmodified lines | |||
| 218 | { | 218 | { |
| 219 | int n, *ptr; | 219 | int n, *ptr; |
| 220 | while (t) { | 220 | while (t) { |
| 221 | ptr = (int *) (cur_text_section->data + t); | 221 | ptr = (int *) (cur_text_section->data + t); |
| 222 | { | 222 | { |
| 223 | Sym *sym; | 223 | Sym *sym; |
| 224 | 224 | ||
| 225 | // extract 32 bit address from MVKH/MVKL | 225 | // extract 32 bit address from MVKH/MVKL |
| 226 | n = ((*ptr >> 7) & 0xffff); | 226 | n = ((*ptr >> 7) & 0xffff); |
| 227 | n |= ((*(ptr + 1) >> 7) & 0xffff) << 16; | 227 | n |= ((*(ptr + 1) >> 7) & 0xffff) << 16; |
| 228 | 228 | ||
| 229 | // define a label that will be relocated | 229 | // define a label that will be relocated |
| 230 | 230 | ||
| 231 | sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0); | 231 | sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0); |
| 232 | greloc(cur_text_section, sym, t, R_C60LO16); | 232 | greloc(cur_text_section, sym, t, R_C60LO16); |
| 233 | greloc(cur_text_section, sym, t + 4, R_C60HI16); | 233 | greloc(cur_text_section, sym, t + 4, R_C60HI16); |
| 234 | 234 | ||
| 235 | // clear out where the pointer was | 235 | // clear out where the pointer was |
| 236 | 236 | ||
| 237 | *ptr &= ~(0xffff << 7); | 237 | *ptr &= ~(0xffff << 7); |
| 238 | *(ptr + 1) &= ~(0xffff << 7); | 238 | *(ptr + 1) &= ~(0xffff << 7); |
| 239 | } | 239 | } |
| 240 | t = n; | 240 | t = n; |
| 241 | } | 241 | } |
| 242 | } | 242 | } |
| 243 | 243 | ||
| @@ -618,7 +618,7 @@ static void gcall_or_jmp(int is_jmp) · 617 unmodified lines | |||
| 618 | { | 618 | { |
| 619 | int r; | 619 | int r; |
| 620 | if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && | 620 | if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && |
| 621 | ((vtop->r & VT_SYM) || (vtop->c.ll-4) == (int)(vtop->c.ll-4))) { | 621 | ((vtop->r & VT_SYM) || (vtop->c.ll-4) == (int)(vtop->c.ll-4))) { |
| 622 | /* constant case */ | 622 | /* constant case */ |
| 623 | if (vtop->r & VT_SYM) { | 623 | if (vtop->r & VT_SYM) { |
| 624 | /* relocation case */ | 624 | /* relocation case */ |
| @@ -1806,7 +1806,7 @@ int gtst(int inv, int t) · 1181 unmodified lines | |||
| 1806 | if (v == VT_CMP) { | 1806 | if (v == VT_CMP) { |
| 1807 | /* fast case : can jump directly since flags are set */ | 1807 | /* fast case : can jump directly since flags are set */ |
| 1808 | if (vtop->c.i & 0x100) | 1808 | if (vtop->c.i & 0x100) |
| 1809 | { | 1809 | { |
| 1810 | /* This was a float compare. If the parity flag is set | 1810 | /* This was a float compare. If the parity flag is set |
| 1811 | the result was unordered. For anything except != this | 1811 | the result was unordered. For anything except != this |
| 1812 | means false and we don't jump (anding both conditions). | 1812 | means false and we don't jump (anding both conditions). |
| @@ -1816,13 +1816,12 @@ int gtst(int inv, int t) · 3 unmodified lines | |||
| 1816 | otherwise if unordered we don't want to jump. */ | 1816 | otherwise if unordered we don't want to jump. */ |
| 1817 | vtop->c.i &= ~0x100; | 1817 | vtop->c.i &= ~0x100; |
| 1818 | if (!inv == (vtop->c.i != TOK_NE)) | 1818 | if (!inv == (vtop->c.i != TOK_NE)) |
| 1819 | o(0x067a); /* jp +6 */ | 1819 | o(0x067a); /* jp +6 */ |
| 1820 | else | 1820 | else { |
| 1821 | { | ||
| 1822 | g(0x0f); | 1821 | g(0x0f); |
| 1823 | t = psym(0x8a, t); /* jp t */ | 1822 | t = psym(0x8a, t); /* jp t */ |
| 1824 | } | 1823 | } |
| 1825 | } | 1824 | } |
| 1826 | g(0x0f); | 1825 | g(0x0f); |
| 1827 | t = psym((vtop->c.i - 16) ^ inv, t); | 1826 | t = psym((vtop->c.i - 16) ^ inv, t); |
| 1828 | } else if (v == VT_JMP || v == VT_JMPI) { | 1827 | } else if (v == VT_JMP || v == VT_JMPI) { |