Changeset 331 for EcnlProtoTool/trunk/tcc-0.9.27/tccrun.c
- Timestamp:
- Jan 21, 2018, 12:10:09 AM (6 years ago)
- Location:
- EcnlProtoTool/trunk/tcc-0.9.27
- Files:
-
- 1 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
EcnlProtoTool/trunk/tcc-0.9.27/tccrun.c
r321 r331 24 24 #ifdef TCC_IS_NATIVE 25 25 26 #ifndef _WIN32 27 # include <sys/mman.h> 28 #endif 29 26 30 #ifdef CONFIG_TCC_BACKTRACE 31 # ifndef _WIN32 32 # include <signal.h> 33 # ifndef __OpenBSD__ 34 # include <sys/ucontext.h> 35 # endif 36 # else 37 # define ucontext_t CONTEXT 38 # endif 27 39 ST_DATA int rt_num_callers = 6; 28 40 ST_DATA const char **rt_bound_error_msg; 29 41 ST_DATA void *rt_prog_main; 30 #endif31 32 #ifdef _WIN3233 #define ucontext_t CONTEXT34 #endif35 36 static void set_pages_executable(void *ptr, unsigned long length);37 static void set_exception_handler(void);38 42 static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level); 39 43 static void rt_error(ucontext_t *uc, const char *fmt, ...); 40 static int tcc_relocate_ex(TCCState *s1, void *ptr); 44 static void set_exception_handler(void); 45 #endif 46 47 static void set_pages_executable(void *ptr, unsigned long length); 48 static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff); 41 49 42 50 #ifdef _WIN64 43 static void win64_add_function_table(TCCState *s1); 51 static void *win64_add_function_table(TCCState *s1); 52 static void win64_del_function_table(void *); 44 53 #endif 45 54 … … 50 59 LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr) 51 60 { 52 int ret; 61 int size; 62 addr_t ptr_diff = 0; 53 63 54 64 if (TCC_RELOCATE_AUTO != ptr) 55 return tcc_relocate_ex(s1, ptr );56 57 ret = tcc_relocate_ex(s1, NULL);58 if ( ret< 0)59 return ret;65 return tcc_relocate_ex(s1, ptr, 0); 66 67 size = tcc_relocate_ex(s1, NULL, 0); 68 if (size < 0) 69 return -1; 60 70 61 71 #ifdef HAVE_SELINUX 62 { /* Use mmap instead of malloc for Selinux. Ref: 63 http://www.gnu.org/s/libc/manual/html_node/File-Size.html */ 64 65 char tmpfname[] = "/tmp/.tccrunXXXXXX"; 66 int fd = mkstemp (tmpfname); 67 68 s1->mem_size = ret; 69 unlink (tmpfname); 70 ftruncate (fd, s1->mem_size); 71 72 s1->write_mem = mmap (NULL, ret, PROT_READ|PROT_WRITE, 73 MAP_SHARED, fd, 0); 74 if (s1->write_mem == MAP_FAILED) 75 tcc_error("/tmp not writeable"); 76 77 s1->runtime_mem = mmap (NULL, ret, PROT_READ|PROT_EXEC, 78 MAP_SHARED, fd, 0); 79 if (s1->runtime_mem == MAP_FAILED) 80 tcc_error("/tmp not executable"); 81 82 ret = tcc_relocate_ex(s1, s1->write_mem); 83 } 84 #else 85 s1->runtime_mem = tcc_malloc(ret); 86 ret = tcc_relocate_ex(s1, s1->runtime_mem); 87 #endif 88 return ret; 72 { 73 /* Using mmap instead of malloc */ 74 void *prx; 75 char tmpfname[] = "/tmp/.tccrunXXXXXX"; 76 int fd = mkstemp(tmpfname); 77 unlink(tmpfname); 78 ftruncate(fd, size); 79 80 ptr = mmap (NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 81 prx = mmap (NULL, size, PROT_READ|PROT_EXEC, MAP_SHARED, fd, 0); 82 if (ptr == MAP_FAILED || prx == MAP_FAILED) 83 tcc_error("tccrun: could not map memory"); 84 dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)size); 85 dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, prx); 86 ptr_diff = (char*)prx - (char*)ptr; 87 } 88 #else 89 ptr = tcc_malloc(size); 90 #endif 91 tcc_relocate_ex(s1, ptr, ptr_diff); /* no more errors expected */ 92 dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, ptr); 93 return 0; 94 } 95 96 ST_FUNC void tcc_run_free(TCCState *s1) 97 { 98 int i; 99 100 for (i = 0; i < s1->nb_runtime_mem; ++i) { 101 #ifdef HAVE_SELINUX 102 unsigned size = (unsigned)(addr_t)s1->runtime_mem[i++]; 103 munmap(s1->runtime_mem[i++], size); 104 munmap(s1->runtime_mem[i], size); 105 #else 106 #ifdef _WIN64 107 win64_del_function_table(*(void**)s1->runtime_mem[i]); 108 #endif 109 tcc_free(s1->runtime_mem[i]); 110 #endif 111 } 112 tcc_free(s1->runtime_mem); 89 113 } 90 114 … … 93 117 { 94 118 int (*prog_main)(int, char **); 95 int ret; 96 119 120 s1->runtime_main = "main"; 121 if ((s1->dflag & 16) && !find_elf_sym(s1->symtab, s1->runtime_main)) 122 return 0; 97 123 if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0) 98 124 return -1; 99 100 prog_main = tcc_get_symbol_err(s1, "main"); 125 prog_main = tcc_get_symbol_err(s1, s1->runtime_main); 101 126 102 127 #ifdef CONFIG_TCC_BACKTRACE … … 107 132 #endif 108 133 134 errno = 0; /* clean errno value */ 135 109 136 #ifdef CONFIG_TCC_BCHECK 110 137 if (s1->do_bounds_check) { 111 138 void (*bound_init)(void); 112 139 void (*bound_exit)(void); 140 void (*bound_new_region)(void *p, addr_t size); 141 int (*bound_delete_region)(void *p); 142 int i, ret; 143 113 144 /* set error function */ 114 145 rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg"); … … 116 147 bound_init = tcc_get_symbol_err(s1, "__bound_init"); 117 148 bound_exit = tcc_get_symbol_err(s1, "__bound_exit"); 149 bound_new_region = tcc_get_symbol_err(s1, "__bound_new_region"); 150 bound_delete_region = tcc_get_symbol_err(s1, "__bound_delete_region"); 151 118 152 bound_init(); 153 /* mark argv area as valid */ 154 bound_new_region(argv, argc*sizeof(argv[0])); 155 for (i=0; i<argc; ++i) 156 bound_new_region(argv[i], strlen(argv[i]) + 1); 157 119 158 ret = (*prog_main)(argc, argv); 159 160 /* unmark argv area */ 161 for (i=0; i<argc; ++i) 162 bound_delete_region(argv[i]); 163 bound_delete_region(argv); 120 164 bound_exit(); 121 } else 122 #endif 123 ret = (*prog_main)(argc, argv); 124 return ret; 125 } 165 return ret; 166 } 167 #endif 168 return (*prog_main)(argc, argv); 169 } 170 171 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 172 #define RUN_SECTION_ALIGNMENT 63 173 #else 174 #define RUN_SECTION_ALIGNMENT 15 175 #endif 126 176 127 177 /* relocate code. Return -1 on error, required size if ptr is NULL, 128 178 otherwise copy code into buffer passed by the caller */ 129 static int tcc_relocate_ex(TCCState *s1, void *ptr )179 static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) 130 180 { 131 181 Section *s; 132 unsigned long offset, length;182 unsigned offset, length, fill, i, k; 133 183 addr_t mem; 134 int i;135 184 136 185 if (NULL == ptr) { … … 140 189 #else 141 190 tcc_add_runtime(s1); 142 relocate_common_syms(); 143 tcc_add_linker_symbols(s1); 191 resolve_common_syms(s1); 144 192 build_got_entries(s1); 145 193 #endif … … 149 197 150 198 offset = 0, mem = (addr_t)ptr; 199 fill = -mem & RUN_SECTION_ALIGNMENT; 200 #ifdef _WIN64 201 offset += sizeof (void*); 202 #endif 203 for (k = 0; k < 2; ++k) { 204 for(i = 1; i < s1->nb_sections; i++) { 205 s = s1->sections[i]; 206 if (0 == (s->sh_flags & SHF_ALLOC)) 207 continue; 208 if (k != !(s->sh_flags & SHF_EXECINSTR)) 209 continue; 210 offset += fill; 211 if (!mem) 212 s->sh_addr = 0; 213 else if (s->sh_flags & SHF_EXECINSTR) 214 s->sh_addr = mem + offset + ptr_diff; 215 else 216 s->sh_addr = mem + offset; 217 #if 0 218 if (mem) 219 printf("%-16s +%02lx %p %04x\n", 220 s->name, fill, (void*)s->sh_addr, (unsigned)s->data_offset); 221 #endif 222 offset += s->data_offset; 223 fill = -(mem + offset) & 15; 224 } 225 #if RUN_SECTION_ALIGNMENT > 15 226 /* To avoid that x86 processors would reload cached instructions each time 227 when data is written in the near, we need to make sure that code and data 228 do not share the same 64 byte unit */ 229 fill = -(mem + offset) & RUN_SECTION_ALIGNMENT; 230 #endif 231 } 232 233 /* relocate symbols */ 234 relocate_syms(s1, s1->symtab, 1); 235 if (s1->nb_errors) 236 return -1; 237 238 if (0 == mem) 239 return offset + RUN_SECTION_ALIGNMENT; 240 241 #ifdef TCC_TARGET_PE 242 s1->pe_imagebase = mem; 243 #endif 244 245 /* relocate each section */ 246 for(i = 1; i < s1->nb_sections; i++) { 247 s = s1->sections[i]; 248 if (s->reloc) 249 relocate_section(s1, s); 250 } 251 relocate_plt(s1); 252 151 253 for(i = 1; i < s1->nb_sections; i++) { 152 254 s = s1->sections[i]; … … 154 256 continue; 155 257 length = s->data_offset; 156 s->sh_addr = mem ? (mem + offset + 15) & ~15 : 0;157 offset = (offset + length + 15) & ~15;158 }159 offset += 16;160 161 /* relocate symbols */162 relocate_syms(s1, 1);163 if (s1->nb_errors)164 return -1;165 166 #ifdef TCC_HAS_RUNTIME_PLTGOT167 s1->runtime_plt_and_got_offset = 0;168 s1->runtime_plt_and_got = (char *)(mem + offset);169 /* double the size of the buffer for got and plt entries170 XXX: calculate exact size for them? */171 offset *= 2;172 #endif173 174 if (0 == mem)175 return offset;176 177 /* relocate each section */178 for(i = 1; i < s1->nb_sections; i++) {179 s = s1->sections[i];180 if (s->reloc)181 relocate_section(s1, s);182 }183 184 for(i = 1; i < s1->nb_sections; i++) {185 s = s1->sections[i];186 if (0 == (s->sh_flags & SHF_ALLOC))187 continue;188 length = s->data_offset;189 // printf("%-12s %08x %04x\n", s->name, s->sh_addr, length);190 258 ptr = (void*)s->sh_addr; 259 if (s->sh_flags & SHF_EXECINSTR) 260 ptr = (char*)ptr - ptr_diff; 191 261 if (NULL == s->data || s->sh_type == SHT_NOBITS) 192 262 memset(ptr, 0, length); … … 195 265 /* mark executable sections as executable in memory */ 196 266 if (s->sh_flags & SHF_EXECINSTR) 197 set_pages_executable(ptr, length); 198 } 199 200 #ifdef TCC_HAS_RUNTIME_PLTGOT 201 set_pages_executable(s1->runtime_plt_and_got, 202 s1->runtime_plt_and_got_offset); 203 #endif 267 set_pages_executable((char*)ptr + ptr_diff, length); 268 } 204 269 205 270 #ifdef _WIN64 206 win64_add_function_table(s1); 207 #endif 271 *(void**)mem = win64_add_function_table(s1); 272 #endif 273 208 274 return 0; 209 275 } … … 218 284 VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect); 219 285 #else 220 #ifndef PAGESIZE 221 # define PAGESIZE 4096 222 #endif 286 void __clear_cache(void *beginning, void *end); 287 # ifndef HAVE_SELINUX 223 288 addr_t start, end; 289 # ifndef PAGESIZE 290 # define PAGESIZE 4096 291 # endif 224 292 start = (addr_t)ptr & ~(PAGESIZE - 1); 225 293 end = (addr_t)ptr + length; 226 294 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1); 227 mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC); 228 #endif 229 } 295 if (mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC)) 296 tcc_error("mprotect failed: did you mean to configure --with-selinux?"); 297 # endif 298 # if defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64 299 __clear_cache(ptr, (char *)ptr + length); 300 # endif 301 #endif 302 } 303 304 #ifdef _WIN64 305 static void *win64_add_function_table(TCCState *s1) 306 { 307 void *p = NULL; 308 if (s1->uw_pdata) { 309 p = (void*)s1->uw_pdata->sh_addr; 310 RtlAddFunctionTable( 311 (RUNTIME_FUNCTION*)p, 312 s1->uw_pdata->data_offset / sizeof (RUNTIME_FUNCTION), 313 s1->pe_imagebase 314 ); 315 s1->uw_pdata = NULL; 316 } 317 return p; 318 } 319 320 static void win64_del_function_table(void *p) 321 { 322 if (p) { 323 RtlDeleteFunctionTable((RUNTIME_FUNCTION*)p); 324 } 325 } 326 #endif 230 327 231 328 /* ------------------------------------------------------------- */ … … 254 351 stab_len = stab_section->data_offset; 255 352 stab_sym = (Stab_Sym *)stab_section->data; 256 stab_str = stabstr_section->data;353 stab_str = (char *) stabstr_section->data; 257 354 } 258 355 … … 347 444 wanted_pc < sym->st_value + sym->st_size) { 348 445 pstrcpy(last_func_name, sizeof(last_func_name), 349 strtab_section->data + sym->st_name);446 (char *) symtab_section->link->data + sym->st_name); 350 447 func_addr = sym->st_value; 351 448 goto found; … … 453 550 runtime errors */ 454 551 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND; 455 /*sigact.sa_sigaction = sig_error;*/ 456 sigact.sa_handler = sig_error; 552 sigact.sa_sigaction = sig_error; 457 553 sigemptyset(&sigact.sa_mask); 458 554 sigaction(SIGFPE, &sigact, NULL); … … 481 577 #if defined(__APPLE__) 482 578 *paddr = uc->uc_mcontext->__ss.__eip; 483 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 579 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 484 580 *paddr = uc->uc_mcontext.mc_eip; 485 581 #elif defined(__dietlibc__) 486 582 *paddr = uc->uc_mcontext.eip; 583 #elif defined(__NetBSD__) 584 *paddr = uc->uc_mcontext.__gregs[_REG_EIP]; 585 #elif defined(__OpenBSD__) 586 *paddr = uc->sc_eip; 487 587 #else 488 588 *paddr = uc->uc_mcontext.gregs[REG_EIP]; … … 492 592 #if defined(__APPLE__) 493 593 fp = uc->uc_mcontext->__ss.__ebp; 494 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 594 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 495 595 fp = uc->uc_mcontext.mc_ebp; 496 596 #elif defined(__dietlibc__) 497 597 fp = uc->uc_mcontext.ebp; 598 #elif defined(__NetBSD__) 599 fp = uc->uc_mcontext.__gregs[_REG_EBP]; 600 #elif defined(__OpenBSD__) 601 *paddr = uc->sc_ebp; 498 602 #else 499 603 fp = uc->uc_mcontext.gregs[REG_EBP]; … … 523 627 #if defined(__APPLE__) 524 628 *paddr = uc->uc_mcontext->__ss.__rip; 525 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 629 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 526 630 *paddr = uc->uc_mcontext.mc_rip; 631 #elif defined(__NetBSD__) 632 *paddr = uc->uc_mcontext.__gregs[_REG_RIP]; 527 633 #else 528 634 *paddr = uc->uc_mcontext.gregs[REG_RIP]; … … 532 638 #if defined(__APPLE__) 533 639 fp = uc->uc_mcontext->__ss.__rbp; 534 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 640 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 535 641 fp = uc->uc_mcontext.mc_rbp; 642 #elif defined(__NetBSD__) 643 fp = uc->uc_mcontext.__gregs[_REG_RBP]; 536 644 #else 537 645 fp = uc->uc_mcontext.gregs[REG_RBP]; … … 587 695 /* XXX: check address validity with program info */ 588 696 *paddr = ((addr_t *)fp)[-1]; 697 return 0; 698 } 699 } 700 701 /* ------------------------------------------------------------- */ 702 #elif defined(__aarch64__) 703 704 static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level) 705 { 706 if (level < 0) 707 return -1; 708 else if (level == 0) { 709 *paddr = uc->uc_mcontext.pc; 710 return 0; 711 } 712 else { 713 addr_t *fp = (addr_t *)uc->uc_mcontext.regs[29]; 714 int i; 715 for (i = 1; i < level; i++) 716 fp = (addr_t *)fp[0]; 717 *paddr = fp[1]; 589 718 return 0; 590 719 } … … 635 764 } 636 765 637 #ifdef _WIN64638 static void win64_add_function_table(TCCState *s1)639 {640 RtlAddFunctionTable(641 (RUNTIME_FUNCTION*)s1->uw_pdata->sh_addr,642 s1->uw_pdata->data_offset / sizeof (RUNTIME_FUNCTION),643 text_section->sh_addr644 );645 }646 #endif647 648 766 /* return the PC at frame level 'level'. Return non zero if not found */ 649 767 static int rt_get_caller_pc(addr_t *paddr, CONTEXT *uc, int level) … … 696 814 } TCCSyms; 697 815 816 #if !defined(CONFIG_TCCBOOT) 817 extern int __environ; 818 extern int __expand_heap; 819 extern int __get_handler_set; 820 extern int __get_locale; 821 extern int __gmt; 822 extern int __h_errno_location; 823 extern int __hwcap; 824 extern int __init_tls; 825 extern int __libc; 826 extern int __libc_sigaction; 827 extern int __libc_start_main; 828 extern int __malloc0; 829 extern int __ofl_lock; 830 extern int __ofl_unlock; 831 extern int __progname; 832 extern int __progname_full; 833 extern int __secs_to_zone; 834 extern int __sigaction; 835 extern int __sysinfo; 836 extern int __tm_to_tzname; 837 //extern int atexit; 838 //extern int environ; 839 //extern int free; 840 extern int gethostbyname2; 841 //extern int getopt; 842 extern int getpwnam; 843 //extern int gmtime; 844 //extern int localtime; 845 //extern int malloc; 846 extern int mbrtowc; 847 //extern int optarg; 848 extern int optind; 849 //extern int rand; 850 //extern int realloc; 851 //extern int setenv; 852 extern int setlocale; 853 //extern int sigaction; 854 //extern int srand; 855 //extern int stderr; 856 //extern int stdin; 857 //extern int stdout; 858 //extern int strtok; 859 extern int syslog; 860 extern int vsyslog; 861 #endif 698 862 699 863 /* add the symbol you want here if no dynamic linking is done */ … … 701 865 #if !defined(CONFIG_TCCBOOT) 702 866 #define TCCSYM(a) { #a, &a, }, 703 TCCSYM(printf) 704 TCCSYM(fprintf) 705 TCCSYM(fopen) 706 TCCSYM(fclose) 867 TCCSYM(__environ) 868 TCCSYM(__expand_heap) 869 TCCSYM(__get_handler_set) 870 TCCSYM(__get_locale) 871 TCCSYM(__gmt) 872 TCCSYM(__h_errno_location) 873 TCCSYM(__hwcap) 874 TCCSYM(__init_tls) 875 TCCSYM(__libc) 876 TCCSYM(__libc_sigaction) 877 TCCSYM(__libc_start_main) 878 TCCSYM(__malloc0) 879 TCCSYM(__ofl_lock) 880 TCCSYM(__ofl_unlock) 881 TCCSYM(__progname) 882 TCCSYM(__progname_full) 883 TCCSYM(__secs_to_zone) 884 TCCSYM(__sigaction) 885 TCCSYM(__sysinfo) 886 TCCSYM(__tm_to_tzname) 887 TCCSYM(atexit) 888 TCCSYM(environ) 889 TCCSYM(free) 890 TCCSYM(gethostbyname2) 891 TCCSYM(getopt) 892 TCCSYM(getpwnam) 893 TCCSYM(gmtime) 894 TCCSYM(localtime) 895 TCCSYM(malloc) 896 TCCSYM(mbrtowc) 897 TCCSYM(optarg) 898 TCCSYM(optind) 899 TCCSYM(rand) 900 TCCSYM(realloc) 901 TCCSYM(setenv) 902 TCCSYM(setlocale) 903 TCCSYM(sigaction) 904 TCCSYM(srand) 905 TCCSYM(stderr) 906 TCCSYM(stdin) 907 TCCSYM(stdout) 908 TCCSYM(strtok) 909 TCCSYM(syslog) 910 TCCSYM(vsyslog) 707 911 #undef TCCSYM 708 912 #endif … … 710 914 }; 711 915 712 ST_FUNC void * resolve_sym(TCCState *s1, const char *symbol)916 ST_FUNC void *dlsym(void *handle, const char *symbol) 713 917 { 714 918 TCCSyms *p; … … 722 926 } 723 927 724 #elif !defined(_WIN32)725 726 ST_FUNC void *resolve_sym(TCCState *s1, const char *sym)727 {728 return dlsym(RTLD_DEFAULT, sym);729 }730 731 928 #endif /* CONFIG_TCC_STATIC */ 732 929 #endif /* TCC_IS_NATIVE */
Note:
See TracChangeset
for help on using the changeset viewer.