1
0
Fork 0

tcc_error_noabort(): always use this unless compiling

This avoids 'exit(1)' with errors outside of compilation
(nasty in particular with libtcc usage)

As a sideeffect multiple errors can be seen for linker
errors (such as undefined symbols, relocation errors, ...)
This commit is contained in:
grischka 2023-04-15 09:54:23 +02:00
parent 19ef024aa9
commit 7916cf71cc
17 changed files with 190 additions and 181 deletions

View File

@ -214,7 +214,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
h = x & 2; h = x & 2;
th_ko = (x & 3) && (!blx_avail || !is_call); th_ko = (x & 3) && (!blx_avail || !is_call);
if (th_ko || x >= 0x2000000 || x < -0x2000000) if (th_ko || x >= 0x2000000 || x < -0x2000000)
tcc_error("can't relocate value at %x,%d",addr, type); tcc_error_noabort("can't relocate value at %x,%d",addr, type);
x >>= 2; x >>= 2;
x &= 0xffffff; x &= 0xffffff;
/* Only reached if blx is avail and it is a call */ /* Only reached if blx is avail and it is a call */
@ -303,7 +303,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
- instruction must be a call (bl) or a jump to PLT */ - instruction must be a call (bl) or a jump to PLT */
if (!to_thumb || x >= 0x1000000 || x < -0x1000000) if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
if (to_thumb || (val & 2) || (!is_call && !to_plt)) if (to_thumb || (val & 2) || (!is_call && !to_plt))
tcc_error("can't relocate value at %x,%d",addr, type); tcc_error_noabort("can't relocate value at %x,%d",addr, type);
/* Compute and store final offset */ /* Compute and store final offset */
s = (x >> 24) & 1; s = (x >> 24) & 1;
@ -374,7 +374,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
x = (x * 2) / 2; x = (x * 2) / 2;
x += val - addr; x += val - addr;
if((x^(x>>1))&0x40000000) if((x^(x>>1))&0x40000000)
tcc_error("can't relocate value at %x,%d",addr, type); tcc_error_noabort("can't relocate value at %x,%d",addr, type);
(*(int *)ptr) |= x & 0x7fffffff; (*(int *)ptr) |= x & 0x7fffffff;
} }
return; return;

View File

@ -126,7 +126,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
uint64_t got = s1->got->sh_addr + 16; uint64_t got = s1->got->sh_addr + 16;
uint64_t off = (got >> 12) - (plt >> 12); uint64_t off = (got >> 12) - (plt >> 12);
if ((off + ((uint32_t)1 << 20)) >> 21) if ((off + ((uint32_t)1 << 20)) >> 21)
tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt); tcc_error_noabort("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt);
write32le(p, 0xa9bf7bf0); // stp x16,x30,[sp,#-16]! write32le(p, 0xa9bf7bf0); // stp x16,x30,[sp,#-16]!
write32le(p + 4, (0x90000010 | // adrp x16,... write32le(p + 4, (0x90000010 | // adrp x16,...
(off & 0x1ffffc) << 3 | (off & 3) << 29)); (off & 0x1ffffc) << 3 | (off & 3) << 29));
@ -145,7 +145,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
uint64_t addr = got + read64le(p); uint64_t addr = got + read64le(p);
uint64_t off = (addr >> 12) - (pc >> 12); uint64_t off = (addr >> 12) - (pc >> 12);
if ((off + ((uint32_t)1 << 20)) >> 21) if ((off + ((uint32_t)1 << 20)) >> 21)
tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", (long)off, (long)addr, (long)pc); tcc_error_noabort("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", (long)off, (long)addr, (long)pc);
write32le(p, (0x90000010 | // adrp x16,... write32le(p, (0x90000010 | // adrp x16,...
(off & 0x1ffffc) << 3 | (off & 3) << 29)); (off & 0x1ffffc) << 3 | (off & 3) << 29));
write32le(p + 4, (0xf9400211 | // ldr x17,[x16,#...] write32le(p + 4, (0xf9400211 | // ldr x17,[x16,#...]
@ -239,7 +239,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
case R_AARCH64_ADR_PREL_PG_HI21: { case R_AARCH64_ADR_PREL_PG_HI21: {
uint64_t off = (val >> 12) - (addr >> 12); uint64_t off = (val >> 12) - (addr >> 12);
if ((off + ((uint64_t)1 << 20)) >> 21) if ((off + ((uint64_t)1 << 20)) >> 21)
tcc_error("R_AARCH64_ADR_PREL_PG_HI21 relocation failed"); tcc_error_noabort("R_AARCH64_ADR_PREL_PG_HI21 relocation failed");
write32le(ptr, ((read32le(ptr) & 0x9f00001f) | write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
(off & 0x1ffffc) << 3 | (off & 3) << 29)); (off & 0x1ffffc) << 3 | (off & 3) << 29));
return; return;
@ -272,7 +272,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
(char *) symtab_section->link->data + sym->st_name); (char *) symtab_section->link->data + sym->st_name);
#endif #endif
if (((val - addr) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc) if (((val - addr) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc)
tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed" tcc_error_noabort("R_AARCH64_(JUMP|CALL)26 relocation failed"
" (val=%lx, addr=%lx)", (long)val, (long)addr); " (val=%lx, addr=%lx)", (long)val, (long)addr);
write32le(ptr, (0x14000000 | write32le(ptr, (0x14000000 |
(uint32_t)(type == R_AARCH64_CALL26) << 31 | (uint32_t)(type == R_AARCH64_CALL26) << 31 |
@ -283,7 +283,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
(((s1->got->sh_addr + (((s1->got->sh_addr +
get_sym_attr(s1, sym_index, 0)->got_offset) >> 12) - (addr >> 12)); get_sym_attr(s1, sym_index, 0)->got_offset) >> 12) - (addr >> 12));
if ((off + ((uint64_t)1 << 20)) >> 21) if ((off + ((uint64_t)1 << 20)) >> 21)
tcc_error("R_AARCH64_ADR_GOT_PAGE relocation failed"); tcc_error_noabort("R_AARCH64_ADR_GOT_PAGE relocation failed");
write32le(ptr, ((read32le(ptr) & 0x9f00001f) | write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
(off & 0x1ffffc) << 3 | (off & 3) << 29)); (off & 0x1ffffc) << 3 | (off & 3) << 29));
return; return;

View File

@ -67,7 +67,7 @@ int gotplt_entry_type (int reloc_type)
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr) ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
{ {
tcc_error("C67 got not implemented"); tcc_error_noabort("C67 got not implemented");
return 0; return 0;
} }

View File

@ -227,7 +227,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
case R_386_16: case R_386_16:
if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) { if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
output_file: output_file:
tcc_error("can only produce 16-bit binary files"); tcc_error_noabort("can only produce 16-bit binary files");
} }
write16le(ptr, read16le(ptr) + val); write16le(ptr, read16le(ptr) + val);
return; return;
@ -274,7 +274,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
add32le(ptr + 5, -x); add32le(ptr + 5, -x);
} }
else else
tcc_error("unexpected R_386_TLS_GD pattern"); tcc_error_noabort("unexpected R_386_TLS_GD pattern");
} }
return; return;
case R_386_TLS_LDM: case R_386_TLS_LDM:
@ -297,7 +297,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
rel[1].r_info = ELFW(R_INFO)(0, R_386_NONE); rel[1].r_info = ELFW(R_INFO)(0, R_386_NONE);
} }
else else
tcc_error("unexpected R_386_TLS_LDM pattern"); tcc_error_noabort("unexpected R_386_TLS_LDM pattern");
} }
return; return;
case R_386_TLS_LDO_32: case R_386_TLS_LDO_32:

103
libtcc.c
View File

