stuff & fixes

libtcc.c:
- revert "Small patch to allow..." (someone's personal easteregg)
  (see da3a763e97)
- check return value from macho_load_tbd/dylib

tcc.c:
- remove help for "not yet implemented" option

tccelf.c:
- check PIE's for "unresolved symbols"

tccgen.c:
- avoid int->double->int cast
  (see a46372e910)
- fix constant propagation with pseudo long doubles
  (must mask out VT_LONG from type)
- cleanup find_field() (again)

tccpp.c:
- disallow strings and double constants in #if expressions

win32/include/uchar.h:
- change file mode
This commit is contained in:
grischka 2023-06-03 21:20:48 +02:00
parent 3f3cbb51ed
commit cd75ca692a
8 changed files with 48 additions and 94 deletions

View File

@ -99,50 +99,12 @@ BOOL WINAPI DllMain (HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved)
/* on win32, we suppose the lib and includes are at the location of 'tcc.exe' */ /* on win32, we suppose the lib and includes are at the location of 'tcc.exe' */
static inline char *config_tccdir_w32(char *path) static inline char *config_tccdir_w32(char *path)
{ {
char temp[1024];
char try[1024];
char *p; char *p;
int c;
GetModuleFileName(tcc_module, path, MAX_PATH); GetModuleFileName(tcc_module, path, MAX_PATH);
p = tcc_basename(normalize_slashes(strlwr(path))); p = tcc_basename(normalize_slashes(strlwr(path)));
if (p > path) if (p > path)
--p; --p;
*p = 0; *p = 0;
/*
* See if we are perhaps in a "bin/" subfolder of the
* installation path, in which case the real root of
* the installation is one level up. We can test this
* by looking for the 'include' folder.
*/
strncpy(temp, path, sizeof(temp)-1);
strcat(temp, "/include");
if (_access(temp, 0) != 0) {
/* No 'include' folder found, so go up one level. */
strncpy(temp, path, sizeof(temp)-1);
/* Try this for several "levels" up. */
for (c = 0; c < 4; c++) {
p = tcc_basename(temp);
if (p > temp) {
--p;
*p = '\0';
}
strncpy(try, temp, sizeof(try)-1);
strcat(try, "/include");
if (_access(try, 0) == 0) {
if (p != NULL)
p = '\0';
strcpy(path, temp);
break;
}
}
}
return path; return path;
} }
#define CONFIG_TCCDIR config_tccdir_w32(alloca(MAX_PATH)) #define CONFIG_TCCDIR config_tccdir_w32(alloca(MAX_PATH))
@ -1174,7 +1136,7 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
} else { } else {
ret = macho_load_tbd(s1, fd, filename, (flags & AFF_REFERENCED_DLL) != 0); ret = macho_load_tbd(s1, fd, filename, (flags & AFF_REFERENCED_DLL) != 0);
} }
break; goto check_success;
default: default:
{ {
const char *ext = tcc_fileextension(filename); const char *ext = tcc_fileextension(filename);

3
tcc.c
View File

@ -48,7 +48,6 @@ static const char help[] =
" -Dsym[=val] define 'sym' with value 'val'\n" " -Dsym[=val] define 'sym' with value 'val'\n"
" -Usym undefine 'sym'\n" " -Usym undefine 'sym'\n"
" -E preprocess only\n" " -E preprocess only\n"
" -C keep comments (not yet implemented)\n"
"Linker options:\n" "Linker options:\n"
" -Ldir add library path 'dir'\n" " -Ldir add library path 'dir'\n"
" -llib link with dynamic or static library 'lib'\n" " -llib link with dynamic or static library 'lib'\n"
@ -303,7 +302,7 @@ redo:
if (opt == OPT_M32 || opt == OPT_M64) if (opt == OPT_M32 || opt == OPT_M64)
return tcc_tool_cross(s, argv, opt); return tcc_tool_cross(s, argv, opt);
if (s->verbose) if (s->verbose)
printf(version); printf("%s", version);
if (opt == OPT_AR) if (opt == OPT_AR)
return tcc_tool_ar(s, argc, argv); return tcc_tool_ar(s, argc, argv);
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE

3
tcc.h
View File

@ -284,7 +284,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
/* library search paths */ /* library search paths */
#ifndef CONFIG_TCC_LIBPATHS #ifndef CONFIG_TCC_LIBPATHS
# ifdef TCC_TARGET_PE # if defined TCC_TARGET_PE || defined _WIN32
# define CONFIG_TCC_LIBPATHS "{B}/lib" # define CONFIG_TCC_LIBPATHS "{B}/lib"
# else # else
# define CONFIG_TCC_LIBPATHS \ # define CONFIG_TCC_LIBPATHS \
@ -496,7 +496,6 @@ typedef struct CString {
int size; /* size in bytes */ int size; /* size in bytes */
int size_allocated; int size_allocated;
void *data; /* either 'char *' or 'nwchar_t *' */ void *data; /* either 'char *' or 'nwchar_t *' */
struct CString *prev;
} CString; } CString;
/* type definition */ /* type definition */

View File

@ -1880,7 +1880,7 @@ static void fill_local_got_entries(TCCState *s1)
/* Bind symbols of executable: resolve undefined symbols from exported symbols /* Bind symbols of executable: resolve undefined symbols from exported symbols
in shared libraries */ in shared libraries */
static void bind_exe_dynsyms(TCCState *s1) static void bind_exe_dynsyms(TCCState *s1, int is_PIE)
{ {
const char *name; const char *name;
int sym_index, index; int sym_index, index;
@ -1895,6 +1895,8 @@ static void bind_exe_dynsyms(TCCState *s1)
name = (char *) symtab_section->link->data + sym->st_name; name = (char *) symtab_section->link->data + sym->st_name;
sym_index = find_elf_sym(s1->dynsymtab_section, name); sym_index = find_elf_sym(s1->dynsymtab_section, name);
if (sym_index) { if (sym_index) {
if (is_PIE)
continue;
esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index]; esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
type = ELFW(ST_TYPE)(esym->st_info); type = ELFW(ST_TYPE)(esym->st_info);
if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) { if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
@ -1970,9 +1972,9 @@ static void bind_libs_dynsyms(TCCState *s1)
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) { for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
name = (char *)symtab_section->link->data + sym->st_name; name = (char *)symtab_section->link->data + sym->st_name;
dynsym_index = find_elf_sym(s1->dynsymtab_section, name); dynsym_index = find_elf_sym(s1->dynsymtab_section, name);
if (sym->st_shndx != SHN_UNDEF if (sym->st_shndx != SHN_UNDEF) {
&& ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL
if (dynsym_index || s1->rdynamic) && (dynsym_index || s1->rdynamic))
set_elf_sym(s1->dynsym, sym->st_value, sym->st_size, set_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
sym->st_info, 0, sym->st_shndx, name); sym->st_info, 0, sym->st_shndx, name);
} else if (dynsym_index) { } else if (dynsym_index) {
@ -2797,8 +2799,8 @@ static int elf_output_file(TCCState *s1, const char *filename)
dynamic->sh_entsize = sizeof(ElfW(Dyn)); dynamic->sh_entsize = sizeof(ElfW(Dyn));
got_sym = build_got(s1); got_sym = build_got(s1);
if (file_type == TCC_OUTPUT_EXE) { if (file_type & TCC_OUTPUT_EXE) {
bind_exe_dynsyms(s1); bind_exe_dynsyms(s1, file_type & TCC_OUTPUT_DYN);
if (s1->nb_errors) if (s1->nb_errors)
goto the_end; goto the_end;
} }

View File

@ -2474,7 +2474,7 @@ void gen_negf(int op)
/* generate a floating point operation with constant propagation */ /* generate a floating point operation with constant propagation */
static void gen_opif(int op) static void gen_opif(int op)
{ {
int c1, c2, cast_int = 0; int c1, c2, i, bt;
SValue *v1, *v2; SValue *v1, *v2;
#if defined _MSC_VER && defined __x86_64__ #if defined _MSC_VER && defined __x86_64__
/* avoid bad optimization with f1 -= f2 for f1:-0.0, f2:0.0 */ /* avoid bad optimization with f1 -= f2 for f1:-0.0, f2:0.0 */
@ -2486,15 +2486,16 @@ static void gen_opif(int op)
v2 = vtop; v2 = vtop;
if (op == TOK_NEG) if (op == TOK_NEG)
v1 = v2; v1 = v2;
bt = v1->type.t & VT_BTYPE;
/* currently, we cannot do computations with forward symbols */ /* currently, we cannot do computations with forward symbols */
c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
if (c1 && c2) { if (c1 && c2) {
if (v1->type.t == VT_FLOAT) { if (bt == VT_FLOAT) {
f1 = v1->c.f; f1 = v1->c.f;
f2 = v2->c.f; f2 = v2->c.f;
} else if (v1->type.t == VT_DOUBLE) { } else if (bt == VT_DOUBLE) {
f1 = v1->c.d; f1 = v1->c.d;
f2 = v2->c.d; f2 = v2->c.d;
} else { } else {
@ -2533,41 +2534,39 @@ static void gen_opif(int op)
f1 = -f1; f1 = -f1;
goto unary_result; goto unary_result;
case TOK_EQ: case TOK_EQ:
f1 = f1 == f2; i = f1 == f2;
make_int: make_int:
cast_int = 1; vtop -= 2;
break; vpushi(i);
return;
case TOK_NE: case TOK_NE:
f1 = f1 != f2; i = f1 != f2;
goto make_int; goto make_int;
case TOK_LT: case TOK_LT:
f1 = f1 < f2; i = f1 < f2;
goto make_int; goto make_int;
case TOK_GE: case TOK_GE:
f1 = f1 >= f2; i = f1 >= f2;
goto make_int; goto make_int;
case TOK_LE: case TOK_LE:
f1 = f1 <= f2; i = f1 <= f2;
goto make_int; goto make_int;
case TOK_GT: case TOK_GT:
f1 = f1 > f2; i = f1 > f2;
goto make_int; goto make_int;
/* XXX: also handles tests ? */
default: default:
goto general_case; goto general_case;
} }
vtop--; vtop--;
unary_result: unary_result:
/* XXX: overflow test ? */ /* XXX: overflow test ? */
if (v1->type.t == VT_FLOAT) { if (bt == VT_FLOAT) {
v1->c.f = f1; v1->c.f = f1;
} else if (v1->type.t == VT_DOUBLE) { } else if (bt == VT_DOUBLE) {
v1->c.d = f1; v1->c.d = f1;
} else { } else {
v1->c.ld = f1; v1->c.ld = f1;
} }
if (cast_int)
gen_cast_s(VT_INT);
} else { } else {
general_case: general_case:
if (op == TOK_NEG) { if (op == TOK_NEG) {
@ -4029,10 +4028,18 @@ static Sym * find_field (CType *type, int v, int *cumofs)
{ {
Sym *s = type->ref; Sym *s = type->ref;
int v1 = v | SYM_FIELD; int v1 = v | SYM_FIELD;
if (!(v & SYM_FIELD)) { /* top-level call */
if ((type->t & VT_BTYPE) != VT_STRUCT)
expect("struct or union");
if (v < TOK_UIDENT)
expect("field name");
if (s->c < 0)
tcc_error("dereferencing incomplete type '%s'",
get_tok_str(s->v & ~SYM_STRUCT, 0));
}
while ((s = s->next) != NULL) { while ((s = s->next) != NULL) {
if (s->v == v1) { if (s->v == v1) {
*cumofs += s->c; *cumofs = s->c;
return s; return s;
} }
if ((s->type.t & VT_BTYPE) == VT_STRUCT if ((s->type.t & VT_BTYPE) == VT_STRUCT
@ -4045,17 +4052,9 @@ static Sym * find_field (CType *type, int v, int *cumofs)
} }
} }
} }
if (!(v & SYM_FIELD))
if (!(v & SYM_FIELD)) { /* top-level call */ tcc_error("field not found: %s", get_tok_str(v, NULL));
s = type->ref; return s;
if (s->c < 0)
tcc_error("dereferencing incomplete type '%s'",
get_tok_str(s->v & ~SYM_STRUCT, 0));
else
tcc_error("field not found: %s",
get_tok_str(v, &tokc));
}
return NULL;
} }
static void check_fields (CType *type, int check) static void check_fields (CType *type, int check)
@ -6003,21 +6002,15 @@ special_math_val:
if (tok == TOK_INC || tok == TOK_DEC) { if (tok == TOK_INC || tok == TOK_DEC) {
inc(1, tok); inc(1, tok);
next(); next();
} else if (tok == '.' || tok == TOK_ARROW || tok == TOK_CDOUBLE) { } else if (tok == '.' || tok == TOK_ARROW) {
int qualifiers, cumofs = 0; int qualifiers, cumofs;
/* field */ /* field */
if (tok == TOK_ARROW) if (tok == TOK_ARROW)
indir(); indir();
qualifiers = vtop->type.t & (VT_CONSTANT | VT_VOLATILE); qualifiers = vtop->type.t & (VT_CONSTANT | VT_VOLATILE);
test_lvalue(); test_lvalue();
/* expect pointer on structure */ /* expect pointer on structure */
if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
expect("struct or union");
if (tok == TOK_CDOUBLE)
expect("field name");
next(); next();
if (tok == TOK_CINT || tok == TOK_CUINT)
expect("field name");
s = find_field(&vtop->type, tok, &cumofs); s = find_field(&vtop->type, tok, &cumofs);
/* add field offset to pointer */ /* add field offset to pointer */
gaddrof(); gaddrof();
@ -7494,9 +7487,6 @@ static int decl_designator(init_params *p, CType *type, unsigned long c,
l = tok; l = tok;
struct_field: struct_field:
next(); next();
if ((type->t & VT_BTYPE) != VT_STRUCT)
expect("struct/union type");
cumofs = 0;
f = find_field(type, l, &cumofs); f = find_field(type, l, &cumofs);
if (cur_field) if (cur_field)
*cur_field = f; *cur_field = f;

View File

@ -1457,7 +1457,10 @@ static int expr_preprocess(TCCState *s1)
while (tok != TOK_LINEFEED && tok != TOK_EOF) { while (tok != TOK_LINEFEED && tok != TOK_EOF) {
next(); /* do macro subst */ next(); /* do macro subst */
redo: redo:
if (tok == TOK_DEFINED) { if (tok < TOK_IDENT) {
if (tok >= TOK_STR && tok <= TOK_CLDOUBLE)
tcc_error("invalid constant in preprocessor expression");
} else if (tok == TOK_DEFINED) {
next_nomacro(); next_nomacro();
t = tok; t = tok;
if (t == '(') if (t == '(')
@ -1489,7 +1492,7 @@ static int expr_preprocess(TCCState *s1)
expect("')'"); expect("')'");
tok = TOK_CINT; tok = TOK_CINT;
tokc.i = c; tokc.i = c;
} else if (tok >= TOK_IDENT) { } else {
/* if undefined macro, replace with zero, check for func-like */ /* if undefined macro, replace with zero, check for func-like */
t = tok; t = tok;
tok = TOK_CINT; tok = TOK_CINT;

View File

@ -209,9 +209,8 @@ TF_TYPE(thread_test_complex, vn)
sleep_ms(2); sleep_ms(2);
ret = tcc_add_file(s, argv[0]); ret = tcc_add_file(s, argv[0]);
sleep_ms(3); sleep_ms(3);
if (ret < 0) if (ret == 0)
exit(1); tcc_run(s, argc, argv);
tcc_run(s, argc, argv);
tcc_delete(s); tcc_delete(s);
fflush(stdout); fflush(stdout);
return 0; return 0;

0
win32/include/uchar.h Executable file → Normal file
View File