| @@ -542,6 +542,9 @@ struct TCCState { · 541 unmodified lines |
| 542 | | 542 | |
| 543 | /* output file for preprocessing */ | 543 | /* output file for preprocessing */ |
| 544 | FILE *outfile; | 544 | FILE *outfile; |
| | 545 | |
| | 546 | /* for tcc_relocate */ |
| | 547 | int runtime_added; |
| 545 | }; | 548 | }; |
| 546 | | 549 | |
| 547 | /* The current value can be: */ | 550 | /* The current value can be: */ |
| @@ -10277,88 +10280,61 @@ static void sig_error(int signum, siginfo_t *siginf, void *puc) · 9729 unmodified lines |
| 10277 | } | 10280 | } |
| 10278 | #endif | 10281 | #endif |
| 10279 | | 10282 | |
| 10280 | /* do all relocations (needed before using tcc_get_symbol()) */ | 10283 | /* copy code into memory passed in by the caller and do all relocations |
| 10281 | int tcc_relocate(TCCState *s1) | 10284 | (needed before using tcc_get_symbol()). |
| | 10285 | returns -1 on error and required size if ptr is NULL */ |
| | 10286 | int tcc_relocate(TCCState *s1, void *ptr) |
| 10282 | { | 10287 | { |
| 10283 | Section *s; | 10288 | Section *s; |
| | 10289 | unsigned long offset, length, mem; |
| 10284 | int i; | 10290 | int i; |
| 10285 | | 10291 | |
| 10286 | s1->nb_errors = 0; | 10292 | s1->nb_errors = 0; |
| 10287 | | 10293 | |
| | 10294 | if (0 == s1->runtime_added) { |
| 10288 | #ifdef TCC_TARGET_PE | 10295 | #ifdef TCC_TARGET_PE |
| 10289 | pe_add_runtime(s1); | 10296 | pe_add_runtime(s1); |
| | 10297 | relocate_common_syms(); |
| | 10298 | tcc_add_linker_symbols(s1); |
| 10290 | #else | 10299 | #else |
| 10291 | tcc_add_runtime(s1); | 10300 | tcc_add_runtime(s1); |
| 10292 | #endif | 10301 | relocate_common_syms(); |
| 10293 | | 10302 | tcc_add_linker_symbols(s1); |
| 10294 | relocate_common_syms(); | 10303 | build_got_entries(s1); |
| 10295 | | | |
| 10296 | tcc_add_linker_symbols(s1); | | |
| 10297 | #ifndef TCC_TARGET_PE | | |
| 10298 | build_got_entries(s1); | | |
| 10299 | #endif | 10304 | #endif |
| 10300 | | 10305 | s1->runtime_added = 1; |
| 10301 | #ifdef TCC_TARGET_X86_64 | | |
| 10302 | { | | |
| 10303 | /* If the distance of two sections are longer than 32bit, our | | |
| 10304 | program will crash. Let's combine all sections which are | | |
| 10305 | necessary to run the program into a single buffer in the | | |
| 10306 | text section */ | | |
| 10307 | unsigned char *p; | | |
| 10308 | int size; | | |
| 10309 | /* calculate the size of buffers we need */ | | |
| 10310 | size = 0; | | |
| 10311 | for(i = 1; i < s1->nb_sections; i++) { | | |
| 10312 | s = s1->sections[i]; | | |
| 10313 | if (s->sh_flags & SHF_ALLOC) { | | |
| 10314 | size += s->data_offset; | | |
| 10315 | } | | |
| 10316 | } | | |
| 10317 | /* double the size of the buffer for got and plt entries | | |
| 10318 | XXX: calculate exact size for them? */ | | |
| 10319 | section_realloc(text_section, size * 2); | | |
| 10320 | p = text_section->data + text_section->data_offset; | | |
| 10321 | /* we will put got and plt after this offset */ | | |
| 10322 | text_section->data_offset = size; | | |
| 10323 | | | |
| 10324 | for(i = 1; i < s1->nb_sections; i++) { | | |
| 10325 | s = s1->sections[i]; | | |
| 10326 | if (s->sh_flags & SHF_ALLOC) { | | |
| 10327 | if (s != text_section && s->data_offset) { | | |
| 10328 | if (s->sh_type == SHT_NOBITS) { | | |
| 10329 | /* for bss section */ | | |
| 10330 | memset(p, 0, s->data_offset); | | |
| 10331 | } else { | | |
| 10332 | memcpy(p, s->data, s->data_offset); | | |
| 10333 | tcc_free(s->data); | | |
| 10334 | } | | |
| 10335 | s->data = p; | | |
| 10336 | /* we won't free s->data for this section */ | | |
| 10337 | s->data_allocated = 0; | | |
| 10338 | p += s->data_offset; | | |
| 10339 | } | | |
| 10340 | s->sh_addr = (unsigned long)s->data; | | |
| 10341 | } | | |
| 10342 | } | | |
| 10343 | } | 10306 | } |
| 10344 | #else | 10307 | |
| 10345 | /* compute relocation address : section are relocated in place. We | 10308 | offset = 0; |
| 10346 | also alloc the bss space */ | 10309 | mem = (unsigned long)ptr; |
| 10347 | for(i = 1; i < s1->nb_sections; i++) { | 10310 | for(i = 1; i < s1->nb_sections; i++) { |
| 10348 | s = s1->sections[i]; | 10311 | s = s1->sections[i]; |
| 10349 | if (s->sh_flags & SHF_ALLOC) { | 10312 | if (0 == (s->sh_flags & SHF_ALLOC)) |
| | 10313 | continue; |
| | 10314 | length = s->data_offset; |
| | 10315 | if (0 == mem) { |
| | 10316 | s->sh_addr = 0; |
| | 10317 | } else if (1 == mem) { |
| | 10318 | /* section are relocated in place. |
| | 10319 | We also alloc the bss space */ |
| 10350 | if (s->sh_type == SHT_NOBITS) | 10320 | if (s->sh_type == SHT_NOBITS) |
| 10351 | s->data = tcc_mallocz(s->data_offset); | 10321 | s->data = tcc_malloc(length); |
| 10352 | s->sh_addr = (unsigned long)s->data; | 10322 | s->sh_addr = (unsigned long)s->data; |
| | 10323 | } else { |
| | 10324 | /* sections are relocated to new memory */ |
| | 10325 | s->sh_addr = (mem + offset + 15) & ~15; |
| 10353 | } | 10326 | } |
| | 10327 | offset = (offset + length + 15) & ~15; |
| 10354 | } | 10328 | } |
| 10355 | #endif | | |
| 10356 | | 10329 | |
| | 10330 | /* relocate symbols */ |
| 10357 | relocate_syms(s1, 1); | 10331 | relocate_syms(s1, 1); |
| 10358 | | 10332 | if (s1->nb_errors) |
| 10359 | if (s1->nb_errors != 0) | | |
| 10360 | return -1; | 10333 | return -1; |
| 10361 | | 10334 | |
| | 10335 | if (0 == mem) |
| | 10336 | return offset + 15; |
| | 10337 | |
| 10362 | /* relocate each section */ | 10338 | /* relocate each section */ |
| 10363 | for(i = 1; i < s1->nb_sections; i++) { | 10339 | for(i = 1; i < s1->nb_sections; i++) { |
| 10364 | s = s1->sections[i]; | 10340 | s = s1->sections[i]; |
| @@ -10366,12 +10342,20 @@ int tcc_relocate(TCCState *s1) · 1 unmodified line |
| 10366 | relocate_section(s1, s); | 10342 | relocate_section(s1, s); |
| 10367 | } | 10343 | } |
| 10368 | | 10344 | |
| 10369 | /* mark executable sections as executable in memory */ | | |
| 10370 | for(i = 1; i < s1->nb_sections; i++) { | 10345 | for(i = 1; i < s1->nb_sections; i++) { |
| 10371 | s = s1->sections[i]; | 10346 | s = s1->sections[i]; |
| 10372 | if ((s->sh_flags & (SHF_ALLOC | SHF_EXECINSTR)) == | 10347 | if (0 == (s->sh_flags & SHF_ALLOC)) |
| 10373 | (SHF_ALLOC | SHF_EXECINSTR)) | 10348 | continue; |
| 10374 | set_pages_executable(s->data, s->data_offset); | 10349 | length = s->data_offset; |
| | 10350 | // printf("%-12s %08x %04x\n", s->name, s->sh_addr, length); |
| | 10351 | ptr = (void*)s->sh_addr; |
| | 10352 | if (NULL == s->data || s->sh_type == SHT_NOBITS) |
| | 10353 | memset(ptr, 0, length); |
| | 10354 | else if (ptr != s->data) |
| | 10355 | memcpy(ptr, s->data, length); |
| | 10356 | /* mark executable sections as executable in memory */ |
| | 10357 | if (s->sh_flags & SHF_EXECINSTR) |
| | 10358 | set_pages_executable(ptr, length); |
| 10375 | } | 10359 | } |
| 10376 | return 0; | 10360 | return 0; |
| 10377 | } | 10361 | } |
| @@ -10380,9 +10364,14 @@ int tcc_relocate(TCCState *s1) · 2 unmodified lines |
| 10380 | int tcc_run(TCCState *s1, int argc, char **argv) | 10364 | int tcc_run(TCCState *s1, int argc, char **argv) |
| 10381 | { | 10365 | { |
| 10382 | int (*prog_main)(int, char **); | 10366 | int (*prog_main)(int, char **); |
| | 10367 | void *ptr; |
| | 10368 | int ret; |
| 10383 | | 10369 | |
| 10384 | if (tcc_relocate(s1) < 0) | 10370 | ret = tcc_relocate(s1, NULL); |
| | 10371 | if (ret < 0) |
| 10385 | return -1; | 10372 | return -1; |
| | 10373 | ptr = tcc_malloc(ret); |
| | 10374 | tcc_relocate(s1, ptr); |
| 10386 | | 10375 | |
| 10387 | prog_main = tcc_get_symbol_err(s1, "main"); | 10376 | prog_main = tcc_get_symbol_err(s1, "main"); |
| 10388 | | 10377 | |
| @@ -10417,7 +10406,9 @@ int tcc_run(TCCState *s1, int argc, char **argv) · 28 unmodified lines |
| 10417 | bound_init(); | 10406 | bound_init(); |
| 10418 | } | 10407 | } |
| 10419 | #endif | 10408 | #endif |
| 10420 | return (*prog_main)(argc, argv); | 10409 | ret = (*prog_main)(argc, argv); |
| | 10410 | tcc_free(ptr); |
| | 10411 | return ret; |
| 10421 | } | 10412 | } |
| 10422 | | 10413 | |
| 10423 | void tcc_memstats(void) | 10414 | void tcc_memstats(void) |