@ -250,6 +250,12 @@ ST_FUNC char *tcc_load_text(int fd)
#undef malloc #undef malloc
#undef realloc #undef realloc
void mem_error(const char *msg)
{
fprintf(stderr, "%s\n", msg);
exit (1);
}
#ifndef MEM_DEBUG #ifndef MEM_DEBUG
PUB_FUNC void tcc_free(void *ptr) PUB_FUNC void tcc_free(void *ptr)
@ -262,7 +268,7 @@ PUB_FUNC void *tcc_malloc(unsigned long size)
void *ptr; void *ptr;
ptr = malloc(size); ptr = malloc(size);
if (!ptr && size) if (!ptr && size)
_tcc_error("memory full (malloc)"); mem_error("memory full (malloc)");
return ptr; return ptr;
} }
@ -280,7 +286,7 @@ PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size)
void *ptr1; void *ptr1;
ptr1 = realloc(ptr, size); ptr1 = realloc(ptr, size);
if (!ptr1 && size) if (!ptr1 && size)
_tcc_error("memory full (realloc)"); mem_error("memory full (realloc)");
return ptr1; return ptr1;
} }
@ -345,7 +351,7 @@ PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line)
header = malloc(sizeof(mem_debug_header_t) + size); header = malloc(sizeof(mem_debug_header_t) + size);
if (!header) if (!header)
_tcc_error("memory full (malloc)"); mem_error("memory full (malloc)");
header->magic1 = MEM_DEBUG_MAGIC1; header->magic1 = MEM_DEBUG_MAGIC1;
header->magic2 = MEM_DEBUG_MAGIC2; header->magic2 = MEM_DEBUG_MAGIC2;
@ -405,7 +411,7 @@ PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file
mem_debug_chain_update = (header == mem_debug_chain); mem_debug_chain_update = (header == mem_debug_chain);
header = realloc(header, sizeof(mem_debug_header_t) + size); header = realloc(header, sizeof(mem_debug_header_t) + size);
if (!header) if (!header)
_tcc_error("memory full (realloc)"); mem_error("memory full (realloc)");
header->size = size; header->size = size;
write32le(MEM_DEBUG_CHECK3(header), MEM_DEBUG_MAGIC3); write32le(MEM_DEBUG_CHECK3(header), MEM_DEBUG_MAGIC3);
if (header->next) if (header->next)
@ -537,12 +543,6 @@ static void error1(int mode, const char *fmt, va_list ap)
TCCState *s1 = tcc_state; TCCState *s1 = tcc_state;
CString cs; CString cs;
cstr_new(&cs);
if (s1 == NULL)
/* can happen only if called from tcc_malloc(): 'out of memory' */
goto no_file;
tcc_exit_state(s1); tcc_exit_state(s1);
if (mode == ERROR_WARN) { if (mode == ERROR_WARN) {
@ -563,6 +563,7 @@ static void error1(int mode, const char *fmt, va_list ap)
return; return;
} }
cstr_new(&cs);
f = NULL; f = NULL;
if (s1->error_set_jmp_enabled) { /* we're called while parsing a file */ if (s1->error_set_jmp_enabled) { /* we're called while parsing a file */
/* use upper file if inline ":asm:" or token ":paste:" */ /* use upper file if inline ":asm:" or token ":paste:" */
@ -578,8 +579,6 @@ static void error1(int mode, const char *fmt, va_list ap)
} else if (s1->current_filename) { } else if (s1->current_filename) {
cstr_printf(&cs, "%s: ", s1->current_filename); cstr_printf(&cs, "%s: ", s1->current_filename);
} }
no_file:
if (0 == cs.size) if (0 == cs.size)
cstr_printf(&cs, "tcc: "); cstr_printf(&cs, "tcc: ");
cstr_printf(&cs, mode == ERROR_WARN ? "warning: " : "error: "); cstr_printf(&cs, mode == ERROR_WARN ? "warning: " : "error: ");
@ -595,15 +594,10 @@ no_file:
s1->error_func(s1->error_opaque, (char*)cs.data); s1->error_func(s1->error_opaque, (char*)cs.data);
} }
cstr_free(&cs); cstr_free(&cs);
if (s1) { if (mode != ERROR_WARN)
if (mode != ERROR_WARN) s1->nb_errors++;
s1->nb_errors++; if (mode == ERROR_ERROR && s1->error_set_jmp_enabled)
if (mode != ERROR_ERROR) longjmp(s1->error_jmp_buf, 1);
return;
if (s1->error_set_jmp_enabled)
longjmp(s1->error_jmp_buf, 1);
}
exit(1);
} }
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc error_func) LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc error_func)
@ -623,20 +617,24 @@ LIBTCCAPI void *tcc_get_error_opaque(TCCState *s)
} }
/* error without aborting current compilation */ /* error without aborting current compilation */
PUB_FUNC void _tcc_error_noabort(const char *fmt, ...) PUB_FUNC int _tcc_error_noabort(const char *fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
error1(ERROR_NOABORT, fmt, ap); error1(ERROR_NOABORT, fmt, ap);
va_end(ap); va_end(ap);
return -1;
} }
#undef _tcc_error
PUB_FUNC void _tcc_error(const char *fmt, ...) PUB_FUNC void _tcc_error(const char *fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
for (;;) error1(ERROR_ERROR, fmt, ap); error1(ERROR_ERROR, fmt, ap);
exit(1);
} }
#define _tcc_error use_tcc_error_noabort
PUB_FUNC void _tcc_warning(const char *fmt, ...) PUB_FUNC void _tcc_warning(const char *fmt, ...)
{ {
@ -646,6 +644,7 @@ PUB_FUNC void _tcc_warning(const char *fmt, ...)
va_end(ap); va_end(ap);
} }
/********************************************************/ /********************************************************/
/* I/O layer */ /* I/O layer */
@ -855,6 +854,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
dynarray_reset(&s1->argv, &s1->argc); dynarray_reset(&s1->argv, &s1->argc);
cstr_free(&s1->cmdline_defs); cstr_free(&s1->cmdline_defs);
cstr_free(&s1->cmdline_incl); cstr_free(&s1->cmdline_incl);
cstr_free(&s1->linker_arg);
#ifdef TCC_IS_NATIVE #ifdef TCC_IS_NATIVE
/* free runtime memory */ /* free runtime memory */
tcc_run_free(s1); tcc_run_free(s1);
@ -1218,7 +1218,7 @@ ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename)
{ {
if (-1 == tcc_add_library_internal(s1, "%s/%s", if (-1 == tcc_add_library_internal(s1, "%s/%s",
filename, 0, s1->crt_paths, s1->nb_crt_paths)) filename, 0, s1->crt_paths, s1->nb_crt_paths))
tcc_error_noabort("file '%s' not found", filename); return tcc_error_noabort("file '%s' not found", filename);
return 0; return 0;
} }
#endif #endif
@ -1505,7 +1505,7 @@ static int tcc_set_linker(TCCState *s, const char *option)
return 0; return 0;
} else { } else {
err: err:
tcc_error("unsupported linker option '%s'", option); return tcc_error_noabort("unsupported linker option '%s'", option);
} }
if (ignoring) if (ignoring)
tcc_warning_c(warn_unsupported)("unsupported linker option '%s'", option); tcc_warning_c(warn_unsupported)("unsupported linker option '%s'", option);
@ -1775,7 +1775,7 @@ static int args_parser_make_argv(const char *r, int *argc, char ***argv)
} }
/* read list file */ /* read list file */
static void args_parser_listfile(TCCState *s, static int args_parser_listfile(TCCState *s,
const char *filename, int optind, int *pargc, char ***pargv) const char *filename, int optind, int *pargc, char ***pargv)
{ {
TCCState *s1 = s; TCCState *s1 = s;
@ -1786,7 +1786,7 @@ static void args_parser_listfile(TCCState *s,
fd = open(filename, O_RDONLY | O_BINARY); fd = open(filename, O_RDONLY | O_BINARY);
if (fd < 0) if (fd < 0)
tcc_error("listfile '%s' not found", filename); return tcc_error_noabort("listfile '%s' not found", filename);
p = tcc_load_text(fd); p = tcc_load_text(fd);
for (i = 0; i < *pargc; ++i) for (i = 0; i < *pargc; ++i)
@ -1798,6 +1798,7 @@ static void args_parser_listfile(TCCState *s,
tcc_free(p); tcc_free(p);
dynarray_reset(&s->argv, &s->argc); dynarray_reset(&s->argv, &s->argc);
*pargc = s->argc = argc, *pargv = s->argv = argv; *pargc = s->argc = argc, *pargv = s->argv = argv;
return 0;
} }
#if defined TCC_TARGET_MACHO #if defined TCC_TARGET_MACHO
@ -1815,7 +1816,7 @@ static uint32_t parse_version(TCCState *s1, const char *version)
c = strtoul(&last[1], &last, 10); c = strtoul(&last[1], &last, 10);
} }
if (*last || a > 0xffff || b > 0xff || c > 0xff) if (*last || a > 0xffff || b > 0xff || c > 0xff)
tcc_error("version a.b.c not correct: %s", version); tcc_error_noabort("version a.b.c not correct: %s", version);
return (a << 16) | (b << 8) | c; return (a << 16) | (b << 8) | c;
} }
#endif #endif
@ -1827,17 +1828,17 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind)
const char *optarg, *r; const char *optarg, *r;
const char *run = NULL; const char *run = NULL;
int x; int x;
CString linker_arg; /* collect -Wl options */
int tool = 0, arg_start = 0, noaction = optind; int tool = 0, arg_start = 0, noaction = optind;
char **argv = *pargv; char **argv = *pargv;
int argc = *pargc; int argc = *pargc;
cstr_new(&linker_arg); cstr_reset(&s->linker_arg);
while (optind < argc) { while (optind < argc) {
r = argv[optind]; r = argv[optind];
if (r[0] == '@' && r[1] != '\0') { if (r[0] == '@' && r[1] != '\0') {
args_parser_listfile(s, r + 1, optind, &argc, &argv); if (args_parser_listfile(s, r + 1, optind, &argc, &argv))
return -1;
continue; continue;
} }
optind++; optind++;
@ -1851,7 +1852,8 @@ reparse:
if (r[0] != '@') /* allow "tcc file(s) -run @ args ..." */ if (r[0] != '@') /* allow "tcc file(s) -run @ args ..." */
args_parser_add_file(s, r, s->filetype); args_parser_add_file(s, r, s->filetype);
if (run) { if (run) {
tcc_set_options(s, run); if (tcc_set_options(s, run))
return -1;
arg_start = optind - 1; arg_start = optind - 1;
break; break;
} }
@ -1863,7 +1865,7 @@ reparse:
const char *p1 = popt->name; const char *p1 = popt->name;
const char *r1 = r + 1; const char *r1 = r + 1;
if (p1 == NULL) if (p1 == NULL)
tcc_error("invalid option -- '%s'", r); return tcc_error_noabort("invalid option -- '%s'", r);
if (!strstart(p1, &r1)) if (!strstart(p1, &r1))
continue; continue;
optarg = r1; optarg = r1;
@ -1871,7 +1873,7 @@ reparse:
if (*r1 == '\0' && !(popt->flags & TCC_OPTION_NOSEP)) { if (*r1 == '\0' && !(popt->flags & TCC_OPTION_NOSEP)) {
if (optind >= argc) if (optind >= argc)
arg_err: arg_err:
tcc_error("argument to '%s' is missing", r); return tcc_error_noabort("argument to '%s' is missing", r);
optarg = argv[optind++]; optarg = argv[optind++];
} }
} else if (*r1 != '\0') } else if (*r1 != '\0')
@ -1994,11 +1996,12 @@ reparse:
break; break;
case TCC_OPTION_run: case TCC_OPTION_run:
#ifndef TCC_IS_NATIVE #ifndef TCC_IS_NATIVE
tcc_error("-run is not available in a cross compiler"); return tcc_error_noabort("-run is not available in a cross compiler");
#endif #else
run = optarg; run = optarg;
x = TCC_OUTPUT_MEMORY; x = TCC_OUTPUT_MEMORY;
goto set_output_type; goto set_output_type;
#endif
case TCC_OPTION_v: case TCC_OPTION_v:
do ++s->verbose; while (*optarg++ == 'v'); do ++s->verbose; while (*optarg++ == 'v');
++noaction; ++noaction;
@ -2015,7 +2018,7 @@ reparse:
} else if (!strcmp(optarg, "hard")) } else if (!strcmp(optarg, "hard"))
s->float_abi = ARM_HARD_FLOAT; s->float_abi = ARM_HARD_FLOAT;
else else
tcc_error("unsupported float abi '%s'", optarg); return tcc_error_noabort("unsupported float abi '%s'", optarg);
break; break;
#endif #endif
case TCC_OPTION_m: case TCC_OPTION_m:
@ -2039,11 +2042,14 @@ reparse:
s->rdynamic = 1; s->rdynamic = 1;
break; break;
case TCC_OPTION_Wl: case TCC_OPTION_Wl:
if (linker_arg.size) if (s->linker_arg.size)
--linker_arg.size, cstr_ccat(&linker_arg, ','); ((char*)s->linker_arg.data)[s->linker_arg.size - 1] = ',';
cstr_cat(&linker_arg, optarg, 0); cstr_cat(&s->linker_arg, optarg, 0);
if (tcc_set_linker(s, linker_arg.data)) x = tcc_set_linker(s, s->linker_arg.data);
cstr_free(&linker_arg); if (x)
cstr_reset(&s->linker_arg);
if (x < 0)
return -1;
break; break;
case TCC_OPTION_Wp: case TCC_OPTION_Wp:
r = optarg; r = optarg;
@ -2124,7 +2130,7 @@ reparse:
extra_action: extra_action:
arg_start = optind - 1; arg_start = optind - 1;
if (arg_start != noaction) if (arg_start != noaction)
tcc_error("cannot parse %s here", r); return tcc_error_noabort("cannot parse %s here", r);
tool = x; tool = x;
break; break;
default: default:
@ -2133,8 +2139,8 @@ unsupported_option:
break; break;
} }
} }
if (linker_arg.size) { if (s->linker_arg.size) {
r = linker_arg.data; r = s->linker_arg.data;
goto arg_err; goto arg_err;
} }
*pargc = argc - arg_start; *pargc = argc - arg_start;
@ -2150,13 +2156,14 @@ unsupported_option:
return OPT_HELP; return OPT_HELP;
} }
LIBTCCAPI void tcc_set_options(TCCState *s, const char *r) LIBTCCAPI int tcc_set_options(TCCState *s, const char *r)
{ {
char **argv = NULL; char **argv = NULL;
int argc = 0; int argc = 0, ret;
args_parser_make_argv(r, &argc, &argv); args_parser_make_argv(r, &argc, &argv);
tcc_parse_args(s, &argc, &argv, 0); ret = tcc_parse_args(s, &argc, &argv, 0);
dynarray_reset(&argv, &argc); dynarray_reset(&argv, &argc);
return ret < 0 ? ret : 0;
} }
PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time) PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time)

