mirror of
https://github.com/frida/tinycc
synced 2024-12-25 22:46:49 +03:00
Fix more attribute placements
when parsing the type in this cast: (int (__attribute__(X) *)(int))foo we ignored the attribute, which matters if it's e.g. a 'stdcall' attribute on the function pointer. Only this particular placement was misparsed. Putting the attribute after the '*' or outside the inner parens worked. This idiom seems to be used on SQLite, perhaps this fixes a compilation problem on win32 with that.
This commit is contained in:
parent
325241c0de
commit
3e007193a2
77
tccgen.c
77
tccgen.c
@ -846,6 +846,52 @@ ST_FUNC Sym *external_global_sym(int v, CType *type, int r)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Merge symbol attributes. */
|
||||||
|
static void merge_symattr(struct SymAttr *sa, struct SymAttr *sa1)
|
||||||
|
{
|
||||||
|
if (sa1->aligned && !sa->aligned)
|
||||||
|
sa->aligned = sa1->aligned;
|
||||||
|
sa->packed |= sa1->packed;
|
||||||
|
sa->weak |= sa1->weak;
|
||||||
|
if (sa1->visibility != STV_DEFAULT) {
|
||||||
|
int vis = sa->visibility;
|
||||||
|
if (vis == STV_DEFAULT
|
||||||
|
|| vis > sa1->visibility)
|
||||||
|
vis = sa1->visibility;
|
||||||
|
sa->visibility = vis;
|
||||||
|
}
|
||||||
|
sa->dllexport |= sa1->dllexport;
|
||||||
|
sa->nodecorate |= sa1->nodecorate;
|
||||||
|
sa->dllimport |= sa1->dllimport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Merge function attributes. */
|
||||||
|
static void merge_funcattr(struct FuncAttr *fa, struct FuncAttr *fa1)
|
||||||
|
{
|
||||||
|
if (fa1->func_call && !fa->func_call)
|
||||||
|
fa->func_call = fa1->func_call;
|
||||||
|
if (fa1->func_type && !fa->func_type)
|
||||||
|
fa->func_type = fa1->func_type;
|
||||||
|
if (fa1->func_args && !fa->func_args)
|
||||||
|
fa->func_args = fa1->func_args;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Merge attributes. */
|
||||||
|
static void merge_attr(AttributeDef *ad, AttributeDef *ad1)
|
||||||
|
{
|
||||||
|
merge_symattr(&ad->a, &ad1->a);
|
||||||
|
merge_funcattr(&ad->f, &ad1->f);
|
||||||
|
|
||||||
|
if (ad1->section)
|
||||||
|
ad->section = ad1->section;
|
||||||
|
if (ad1->alias_target)
|
||||||
|
ad->alias_target = ad1->alias_target;
|
||||||
|
if (ad1->asm_label)
|
||||||
|
ad->asm_label = ad1->asm_label;
|
||||||
|
if (ad1->attr_mode)
|
||||||
|
ad->attr_mode = ad1->attr_mode;
|
||||||
|
}
|
||||||
|
|
||||||
/* Merge some type attributes. */
|
/* Merge some type attributes. */
|
||||||
static void patch_type(Sym *sym, CType *type)
|
static void patch_type(Sym *sym, CType *type)
|
||||||
{
|
{
|
||||||
@ -905,20 +951,8 @@ static void patch_storage(Sym *sym, AttributeDef *ad, CType *type)
|
|||||||
if (sym->a.dllimport != ad->a.dllimport)
|
if (sym->a.dllimport != ad->a.dllimport)
|
||||||
tcc_error("incompatible dll linkage for redefinition of '%s'",
|
tcc_error("incompatible dll linkage for redefinition of '%s'",
|
||||||
get_tok_str(sym->v, NULL));
|
get_tok_str(sym->v, NULL));
|
||||||
sym->a.dllexport |= ad->a.dllexport;
|
|
||||||
#endif
|
#endif
|
||||||
sym->a.weak |= ad->a.weak;
|
merge_symattr(&sym->a, &ad->a);
|
||||||
if (ad->a.visibility) {
|
|
||||||
int vis = sym->a.visibility;
|
|
||||||
int vis2 = ad->a.visibility;
|
|
||||||
if (vis == STV_DEFAULT)
|
|
||||||
vis = vis2;
|
|
||||||
else if (vis2 != STV_DEFAULT)
|
|
||||||
vis = (vis < vis2) ? vis : vis2;
|
|
||||||
sym->a.visibility = vis;
|
|
||||||
}
|
|
||||||
if (ad->a.aligned)
|
|
||||||
sym->a.aligned = ad->a.aligned;
|
|
||||||
if (ad->asm_label)
|
if (ad->asm_label)
|
||||||
sym->asm_label = ad->asm_label;
|
sym->asm_label = ad->asm_label;
|
||||||
update_storage(sym);
|
update_storage(sym);
|
||||||
@ -4000,14 +4034,8 @@ do_decl:
|
|||||||
|
|
||||||
static void sym_to_attr(AttributeDef *ad, Sym *s)
|
static void sym_to_attr(AttributeDef *ad, Sym *s)
|
||||||
{
|
{
|
||||||
if (s->a.aligned && 0 == ad->a.aligned)
|
merge_symattr(&ad->a, &s->a);
|
||||||
ad->a.aligned = s->a.aligned;
|
merge_funcattr(&ad->f, &s->f);
|
||||||
if (s->f.func_call && 0 == ad->f.func_call)
|
|
||||||
ad->f.func_call = s->f.func_call;
|
|
||||||
if (s->f.func_type && 0 == ad->f.func_type)
|
|
||||||
ad->f.func_type = s->f.func_type;
|
|
||||||
if (s->a.packed)
|
|
||||||
ad->a.packed = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add type qualifiers to a type. If the type is an array then the qualifiers
|
/* Add type qualifiers to a type. If the type is an array then the qualifiers
|
||||||
@ -4294,9 +4322,10 @@ static int post_type(CType *type, AttributeDef *ad, int storage, int td)
|
|||||||
l = 0;
|
l = 0;
|
||||||
else if (parse_btype(&pt, &ad1))
|
else if (parse_btype(&pt, &ad1))
|
||||||
l = FUNC_NEW;
|
l = FUNC_NEW;
|
||||||
else if (td)
|
else if (td) {
|
||||||
return 0;
|
merge_attr (ad, &ad1);
|
||||||
else
|
return 0;
|
||||||
|
} else
|
||||||
l = FUNC_OLD;
|
l = FUNC_OLD;
|
||||||
first = NULL;
|
first = NULL;
|
||||||
plast = &first;
|
plast = &first;
|
||||||
|
2
tccpe.c
2
tccpe.c
@ -1747,7 +1747,7 @@ ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd)
|
|||||||
ret = pe_load_def(s1, fd);
|
ret = pe_load_def(s1, fd);
|
||||||
else if (pe_load_res(s1, fd) == 0)
|
else if (pe_load_res(s1, fd) == 0)
|
||||||
ret = 0;
|
ret = 0;
|
||||||
else if (read_mem(fd, 0, buf, 4) && 0 == memcmp(buf, "MZ\220", 4))
|
else if (read_mem(fd, 0, buf, 4) && 0 == memcmp(buf, "MZ", 2))
|
||||||
ret = pe_load_dll(s1, filename);
|
ret = pe_load_dll(s1, filename);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,13 @@ void __attribute__((stdcall)) foo (void)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define __stdcall __attribute__((stdcall))
|
||||||
|
extern int some_stdcall_func (int, int, int) __stdcall;
|
||||||
|
__stdcall int __stdcall some_stdcall_func(int foo, int bar, int baz) {
|
||||||
|
//printf("Hello from stdcall: %i %i %i\n", foo, bar, baz);
|
||||||
|
return 43;
|
||||||
|
}
|
||||||
|
|
||||||
/* The actual attribute isn't important, must just be
|
/* The actual attribute isn't important, must just be
|
||||||
parsable. */
|
parsable. */
|
||||||
#define ATTR __attribute__((__noinline__))
|
#define ATTR __attribute__((__noinline__))
|
||||||
@ -24,9 +31,11 @@ int ATTR actual_function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern int printf (const char *, ...);
|
extern int printf (const char *, ...);
|
||||||
|
static int globalvar;
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
void *function_pointer = &actual_function;
|
void *function_pointer = &actual_function;
|
||||||
|
int localvar = 42, i;
|
||||||
|
|
||||||
int a = ((ATTR int(*) (void)) function_pointer)();
|
int a = ((ATTR int(*) (void)) function_pointer)();
|
||||||
printf("%i\n", a);
|
printf("%i\n", a);
|
||||||
@ -36,5 +45,21 @@ int main()
|
|||||||
int b = ( (int(ATTR *)(void)) function_pointer)();
|
int b = ( (int(ATTR *)(void)) function_pointer)();
|
||||||
printf("%i\n", b);
|
printf("%i\n", b);
|
||||||
|
|
||||||
|
/* All these should work and leave the stack pointer in its original
|
||||||
|
position. */
|
||||||
|
some_stdcall_func(1, 10, 100);
|
||||||
|
((int __stdcall (*)(int, int, int))some_stdcall_func) (2, 20, 200);
|
||||||
|
((int(*__stdcall)(int, int, int))some_stdcall_func) (3, 30, 300);
|
||||||
|
for (i = 0; i < 1024; i++) {
|
||||||
|
globalvar = i;
|
||||||
|
/* This was once misparsed at <= gitrev 325241c0, forgetting
|
||||||
|
the stdcall attribute on the function pointer leading to
|
||||||
|
stack increment being done twice (in callee and caller).
|
||||||
|
This will clobber 'i' and 'localvar' which is how we detect
|
||||||
|
this. */
|
||||||
|
((int(__stdcall*)(int, int, int))some_stdcall_func) (4, 40, 400);
|
||||||
|
if (localvar != 42 || globalvar != i)
|
||||||
|
printf("error, localvar=%d i=%d globalvar=%d\n", localvar, i, globalvar);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user