View File

@ -34,7 +34,7 @@ LIBTCCAPI TCCErrorFunc tcc_get_error_func(TCCState *s);
LIBTCCAPI void *tcc_get_error_opaque(TCCState *s); LIBTCCAPI void *tcc_get_error_opaque(TCCState *s);
/* set options as from command line (multiple supported) */ /* set options as from command line (multiple supported) */
LIBTCCAPI void tcc_set_options(TCCState *s, const char *str); LIBTCCAPI int tcc_set_options(TCCState *s, const char *str);
/*****************************/ /*****************************/
/* preprocessor */ /* preprocessor */

View File

@ -127,7 +127,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
uint64_t got = s1->got->sh_addr; uint64_t got = s1->got->sh_addr;
uint64_t off = (got - plt + 0x800) >> 12; uint64_t off = (got - plt + 0x800) >> 12;
if ((off + ((uint32_t)1 << 20)) >> 21) if ((off + ((uint32_t)1 << 20)) >> 21)
tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt); tcc_error_noabort("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt);
write32le(p, 0x397 | (off << 12)); // auipc t2, %pcrel_hi(got) write32le(p, 0x397 | (off << 12)); // auipc t2, %pcrel_hi(got)
write32le(p + 4, 0x41c30333); // sub t1, t1, t3 write32le(p + 4, 0x41c30333); // sub t1, t1, t3
write32le(p + 8, 0x0003be03 // ld t3, %pcrel_lo(got)(t2) write32le(p + 8, 0x0003be03 // ld t3, %pcrel_lo(got)(t2)
@ -144,7 +144,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
uint64_t addr = got + read64le(p); uint64_t addr = got + read64le(p);
uint64_t off = (addr - pc + 0x800) >> 12; uint64_t off = (addr - pc + 0x800) >> 12;
if ((off + ((uint32_t)1 << 20)) >> 21) if ((off + ((uint32_t)1 << 20)) >> 21)
tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", (long)off, (long)addr, (long)pc); tcc_error_noabort("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", (long)off, (long)addr, (long)pc);
write32le(p, 0xe17 | (off << 12)); // auipc t3, %pcrel_hi(func@got) write32le(p, 0xe17 | (off << 12)); // auipc t3, %pcrel_hi(func@got)
write32le(p + 4, 0x000e3e03 // ld t3, %pcrel_lo(func@got)(t3) write32le(p + 4, 0x000e3e03 // ld t3, %pcrel_lo(func@got)(t3)
| (((addr - pc) & 0xfff) << 20)); | (((addr - pc) & 0xfff) << 20));
@ -179,7 +179,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
case R_RISCV_BRANCH: case R_RISCV_BRANCH:
off64 = val - addr; off64 = val - addr;
if ((off64 + (1 << 12)) & ~(uint64_t)0x1ffe) if ((off64 + (1 << 12)) & ~(uint64_t)0x1ffe)
tcc_error("R_RISCV_BRANCH relocation failed" tcc_error_noabort("R_RISCV_BRANCH relocation failed"
" (val=%lx, addr=%lx)", (long)val, (long)addr); " (val=%lx, addr=%lx)", (long)val, (long)addr);
off32 = off64 >> 1; off32 = off64 >> 1;
write32le(ptr, (read32le(ptr) & ~0xfe000f80) write32le(ptr, (read32le(ptr) & ~0xfe000f80)
@ -191,7 +191,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
case R_RISCV_JAL: case R_RISCV_JAL:
off64 = val - addr; off64 = val - addr;
if ((off64 + (1 << 21)) & ~(((uint64_t)1 << 22) - 2)) if ((off64 + (1 << 21)) & ~(((uint64_t)1 << 22) - 2))
tcc_error("R_RISCV_JAL relocation failed" tcc_error_noabort("R_RISCV_JAL relocation failed"
" (val=%lx, addr=%lx)", (long)val, (long)addr); " (val=%lx, addr=%lx)", (long)val, (long)addr);
off32 = off64; off32 = off64;
write32le(ptr, (read32le(ptr) & 0xfff) write32le(ptr, (read32le(ptr) & 0xfff)
@ -213,7 +213,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
#endif #endif
off64 = (int64_t)(val - addr + 0x800) >> 12; off64 = (int64_t)(val - addr + 0x800) >> 12;
if ((off64 + ((uint64_t)1 << 20)) >> 21) if ((off64 + ((uint64_t)1 << 20)) >> 21)
tcc_error("R_RISCV_PCREL_HI20 relocation failed: off=%lx cond=%lx sym=%s", tcc_error_noabort("R_RISCV_PCREL_HI20 relocation failed: off=%lx cond=%lx sym=%s",
(long)off64, (long)((int64_t)(off64 + ((uint64_t)1 << 20)) >> 21), (long)off64, (long)((int64_t)(off64 + ((uint64_t)1 << 20)) >> 21),
symtab_section->link->data + sym->st_name); symtab_section->link->data + sym->st_name);
write32le(ptr, (read32le(ptr) & 0xfff) write32le(ptr, (read32le(ptr) & 0xfff)
@ -225,7 +225,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
val = s1->got->sh_addr + get_sym_attr(s1, sym_index, 0)->got_offset; val = s1->got->sh_addr + get_sym_attr(s1, sym_index, 0)->got_offset;
off64 = (int64_t)(val - addr + 0x800) >> 12; off64 = (int64_t)(val - addr + 0x800) >> 12;
if ((off64 + ((uint64_t)1 << 20)) >> 21) if ((off64 + ((uint64_t)1 << 20)) >> 21)
tcc_error("R_RISCV_GOT_HI20 relocation failed"); tcc_error_noabort("R_RISCV_GOT_HI20 relocation failed");
last_hi.addr = addr; last_hi.addr = addr;
last_hi.val = val; last_hi.val = val;
write32le(ptr, (read32le(ptr) & 0xfff) write32le(ptr, (read32le(ptr) & 0xfff)
@ -236,7 +236,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
printf("PCREL_LO12_I: val=%lx addr=%lx\n", (long)val, (long)addr); printf("PCREL_LO12_I: val=%lx addr=%lx\n", (long)val, (long)addr);
#endif #endif
if (val != last_hi.addr) if (val != last_hi.addr)
tcc_error("unsupported hi/lo pcrel reloc scheme"); tcc_error_noabort("unsupported hi/lo pcrel reloc scheme");
val = last_hi.val; val = last_hi.val;
addr = last_hi.addr; addr = last_hi.addr;
write32le(ptr, (read32le(ptr) & 0xfffff) write32le(ptr, (read32le(ptr) & 0xfffff)
@ -244,7 +244,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
return; return;
case R_RISCV_PCREL_LO12_S: case R_RISCV_PCREL_LO12_S:
if (val != last_hi.addr) if (val != last_hi.addr)
tcc_error("unsupported hi/lo pcrel reloc scheme"); tcc_error_noabort("unsupported hi/lo pcrel reloc scheme");
val = last_hi.val; val = last_hi.val;
addr = last_hi.addr; addr = last_hi.addr;
off32 = val - addr; off32 = val - addr;
@ -256,7 +256,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
case R_RISCV_RVC_BRANCH: case R_RISCV_RVC_BRANCH:
off64 = (val - addr); off64 = (val - addr);
if ((off64 + (1 << 8)) & ~(uint64_t)0x1fe) if ((off64 + (1 << 8)) & ~(uint64_t)0x1fe)
tcc_error("R_RISCV_RVC_BRANCH relocation failed" tcc_error_noabort("R_RISCV_RVC_BRANCH relocation failed"
" (val=%lx, addr=%lx)", (long)val, (long)addr); " (val=%lx, addr=%lx)", (long)val, (long)addr);
off32 = off64; off32 = off64;
write16le(ptr, (read16le(ptr) & 0xe383) write16le(ptr, (read16le(ptr) & 0xe383)
@ -269,7 +269,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
case R_RISCV_RVC_JUMP: case R_RISCV_RVC_JUMP:
off64 = (val - addr); off64 = (val - addr);
if ((off64 + (1 << 11)) & ~(uint64_t)0xffe) if ((off64 + (1 << 11)) & ~(uint64_t)0xffe)
tcc_error("R_RISCV_RVC_BRANCH relocation failed" tcc_error_noabort("R_RISCV_RVC_BRANCH relocation failed"
" (val=%lx, addr=%lx)", (long)val, (long)addr); " (val=%lx, addr=%lx)", (long)val, (long)addr);
off32 = off64; off32 = off64;
write16le(ptr, (read16le(ptr) & 0xe003) write16le(ptr, (read16le(ptr) & 0xe003)

24
tcc.c
View File

@ -286,6 +286,8 @@ redo:
tcc_set_options(s, CONFIG_TCC_SWITCHES); tcc_set_options(s, CONFIG_TCC_SWITCHES);
#endif #endif
opt = tcc_parse_args(s, &argc, &argv, 1); opt = tcc_parse_args(s, &argc, &argv, 1);
if (opt < 0)
return 1;
if (n == 0) { if (n == 0) {
if (opt == OPT_HELP) { if (opt == OPT_HELP) {
@ -299,7 +301,7 @@ redo:
return 0; return 0;
} }
if (opt == OPT_M32 || opt == OPT_M64) if (opt == OPT_M32 || opt == OPT_M64)
tcc_tool_cross(s, argv, opt); /* never returns */ return tcc_tool_cross(s, argv, opt);
if (s->verbose) if (s->verbose)
printf(version); printf(version);
if (opt == OPT_AR) if (opt == OPT_AR)
@ -318,22 +320,22 @@ redo:
return 0; return 0;
} }
if (s->nb_files == 0) if (s->nb_files == 0) {
tcc_error("no input files"); tcc_error_noabort("no input files");
} else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
if (s->outfile && 0!=strcmp("-",s->outfile)) { if (s->outfile && 0!=strcmp("-",s->outfile)) {
ppfp = fopen(s->outfile, "w"); ppfp = fopen(s->outfile, "w");
if (!ppfp) if (!ppfp)
tcc_error("could not write '%s'", s->outfile); tcc_error_noabort("could not write '%s'", s->outfile);
} }
} else if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) { } else if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) {
if (s->nb_libraries) if (s->nb_libraries)
tcc_error("cannot specify libraries with -c"); tcc_error_noabort("cannot specify libraries with -c");
if (s->nb_files > 1 && s->outfile) else if (s->nb_files > 1 && s->outfile)
tcc_error("cannot specify output file with -c many files"); tcc_error_noabort("cannot specify output file with -c many files");
} }
if (s->nb_errors)
return 1;
if (s->do_bench) if (s->do_bench)
start_time = getclock_ms(); start_time = getclock_ms();
} }
@ -391,7 +393,7 @@ redo:
if (!s->just_deps && tcc_output_file(s, s->outfile)) if (!s->just_deps && tcc_output_file(s, s->outfile))
ret = 1; ret = 1;
else if (s->gen_deps) else if (s->gen_deps)
gen_makedeps(s, s->outfile, s->deps_outfile); ret = gen_makedeps(s, s->outfile, s->deps_outfile);
} }
} }

9
tcc.h
View File

@ -1021,6 +1021,7 @@ struct TCCState {
char *deps_outfile; /* option -MF */ char *deps_outfile; /* option -MF */
int argc; int argc;
char **argv; char **argv;
CString linker_arg; /* collect -Wl options */
}; };
struct filespec { struct filespec {
@ -1239,7 +1240,7 @@ PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line);
#define realloc(p, s) use_tcc_realloc(p, s) #define realloc(p, s) use_tcc_realloc(p, s)
#undef strdup #undef strdup
#define strdup(s) use_tcc_strdup(s) #define strdup(s) use_tcc_strdup(s)
PUB_FUNC void _tcc_error_noabort(const char *fmt, ...) PRINTF_LIKE(1,2); PUB_FUNC int _tcc_error_noabort(const char *fmt, ...) PRINTF_LIKE(1,2);
PUB_FUNC NORETURN void _tcc_error(const char *fmt, ...) PRINTF_LIKE(1,2); PUB_FUNC NORETURN void _tcc_error(const char *fmt, ...) PRINTF_LIKE(1,2);
PUB_FUNC void _tcc_warning(const char *fmt, ...) PRINTF_LIKE(1,2); PUB_FUNC void _tcc_warning(const char *fmt, ...) PRINTF_LIKE(1,2);
#define tcc_internal_error(msg) tcc_error("internal compiler error\n"\ #define tcc_internal_error(msg) tcc_error("internal compiler error\n"\
@ -1787,8 +1788,8 @@ ST_FUNC int tcc_tool_ar(TCCState *s, int argc, char **argv);
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
ST_FUNC int tcc_tool_impdef(TCCState *s, int argc, char **argv); ST_FUNC int tcc_tool_impdef(TCCState *s, int argc, char **argv);
#endif #endif
ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int option); ST_FUNC int tcc_tool_cross(TCCState *s, char **argv, int option);
ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename); ST_FUNC int gen_makedeps(TCCState *s, const char *target, const char *filename);
#endif #endif
/* ------------ tccdbg.c ------------ */ /* ------------ tccdbg.c ------------ */
@ -1915,7 +1916,9 @@ PUB_FUNC void tcc_exit_state(TCCState *s1);
# define TCC_STATE_VAR(sym) tcc_state->sym # define TCC_STATE_VAR(sym) tcc_state->sym
# define TCC_SET_STATE(fn) fn # define TCC_SET_STATE(fn) fn
# undef USING_GLOBALS # undef USING_GLOBALS
# undef _tcc_error
#else #else
# define TCC_STATE_VAR(sym) s1->sym # define TCC_STATE_VAR(sym) s1->sym
# define TCC_SET_STATE(fn) (tcc_enter_state(s1),fn) # define TCC_SET_STATE(fn) (tcc_enter_state(s1),fn)
# define _tcc_error use_tcc_error_noabort
#endif #endif

View File

@ -21,6 +21,9 @@
#include "tcc.h" #include "tcc.h"
/* XXX: this file uses tcc_error() to the effect of exit(1) */
#undef _tcc_error
#define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */ #define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */
#define MAX_STR_TABLE 1000000 #define MAX_STR_TABLE 1000000
AOUTHDR o_filehdr; /* OPTIONAL (A.OUT) FILE HEADER */ AOUTHDR o_filehdr; /* OPTIONAL (A.OUT) FILE HEADER */

View File

@ -506,7 +506,7 @@ ST_FUNC addr_t get_sym_addr(TCCState *s1, const char *name, int err, int forc)
sym = &((ElfW(Sym) *)s1->symtab->data)[sym_index]; sym = &((ElfW(Sym) *)s1->symtab->data)[sym_index];
if (!sym_index || sym->st_shndx == SHN_UNDEF) { if (!sym_index || sym->st_shndx == SHN_UNDEF) {
if (err) if (err)
tcc_error("%s not defined", name); tcc_error_noabort("%s not defined", name);
return (addr_t)-1; return (addr_t)-1;
} }
return sym->st_value; return sym->st_value;
@ -759,7 +759,7 @@ ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset,
rel->r_addend = addend; rel->r_addend = addend;
#endif #endif
if (SHT_RELX != SHT_RELA && addend) if (SHT_RELX != SHT_RELA && addend)
tcc_error("non-zero addend on REL architecture"); tcc_error_noabort("non-zero addend on REL architecture");
} }
ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
@ -953,7 +953,7 @@ static void update_gnu_hash(TCCState *s1, Section *gnu_hash)
PTR_SIZE * bloom_size + PTR_SIZE * bloom_size +
nbuckets * 4 + nbuckets * 4 +
(nb_syms - (q - new_syms)) * 4) (nb_syms - (q - new_syms)) * 4)
tcc_error ("gnu_hash size incorrect"); tcc_error_noabort ("gnu_hash size incorrect");
/* find buckets */ /* find buckets */
for(i = 0; i < nbuckets; i++) for(i = 0; i < nbuckets; i++)
@ -1364,8 +1364,10 @@ redo:
for_each_elem(s, 0, rel, ElfW_Rel) { for_each_elem(s, 0, rel, ElfW_Rel) {
type = ELFW(R_TYPE)(rel->r_info); type = ELFW(R_TYPE)(rel->r_info);
gotplt_entry = gotplt_entry_type(type); gotplt_entry = gotplt_entry_type(type);
if (gotplt_entry == -1) if (gotplt_entry == -1) {
tcc_error ("Unknown relocation type for got: %d", type); tcc_error_noabort ("Unknown relocation type for got: %d", type);
continue;
}
sym_index = ELFW(R_SYM)(rel->r_info); sym_index = ELFW(R_SYM)(rel->r_info);
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
@ -1430,8 +1432,10 @@ redo:
} }
#endif #endif
reloc_type = code_reloc(type); reloc_type = code_reloc(type);
if (reloc_type == -1) if (reloc_type == -1) {
tcc_error ("Unknown relocation type: %d", type); tcc_error_noabort ("Unknown relocation type: %d", type);
continue;
}
if (reloc_type != 0) { if (reloc_type != 0) {
jmp_slot: jmp_slot:
@ -1862,7 +1866,7 @@ static void fill_local_got_entries(TCCState *s1)
struct sym_attr *attr = get_sym_attr(s1, sym_index, 0); struct sym_attr *attr = get_sym_attr(s1, sym_index, 0);
unsigned offset = attr->got_offset; unsigned offset = attr->got_offset;
if (offset != rel->r_offset - s1->got->sh_addr) if (offset != rel->r_offset - s1->got->sh_addr)
tcc_error_noabort("huh"); tcc_error_noabort("fill_local_got_entries: huh?");
rel->r_info = ELFW(R_INFO)(0, R_RELATIVE); rel->r_info = ELFW(R_INFO)(0, R_RELATIVE);
#if SHT_RELX == SHT_RELA #if SHT_RELX == SHT_RELA
rel->r_addend = sym->st_value; rel->r_addend = sym->st_value;
@ -2448,7 +2452,7 @@ static int tidy_section_headers(TCCState *s1, int *sec_order);
/* Create an ELF file on disk. /* Create an ELF file on disk.
This function handle ELF specific layout requirements */ This function handle ELF specific layout requirements */
static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr, static int tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
int file_offset, int *sec_order) int file_offset, int *sec_order)
{ {
int i, shnum, offset, size, file_type; int i, shnum, offset, size, file_type;
@ -2507,6 +2511,8 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
ehdr.e_entry = get_sym_addr(s1, "_start", !!(file_type & TCC_OUTPUT_EXE), 0); ehdr.e_entry = get_sym_addr(s1, "_start", !!(file_type & TCC_OUTPUT_EXE), 0);
if (ehdr.e_entry == (addr_t)-1) if (ehdr.e_entry == (addr_t)-1)
ehdr.e_entry = text_section->sh_addr; ehdr.e_entry = text_section->sh_addr;
if (s1->nb_errors)
return -1;
} }
ehdr.e_machine = EM_TCC_TARGET; ehdr.e_machine = EM_TCC_TARGET;
@ -2563,9 +2569,10 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
} }
fwrite(sh, 1, sizeof(ElfW(Shdr)), f); fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
} }
return 0;
} }
static void tcc_output_binary(TCCState *s1, FILE *f, static int tcc_output_binary(TCCState *s1, FILE *f,
const int *sec_order) const int *sec_order)
{ {
Section *s; Section *s;
@ -2585,13 +2592,14 @@ static void tcc_output_binary(TCCState *s1, FILE *f,
offset += size; offset += size;
} }
} }
return 0;
} }
/* Write an elf, coff or "binary" file */ /* Write an elf, coff or "binary" file */
static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum, static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum,
ElfW(Phdr) *phdr, int file_offset, int *sec_order) ElfW(Phdr) *phdr, int file_offset, int *sec_order)
{ {
int fd, mode, file_type; int fd, mode, file_type, ret;
FILE *f; FILE *f;
file_type = s1->output_type; file_type = s1->output_type;
@ -2601,25 +2609,22 @@ static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum,
mode = 0777; mode = 0777;
unlink(filename); unlink(filename);
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode); fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
if (fd < 0 || (f = fdopen(fd, "wb")) == NULL) { if (fd < 0 || (f = fdopen(fd, "wb")) == NULL)
tcc_error_noabort("could not write '%s: %s'", filename, strerror(errno)); return tcc_error_noabort("could not write '%s: %s'", filename, strerror(errno));
return -1;
}
if (s1->verbose) if (s1->verbose)
printf("<- %s\n", filename); printf("<- %s\n", filename);
#ifdef TCC_TARGET_COFF #ifdef TCC_TARGET_COFF
if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) if (s1->output_format == TCC_OUTPUT_FORMAT_COFF)
tcc_output_coff(s1, f); tcc_output_coff(s1, f);
else else
#endif #endif
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
tcc_output_elf(s1, f, phnum, phdr, file_offset, sec_order); ret = tcc_output_elf(s1, f, phnum, phdr, file_offset, sec_order);
else else
tcc_output_binary(s1, f, sec_order); ret = tcc_output_binary(s1, f, sec_order);
fclose(f); fclose(f);
return 0; return ret;
} }
#ifndef ELF_OBJ_ONLY #ifndef ELF_OBJ_ONLY
@ -3016,13 +3021,12 @@ ST_FUNC int tcc_load_object_file(TCCState *s1,
lseek(fd, file_offset, SEEK_SET); lseek(fd, file_offset, SEEK_SET);
if (tcc_object_type(fd, &ehdr) != AFF_BINTYPE_REL) if (tcc_object_type(fd, &ehdr) != AFF_BINTYPE_REL)
goto fail1; goto invalid;
/* test CPU specific stuff */ /* test CPU specific stuff */
if (ehdr.e_ident[5] != ELFDATA2LSB || if (ehdr.e_ident[5] != ELFDATA2LSB ||
ehdr.e_machine != EM_TCC_TARGET) { ehdr.e_machine != EM_TCC_TARGET) {
fail1: invalid:
tcc_error_noabort("invalid object file"); return tcc_error_noabort("invalid object file");
return -1;
} }
/* read sections */ /* read sections */
shdr = load_data(fd, file_offset + ehdr.e_shoff, shdr = load_data(fd, file_offset + ehdr.e_shoff,
@ -3040,14 +3044,13 @@ ST_FUNC int tcc_load_object_file(TCCState *s1,
nb_syms = 0; nb_syms = 0;
seencompressed = 0; seencompressed = 0;
stab_index = stabstr_index = 0; stab_index = stabstr_index = 0;
ret = -1;
for(i = 1; i < ehdr.e_shnum; i++) { for(i = 1; i < ehdr.e_shnum; i++) {
sh = &shdr[i]; sh = &shdr[i];
if (sh->sh_type == SHT_SYMTAB) { if (sh->sh_type == SHT_SYMTAB) {
if (symtab) { if (symtab) {
tcc_error_noabort("object must contain only one symtab"); tcc_error_noabort("object must contain only one symtab");
fail:
ret = -1;
goto the_end; goto the_end;
} }
nb_syms = sh->sh_size / sizeof(ElfW(Sym)); nb_syms = sh->sh_size / sizeof(ElfW(Sym));
@ -3124,14 +3127,13 @@ ST_FUNC int tcc_load_object_file(TCCState *s1,
s->sh_entsize = sh->sh_entsize; s->sh_entsize = sh->sh_entsize;
sm_table[i].new_section = 1; sm_table[i].new_section = 1;
found: found:
if (sh->sh_type != s->sh_type) { if (sh->sh_type != s->sh_type
#if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD #if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD
if (strcmp (s->name, ".eh_frame")) && strcmp (s->name, ".eh_frame")
#endif #endif
{ ) {
tcc_error_noabort("invalid section type"); tcc_error_noabort("invalid section type");
goto fail; goto the_end;
}
} }
/* align start of section */ /* align start of section */
s->data_offset += -s->data_offset & (sh->sh_addralign - 1); s->data_offset += -s->data_offset & (sh->sh_addralign - 1);
@ -3255,7 +3257,7 @@ ST_FUNC int tcc_load_object_file(TCCState *s1,
invalid_reloc: invalid_reloc:
tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x", tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
i, strsec + sh->sh_name, (int)rel->r_offset); i, strsec + sh->sh_name, (int)rel->r_offset);
goto fail; goto the_end;
} }
rel->r_info = ELFW(R_INFO)(sym_index, type); rel->r_info = ELFW(R_INFO)(sym_index, type);
/* offset the relocation offset */ /* offset the relocation offset */
@ -3391,10 +3393,8 @@ ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte)
len = read_ar_header(fd, file_offset, &hdr); len = read_ar_header(fd, file_offset, &hdr);
if (len == 0) if (len == 0)
return 0; return 0;
if (len < 0) { if (len < 0)
tcc_error_noabort("invalid archive"); return tcc_error_noabort("invalid archive");
return -1;
}
file_offset += len; file_offset += len;
size = strtol(hdr.ar_size, NULL, 0); size = strtol(hdr.ar_size, NULL, 0);
/* align to even */ /* align to even */
@ -3568,8 +3568,7 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
/* test CPU specific stuff */ /* test CPU specific stuff */
if (ehdr.e_ident[5] != ELFDATA2LSB || if (ehdr.e_ident[5] != ELFDATA2LSB ||
ehdr.e_machine != EM_TCC_TARGET) { ehdr.e_machine != EM_TCC_TARGET) {
tcc_error_noabort("bad architecture"); return tcc_error_noabort("bad architecture");
return -1;
} }
/* read sections */ /* read sections */
@ -3655,7 +3654,7 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
if (tcc_add_dllref(s1, name, -1)) if (tcc_add_dllref(s1, name, -1))
continue; continue;
if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) { if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
tcc_error_noabort("referenced dll '%s' not found", name); ret = tcc_error_noabort("referenced dll '%s' not found", name);
goto the_end; goto the_end;
} }
} }
@ -3830,24 +3829,21 @@ static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
s1->new_undef_sym = 0; s1->new_undef_sym = 0;
t = ld_next(s1, filename, sizeof(filename)); t = ld_next(s1, filename, sizeof(filename));
if (t != '(') { if (t != '(') {
tcc_error_noabort("( expected"); ret = tcc_error_noabort("( expected");
ret = -1;
goto lib_parse_error; goto lib_parse_error;
} }
t = ld_next(s1, filename, sizeof(filename)); t = ld_next(s1, filename, sizeof(filename));
for(;;) { for(;;) {
libname[0] = '\0'; libname[0] = '\0';
if (t == LD_TOK_EOF) { if (t == LD_TOK_EOF) {
tcc_error_noabort("unexpected end of file"); ret = tcc_error_noabort("unexpected end of file");
ret = -1;
goto lib_parse_error; goto lib_parse_error;
} else if (t == ')') { } else if (t == ')') {
break; break;
} else if (t == '-') { } else if (t == '-') {
t = ld_next(s1, filename, sizeof(filename)); t = ld_next(s1, filename, sizeof(filename));
if ((t != LD_TOK_NAME) || (filename[0] != 'l')) { if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
tcc_error_noabort("library name expected"); ret = tcc_error_noabort("library name expected");
ret = -1;
goto lib_parse_error; goto lib_parse_error;
} }
pstrcpy(libname, sizeof libname, &filename[1]); pstrcpy(libname, sizeof libname, &filename[1]);
@ -3857,8 +3853,7 @@ static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
snprintf(filename, sizeof filename, "lib%s.so", libname); snprintf(filename, sizeof filename, "lib%s.so", libname);
} }
} else if (t != LD_TOK_NAME) { } else if (t != LD_TOK_NAME) {
tcc_error_noabort("filename expected"); ret = tcc_error_noabort("filename expected");
ret = -1;
goto lib_parse_error; goto lib_parse_error;
} }
if (!strcmp(filename, "AS_NEEDED")) { if (!strcmp(filename, "AS_NEEDED")) {
@ -3922,15 +3917,12 @@ ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd)
!strcmp(cmd, "TARGET")) { !strcmp(cmd, "TARGET")) {
/* ignore some commands */ /* ignore some commands */
t = ld_next(s1, cmd, sizeof(cmd)); t = ld_next(s1, cmd, sizeof(cmd));
if (t != '(') { if (t != '(')
tcc_error_noabort("( expected"); return tcc_error_noabort("( expected");
return -1;
}
for(;;) { for(;;) {
t = ld_next(s1, filename, sizeof(filename)); t = ld_next(s1, filename, sizeof(filename));
if (t == LD_TOK_EOF) { if (t == LD_TOK_EOF) {
tcc_error_noabort("unexpected end of file"); return tcc_error_noabort("unexpected end of file");
return -1;
} else if (t == ')') { } else if (t == ')') {
break; break;
} }

View File

@ -2928,8 +2928,7 @@ redo:
} }
goto redo; goto redo;
} else if (!combine_types(&combtype, vtop - 1, vtop, op)) { } else if (!combine_types(&combtype, vtop - 1, vtop, op)) {
tcc_error_noabort("invalid operand types for binary operation"); tcc_error("invalid operand types for binary operation");
vpop();
} else if (bt1 == VT_PTR || bt2 == VT_PTR) { } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
/* at least one operand is a pointer */ /* at least one operand is a pointer */
/* relational op: must be both pointers */ /* relational op: must be both pointers */

View File

@ -35,6 +35,9 @@
#error Platform not supported #error Platform not supported
#endif #endif
/* XXX: this file uses tcc_error() to the effect of exit(1) */
#undef _tcc_error
#define DEBUG_MACHO 0 #define DEBUG_MACHO 0
#define dprintf if (DEBUG_MACHO) printf #define dprintf if (DEBUG_MACHO) printf

25
tccpe.c
View File

@ -618,10 +618,8 @@ static int pe_write(struct pe_info *pe)
TCCState *s1 = pe->s1; TCCState *s1 = pe->s1;
pf.op = fopen(pe->filename, "wb"); pf.op = fopen(pe->filename, "wb");
if (NULL == pf.op) { if (NULL == pf.op)
tcc_error_noabort("could not write '%s': %s", pe->filename, strerror(errno)); return tcc_error_noabort("could not write '%s': %s", pe->filename, strerror(errno));
return -1;
}
pe->sizeofheaders = pe_file_align(pe, pe->sizeofheaders = pe_file_align(pe,
sizeof (struct pe_header) sizeof (struct pe_header)
@ -1337,9 +1335,8 @@ static int pe_check_symbols(struct pe_info *pe)
if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK) if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
/* STB_WEAK undefined symbols are accepted */ /* STB_WEAK undefined symbols are accepted */
continue; continue;
tcc_error_noabort("undefined symbol '%s'%s", name, ret = tcc_error_noabort("undefined symbol '%s'%s", name,
imp_sym < 0 ? ", missing __declspec(dllimport)?":""); imp_sym < 0 ? ", missing __declspec(dllimport)?":"");
ret = -1;
} else if (pe->s1->rdynamic } else if (pe->s1->rdynamic
&& ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
@ -1990,7 +1987,6 @@ static void pe_set_options(TCCState * s1, struct pe_info *pe)
ST_FUNC int pe_output_file(TCCState *s1, const char *filename) ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
{ {
int ret;
struct pe_info pe; struct pe_info pe;
memset(&pe, 0, sizeof pe); memset(&pe, 0, sizeof pe);
@ -2005,9 +2001,9 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
pe_add_runtime(s1, &pe); pe_add_runtime(s1, &pe);
resolve_common_syms(s1); resolve_common_syms(s1);
pe_set_options(s1, &pe); pe_set_options(s1, &pe);
pe_check_symbols(&pe);
ret = pe_check_symbols(&pe); if (s1->nb_errors)
if (ret)
; ;
else if (filename) { else if (filename) {
pe_assign_addresses(&pe); pe_assign_addresses(&pe);
@ -2016,10 +2012,8 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
relocate_sections(s1); relocate_sections(s1);
pe.start_addr = (DWORD) pe.start_addr = (DWORD)
(get_sym_addr(s1, pe.start_symbol, 1, 1) - pe.imagebase); (get_sym_addr(s1, pe.start_symbol, 1, 1) - pe.imagebase);
if (s1->nb_errors) if (0 == s1->nb_errors)
ret = -1; pe_write(&pe);
else
ret = pe_write(&pe);
dynarray_reset(&pe.sec_info, &pe.sec_count); dynarray_reset(&pe.sec_info, &pe.sec_count);
} else { } else {
#ifdef TCC_IS_NATIVE #ifdef TCC_IS_NATIVE
@ -2031,15 +2025,12 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
#endif #endif
#endif #endif
} }
pe_free_imports(&pe); pe_free_imports(&pe);
#if PE_PRINT_SECTIONS #if PE_PRINT_SECTIONS
if (s1->g_debug & 8) if (s1->g_debug & 8)
pe_print_sections(s1, "tcc.log"); pe_print_sections(s1, "tcc.log");
#endif #endif
return ret; return s1->nb_errors ? -1 : 0;
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */

View File

@ -63,7 +63,7 @@ static void rt_exit(int code);
# include <sys/mman.h> # include <sys/mman.h>
#endif #endif
static void set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length); static int set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length);
static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff); static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff);
#ifdef _WIN64 #ifdef _WIN64
@ -100,16 +100,17 @@ LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr)
ptr = mmap(NULL, size * 2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); ptr = mmap(NULL, size * 2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
/* mmap RX memory at a fixed distance */ /* mmap RX memory at a fixed distance */
prx = mmap((char*)ptr + size, size, PROT_READ|PROT_EXEC, MAP_SHARED|MAP_FIXED, fd, 0); prx = mmap((char*)ptr + size, size, PROT_READ|PROT_EXEC, MAP_SHARED|MAP_FIXED, fd, 0);
if (ptr == MAP_FAILED || prx == MAP_FAILED)
tcc_error("tccrun: could not map memory");
ptr_diff = (char*)prx - (char*)ptr;
close(fd); close(fd);
if (ptr == MAP_FAILED || prx == MAP_FAILED)
return tcc_error_noabort("tccrun: could not map memory");
ptr_diff = (char*)prx - (char*)ptr;
//printf("map %p %p %p\n", ptr, prx, (void*)ptr_diff); //printf("map %p %p %p\n", ptr, prx, (void*)ptr_diff);
} }
#else #else
ptr = tcc_malloc(size); ptr = tcc_malloc(size);
#endif #endif
tcc_relocate_ex(s1, ptr, ptr_diff); /* no more errors expected */ if (tcc_relocate_ex(s1, ptr, ptr_diff))
return -1;
dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)size); dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)size);
dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, ptr); dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, ptr);
return 0; return 0;
@ -237,6 +238,8 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0) if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0)
return -1; return -1;
prog_main = (void*)get_sym_addr(s1, s1->runtime_main, 1, 1); prog_main = (void*)get_sym_addr(s1, s1->runtime_main, 1, 1);
if ((addr_t)-1 == (addr_t)prog_main)
return -1;
#ifdef CONFIG_TCC_BACKTRACE #ifdef CONFIG_TCC_BACKTRACE
memset(rc, 0, sizeof *rc); memset(rc, 0, sizeof *rc);
@ -409,8 +412,10 @@ redo:
#if DEBUG_RUNMEN #if DEBUG_RUNMEN
printf("protect %d %p %04x\n", f, (void*)addr, n); printf("protect %d %p %04x\n", f, (void*)addr, n);
#endif #endif
if (n) if (n) {
set_pages_executable(s1, f, (void*)addr, n); if (set_pages_executable(s1, f, (void*)addr, n))
return -1;
}
} }
} }
@ -440,7 +445,7 @@ redo:
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* allow to run code in memory */ /* allow to run code in memory */
static void set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length) static int set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length)
{ {
#ifdef _WIN32 #ifdef _WIN32
static const unsigned char protect[] = { static const unsigned char protect[] = {
@ -450,7 +455,9 @@ static void set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned lon
PAGE_EXECUTE_READWRITE PAGE_EXECUTE_READWRITE
}; };
DWORD old; DWORD old;
VirtualProtect(ptr, length, protect[mode], &old); if (!VirtualProtect(ptr, length, protect[mode], &old))
return -1;
return 0;
#else #else
static const unsigned char protect[] = { static const unsigned char protect[] = {
PROT_READ | PROT_EXEC, PROT_READ | PROT_EXEC,
@ -463,8 +470,7 @@ static void set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned lon
end = (addr_t)ptr + length; end = (addr_t)ptr + length;
end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1); end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
if (mprotect((void *)start, end - start, protect[mode])) if (mprotect((void *)start, end - start, protect[mode]))
tcc_error("mprotect failed: did you mean to configure --with-selinux?"); return tcc_error_noabort("mprotect failed: did you mean to configure --with-selinux?");
/* XXX: BSD sometimes dump core with bad system call */ /* XXX: BSD sometimes dump core with bad system call */
# if (defined TCC_TARGET_ARM && !TARGETOS_BSD) || defined TCC_TARGET_ARM64 # if (defined TCC_TARGET_ARM && !TARGETOS_BSD) || defined TCC_TARGET_ARM64
if (mode == 0 || mode == 3) { if (mode == 0 || mode == 3) {
@ -472,7 +478,7 @@ static void set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned lon
__clear_cache(ptr, (char *)ptr + length); __clear_cache(ptr, (char *)ptr + length);
} }
# endif # endif
return 0;
#endif #endif
} }

View File

@ -490,9 +490,10 @@ the_end:
#if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64 #if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64
ST_FUNC void tcc_tool_cross(TCCState *s1, char **argv, int option) ST_FUNC int tcc_tool_cross(TCCState *s1, char **argv, int option)
{ {
tcc_error("-m%d not implemented.", option); tcc_error_noabort("-m%d not implemented.", option);
return 1;
} }
#else #else
@ -539,7 +540,7 @@ static int execvp_win32(const char *prog, char **argv)
#define execvp execvp_win32 #define execvp execvp_win32
#endif /* _WIN32 */ #endif /* _WIN32 */
ST_FUNC void tcc_tool_cross(TCCState *s1, char **argv, int target) ST_FUNC int tcc_tool_cross(TCCState *s1, char **argv, int target)
{ {
char program[4096]; char program[4096];
char *a0 = argv[0]; char *a0 = argv[0];
@ -558,7 +559,8 @@ ST_FUNC void tcc_tool_cross(TCCState *s1, char **argv, int target)
if (strcmp(a0, program)) if (strcmp(a0, program))
execvp(argv[0] = program, argv); execvp(argv[0] = program, argv);
tcc_error("could not run '%s'", program); tcc_error_noabort("could not run '%s'", program);
return 1;
} }
#endif /* TCC_TARGET_I386 && TCC_TARGET_X86_64 */ #endif /* TCC_TARGET_I386 && TCC_TARGET_X86_64 */
@ -588,7 +590,7 @@ static char *escape_target_dep(const char *s) {
return res; return res;
} }
ST_FUNC void gen_makedeps(TCCState *s1, const char *target, const char *filename) ST_FUNC int gen_makedeps(TCCState *s1, const char *target, const char *filename)
{ {
FILE *depout; FILE *depout;
char buf[1024], *escaped_target; char buf[1024], *escaped_target;
@ -601,16 +603,16 @@ ST_FUNC void gen_makedeps(TCCState *s1, const char *target, const char *filename
filename = buf; filename = buf;
} }
if (s1->verbose)
printf("<- %s\n", filename);
if(!strcmp(filename, "-")) if(!strcmp(filename, "-"))
depout = fdopen(1, "w"); depout = fdopen(1, "w");
else else
/* XXX return err codes instead of error() ? */ /* XXX return err codes instead of error() ? */
depout = fopen(filename, "w"); depout = fopen(filename, "w");
if (!depout) if (!depout)
tcc_error("could not open '%s'", filename); return tcc_error_noabort("could not open '%s'", filename);
if (s1->verbose)
printf("<- %s\n", filename);
fprintf(depout, "%s:", target); fprintf(depout, "%s:", target);
for (i = 0; i<s1->nb_target_deps; ++i) { for (i = 0; i<s1->nb_target_deps; ++i) {
for (k = 0; k < i; ++k) for (k = 0; k < i; ++k)
@ -623,6 +625,7 @@ ST_FUNC void gen_makedeps(TCCState *s1, const char *target, const char *filename
} }
fprintf(depout, "\n"); fprintf(depout, "\n");
fclose(depout); fclose(depout);
return 0;
} }
/* -------------------------------------------------------------- */ /* -------------------------------------------------------------- */

View File

@ -251,7 +251,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
/* ignore overflow with undefined weak symbols */ /* ignore overflow with undefined weak symbols */
if (((ElfW(Sym)*)symtab_section->data)[sym_index].st_shndx != SHN_UNDEF) if (((ElfW(Sym)*)symtab_section->data)[sym_index].st_shndx != SHN_UNDEF)
#endif #endif
tcc_error("internal error: relocation failed"); tcc_error_noabort("internal error: relocation failed");
} }
add32le(ptr, diff); add32le(ptr, diff);
} }
@ -336,7 +336,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
add32le(ptr + 8, x); add32le(ptr + 8, x);
} }
else else
tcc_error("unexpected R_X86_64_TLSGD pattern"); tcc_error_noabort("unexpected R_X86_64_TLSGD pattern");
} }
break; break;
case R_X86_64_TLSLD: case R_X86_64_TLSLD:
@ -356,7 +356,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
rel[1].r_info = ELFW(R_INFO)(0, R_X86_64_NONE); rel[1].r_info = ELFW(R_INFO)(0, R_X86_64_NONE);
} }
else else
tcc_error("unexpected R_X86_64_TLSLD pattern"); tcc_error_noabort("unexpected R_X86_64_TLSLD pattern");
} }
break; break;
case R_X86_64_DTPOFF32: case R_X86_64_DTPOFF32: