better external allocs handling
This commit is contained in:
232
tcc.c
232
tcc.c
@ -71,6 +71,17 @@ typedef struct SymStack {
|
|||||||
struct Sym *hash[SYM_HASH_SIZE];
|
struct Sym *hash[SYM_HASH_SIZE];
|
||||||
} SymStack;
|
} SymStack;
|
||||||
|
|
||||||
|
/* relocation entry (currently only used for functions or variables */
|
||||||
|
typedef struct Reloc {
|
||||||
|
int type; /* type of relocation */
|
||||||
|
int addr; /* address of relocation */
|
||||||
|
struct Reloc *next; /* next relocation */
|
||||||
|
} Reloc;
|
||||||
|
|
||||||
|
#define RELOC_ADDR32 1 /* 32 bits relocation */
|
||||||
|
#define RELOC_REL32 2 /* 32 bits relative relocation */
|
||||||
|
|
||||||
|
|
||||||
#define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
|
#define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
|
||||||
#define SYM_FIELD 0x20000000 /* struct/union field symbol space */
|
#define SYM_FIELD 0x20000000 /* struct/union field symbol space */
|
||||||
|
|
||||||
@ -144,13 +155,15 @@ int nb_include_paths;
|
|||||||
#define VT_ENUM 0x00800 /* enum definition */
|
#define VT_ENUM 0x00800 /* enum definition */
|
||||||
#define VT_FUNC 0x01000 /* function type */
|
#define VT_FUNC 0x01000 /* function type */
|
||||||
#define VT_STRUCT 0x002000 /* struct/union definition */
|
#define VT_STRUCT 0x002000 /* struct/union definition */
|
||||||
#define VT_TYPEDEF 0x004000 /* typedef definition */
|
#define VT_SHORT 0x004000 /* short type */
|
||||||
#define VT_EXTERN 0x008000 /* extern definition */
|
|
||||||
#define VT_STATIC 0x010000 /* static variable */
|
|
||||||
#define VT_SHORT 0x020000 /* short type */
|
|
||||||
#define VT_STRUCT_SHIFT 18 /* structure/enum name shift (14 bits left) */
|
#define VT_STRUCT_SHIFT 18 /* structure/enum name shift (14 bits left) */
|
||||||
|
|
||||||
#define VT_TYPE 0xffffffc0 /* type mask */
|
/* storage */
|
||||||
|
#define VT_EXTERN 0x00008000 /* extern definition */
|
||||||
|
#define VT_STATIC 0x00010000 /* static variable */
|
||||||
|
#define VT_TYPEDEF 0x00020000 /* typedef definition */
|
||||||
|
|
||||||
|
#define VT_TYPE 0xfffc7fc0 /* type mask */
|
||||||
#define VT_TYPEN 0x0000003f /* ~VT_TYPE */
|
#define VT_TYPEN 0x0000003f /* ~VT_TYPE */
|
||||||
#define VT_FUNCN -4097 /* ~VT_FUNC */
|
#define VT_FUNCN -4097 /* ~VT_FUNC */
|
||||||
|
|
||||||
@ -269,12 +282,12 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void sum();
|
void sum();
|
||||||
void next();
|
void next(void);
|
||||||
void next_nomacro();
|
void next_nomacro();
|
||||||
int expr_const();
|
int expr_const();
|
||||||
void expr_eq();
|
void expr_eq();
|
||||||
void expr();
|
void expr(void);
|
||||||
void decl();
|
void decl(int l);
|
||||||
void decl_initializer(int t, int c, int first, int size_only);
|
void decl_initializer(int t, int c, int first, int size_only);
|
||||||
int decl_initializer_alloc(int t, int has_init);
|
int decl_initializer_alloc(int t, int has_init);
|
||||||
int gv(void);
|
int gv(void);
|
||||||
@ -1450,12 +1463,12 @@ typedef struct GFuncContext {
|
|||||||
int args_size;
|
int args_size;
|
||||||
} GFuncContext;
|
} GFuncContext;
|
||||||
|
|
||||||
void g(c)
|
void g(int c)
|
||||||
{
|
{
|
||||||
*(char *)ind++ = c;
|
*(char *)ind++ = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void o(c)
|
void o(int c)
|
||||||
{
|
{
|
||||||
while (c) {
|
while (c) {
|
||||||
g(c);
|
g(c);
|
||||||
@ -1463,6 +1476,49 @@ void o(c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gen_le32(int c)
|
||||||
|
{
|
||||||
|
g(c);
|
||||||
|
g(c >> 8);
|
||||||
|
g(c >> 16);
|
||||||
|
g(c >> 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add a new relocation entry to symbol 's' */
|
||||||
|
void greloc(Sym *s, int addr, int type)
|
||||||
|
{
|
||||||
|
Reloc *p;
|
||||||
|
p = malloc(sizeof(Reloc));
|
||||||
|
if (!p)
|
||||||
|
error("memory full");
|
||||||
|
p->type = type;
|
||||||
|
p->addr = addr;
|
||||||
|
p->next = (Reloc *)s->c;
|
||||||
|
s->c = (int)p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* patch each relocation entry with value 'val' */
|
||||||
|
void greloc_patch(Sym *s, int val)
|
||||||
|
{
|
||||||
|
Reloc *p, *p1;
|
||||||
|
|
||||||
|
p = (Reloc *)s->c;
|
||||||
|
while (p != NULL) {
|
||||||
|
p1 = p->next;
|
||||||
|
switch(p->type) {
|
||||||
|
case RELOC_ADDR32:
|
||||||
|
*(int *)p->addr = val;
|
||||||
|
break;
|
||||||
|
case RELOC_REL32:
|
||||||
|
*(int *)p->addr = val - p->addr - 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(p);
|
||||||
|
p = p1;
|
||||||
|
}
|
||||||
|
s->c = val;
|
||||||
|
}
|
||||||
|
|
||||||
/* output a symbol and patch all calls to it */
|
/* output a symbol and patch all calls to it */
|
||||||
void gsym_addr(t, a)
|
void gsym_addr(t, a)
|
||||||
{
|
{
|
||||||
@ -1484,7 +1540,7 @@ void gsym(t)
|
|||||||
#define psym oad
|
#define psym oad
|
||||||
|
|
||||||
/* instruction + 4 bytes data. Return the address of the data */
|
/* instruction + 4 bytes data. Return the address of the data */
|
||||||
int oad(c, s)
|
int oad(int c, int s)
|
||||||
{
|
{
|
||||||
o(c);
|
o(c);
|
||||||
*(int *)ind = s;
|
*(int *)ind = s;
|
||||||
@ -1493,6 +1549,17 @@ int oad(c, s)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* output constant with relocation if 't & VT_FORWARD' is true */
|
||||||
|
void gen_addr32(int c, int t)
|
||||||
|
{
|
||||||
|
if (!(t & VT_FORWARD)) {
|
||||||
|
gen_le32(c);
|
||||||
|
} else {
|
||||||
|
greloc((Sym *)c, ind, RELOC_ADDR32);
|
||||||
|
gen_le32(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* XXX: generate correct pointer for forward references to functions */
|
/* XXX: generate correct pointer for forward references to functions */
|
||||||
/* r = (ft, fc) */
|
/* r = (ft, fc) */
|
||||||
void load(r, ft, fc)
|
void load(r, ft, fc)
|
||||||
@ -1516,7 +1583,8 @@ void load(r, ft, fc)
|
|||||||
else
|
else
|
||||||
o(0x8b); /* movl */
|
o(0x8b); /* movl */
|
||||||
if (v == VT_CONST) {
|
if (v == VT_CONST) {
|
||||||
oad(0x05 + r * 8, fc); /* 0xXX, r */
|
o(0x05 + r * 8); /* 0xXX, r */
|
||||||
|
gen_addr32(fc, ft);
|
||||||
} else if (v == VT_LOCAL) {
|
} else if (v == VT_LOCAL) {
|
||||||
oad(0x85 + r * 8, fc); /* xx(%ebp), r */
|
oad(0x85 + r * 8, fc); /* xx(%ebp), r */
|
||||||
} else {
|
} else {
|
||||||
@ -1524,7 +1592,8 @@ void load(r, ft, fc)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (v == VT_CONST) {
|
if (v == VT_CONST) {
|
||||||
oad(0xb8 + r, fc); /* mov $xx, r */
|
o(0xb8 + r); /* mov $xx, r */
|
||||||
|
gen_addr32(fc, ft);
|
||||||
} else if (v == VT_LOCAL) {
|
} else if (v == VT_LOCAL) {
|
||||||
o(0x8d);
|
o(0x8d);
|
||||||
oad(0x85 + r * 8, fc); /* lea xxx(%ebp), r */
|
oad(0x85 + r * 8, fc); /* lea xxx(%ebp), r */
|
||||||
@ -1559,7 +1628,8 @@ void store(r, ft, fc)
|
|||||||
o(0x66);
|
o(0x66);
|
||||||
o(0x89 - b);
|
o(0x89 - b);
|
||||||
if (fr == VT_CONST) {
|
if (fr == VT_CONST) {
|
||||||
oad(0x05 + r * 8, fc); /* mov r,xxx */
|
o(0x05 + r * 8); /* mov r,xxx */
|
||||||
|
gen_addr32(fc, ft);
|
||||||
} else if (fr == VT_LOCAL) {
|
} else if (fr == VT_LOCAL) {
|
||||||
oad(0x85 + r * 8, fc); /* mov r,xxx(%ebp) */
|
oad(0x85 + r * 8, fc); /* mov r,xxx(%ebp) */
|
||||||
} else if (ft & VT_LVAL) {
|
} else if (ft & VT_LVAL) {
|
||||||
@ -1615,9 +1685,11 @@ void gfunc_call(GFuncContext *c, int ft, int fc)
|
|||||||
if (r == VT_CONST) {
|
if (r == VT_CONST) {
|
||||||
/* forward reference */
|
/* forward reference */
|
||||||
if (ft & VT_FORWARD) {
|
if (ft & VT_FORWARD) {
|
||||||
*(int *)fc = psym(0xe8, *(int *)fc);
|
greloc((Sym *)fc, ind + 1, RELOC_REL32);
|
||||||
} else
|
oad(0xe8, 0);
|
||||||
|
} else {
|
||||||
oad(0xe8, fc - ind - 5);
|
oad(0xe8, fc - ind - 5);
|
||||||
|
}
|
||||||
} else if (r == VT_LOCAL) {
|
} else if (r == VT_LOCAL) {
|
||||||
oad(0x95ff, fc); /* call *xxx(%ebp) */
|
oad(0x95ff, fc); /* call *xxx(%ebp) */
|
||||||
} else {
|
} else {
|
||||||
@ -2171,7 +2243,7 @@ void inc(post, c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* enum/struct/union declaration */
|
/* enum/struct/union declaration */
|
||||||
int struct_decl(u)
|
int struct_decl(int u)
|
||||||
{
|
{
|
||||||
int a, t, b, v, size, align, maxalign, c;
|
int a, t, b, v, size, align, maxalign, c;
|
||||||
Sym *s, *ss, **ps;
|
Sym *s, *ss, **ps;
|
||||||
@ -2428,27 +2500,19 @@ int type_decl(int *v, int t, int td)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* define a new external reference to a function 'v' of type 'u' */
|
/* define a new external reference to a function 'v' of type 'u' */
|
||||||
Sym *external_func(v, u)
|
Sym *external_sym(int v, int u)
|
||||||
{
|
{
|
||||||
int n;
|
|
||||||
Sym *s;
|
Sym *s;
|
||||||
s = sym_find(v);
|
s = sym_find(v);
|
||||||
if (!s) {
|
if (!s) {
|
||||||
n = (int)dlsym(0, get_tok_str(v, 0));
|
/* push forward reference */
|
||||||
if (n == 0) {
|
|
||||||
/* used to generate symbol list */
|
|
||||||
s = sym_push1(&global_stack,
|
s = sym_push1(&global_stack,
|
||||||
v, u | VT_CONST | VT_LVAL | VT_FORWARD, 0);
|
v, u | VT_CONST | VT_FORWARD, 0);
|
||||||
} else {
|
|
||||||
/* int f() */
|
|
||||||
s = sym_push1(&global_stack,
|
|
||||||
v, u | VT_CONST | VT_LVAL, n);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void indir()
|
void indir(void)
|
||||||
{
|
{
|
||||||
if (vt & VT_LVAL)
|
if (vt & VT_LVAL)
|
||||||
gv();
|
gv();
|
||||||
@ -2459,7 +2523,7 @@ void indir()
|
|||||||
vt |= VT_LVAL;
|
vt |= VT_LVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unary()
|
void unary(void)
|
||||||
{
|
{
|
||||||
int n, t, ft, fc, p, align, size;
|
int n, t, ft, fc, p, align, size;
|
||||||
Sym *s;
|
Sym *s;
|
||||||
@ -2523,6 +2587,11 @@ void unary()
|
|||||||
indir();
|
indir();
|
||||||
} else if (t == '&') {
|
} else if (t == '&') {
|
||||||
unary();
|
unary();
|
||||||
|
/* functions names must be treated as function pointers,
|
||||||
|
except for unary '&' and sizeof. Since we consider that
|
||||||
|
functions are not lvalues, we only have to handle it
|
||||||
|
there and in function calls. */
|
||||||
|
if (!(vt & VT_FUNC))
|
||||||
test_lvalue();
|
test_lvalue();
|
||||||
vt = mk_pointer(vt & VT_LVALN);
|
vt = mk_pointer(vt & VT_LVALN);
|
||||||
} else
|
} else
|
||||||
@ -2577,12 +2646,12 @@ void unary()
|
|||||||
p = anon_sym++;
|
p = anon_sym++;
|
||||||
sym_push1(&global_stack, p, 0, FUNC_OLD);
|
sym_push1(&global_stack, p, 0, FUNC_OLD);
|
||||||
/* int() function */
|
/* int() function */
|
||||||
s = external_func(t, VT_FUNC | (p << VT_STRUCT_SHIFT));
|
s = external_sym(t, VT_FUNC | (p << VT_STRUCT_SHIFT));
|
||||||
}
|
}
|
||||||
vset(s->t, s->c);
|
vset(s->t, s->c);
|
||||||
/* if forward reference, we must point to s->c */
|
/* if forward reference, we must point to s */
|
||||||
if (vt & VT_FORWARD)
|
if (vt & VT_FORWARD)
|
||||||
vc = (int)&s->c;
|
vc = (int)s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2632,8 +2701,16 @@ void unary()
|
|||||||
int rett, retc;
|
int rett, retc;
|
||||||
|
|
||||||
/* function call */
|
/* function call */
|
||||||
|
if (!(vt & VT_FUNC)) {
|
||||||
|
if ((vt & (VT_PTR | VT_ARRAY)) == VT_PTR) {
|
||||||
|
vt = pointed_type(vt);
|
||||||
if (!(vt & VT_FUNC))
|
if (!(vt & VT_FUNC))
|
||||||
|
goto error_func;
|
||||||
|
} else {
|
||||||
|
error_func:
|
||||||
expect("function type");
|
expect("function type");
|
||||||
|
}
|
||||||
|
}
|
||||||
/* get return type */
|
/* get return type */
|
||||||
s = sym_find((unsigned)vt >> VT_STRUCT_SHIFT);
|
s = sym_find((unsigned)vt >> VT_STRUCT_SHIFT);
|
||||||
|
|
||||||
@ -2725,6 +2802,30 @@ void unary()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check if types are compatible for assignation */
|
||||||
|
int same_types(int t1, int t2)
|
||||||
|
{
|
||||||
|
t1 &= VT_TYPE;
|
||||||
|
t2 &= VT_TYPE;
|
||||||
|
if (t1 & VT_PTR) {
|
||||||
|
/* XXX: zero test ? */
|
||||||
|
if (!(t2 & VT_PTR))
|
||||||
|
return 0;
|
||||||
|
t1 = pointed_type(t1);
|
||||||
|
t2 = pointed_type(t2);
|
||||||
|
/* void matches everything */
|
||||||
|
if (t1 == VT_VOID || t2 == VT_VOID)
|
||||||
|
return 1;
|
||||||
|
return same_types(t1, t2);
|
||||||
|
} else if (t1 & VT_STRUCT) {
|
||||||
|
return (t2 == t1);
|
||||||
|
} else {
|
||||||
|
/* XXX: not complete */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void uneq()
|
void uneq()
|
||||||
{
|
{
|
||||||
int t;
|
int t;
|
||||||
@ -2740,9 +2841,8 @@ void uneq()
|
|||||||
next();
|
next();
|
||||||
if (t == '=') {
|
if (t == '=') {
|
||||||
expr_eq();
|
expr_eq();
|
||||||
/* XXX: be more precise */
|
if (!same_types(vt, vstack_ptr[-2]))
|
||||||
if ((vt & VT_PTR) != (vstack_ptr[-2] & VT_PTR))
|
error("incompatible types");
|
||||||
warning("incompatible type");
|
|
||||||
} else {
|
} else {
|
||||||
vpush();
|
vpush();
|
||||||
expr_eq();
|
expr_eq();
|
||||||
@ -2919,6 +3019,7 @@ void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
|
|||||||
s = local_stack.top;
|
s = local_stack.top;
|
||||||
while (tok != '}') {
|
while (tok != '}') {
|
||||||
decl(VT_LOCAL);
|
decl(VT_LOCAL);
|
||||||
|
if (tok != '}')
|
||||||
block(bsym, csym, case_sym, def_sym, case_reg);
|
block(bsym, csym, case_sym, def_sym, case_reg);
|
||||||
}
|
}
|
||||||
/* pop locally defined symbols */
|
/* pop locally defined symbols */
|
||||||
@ -3002,6 +3103,7 @@ void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
|
|||||||
gsym_addr(c, d);
|
gsym_addr(c, d);
|
||||||
skip(')');
|
skip(')');
|
||||||
gsym(a);
|
gsym(a);
|
||||||
|
skip(';');
|
||||||
} else
|
} else
|
||||||
if (tok == TOK_SWITCH) {
|
if (tok == TOK_SWITCH) {
|
||||||
next();
|
next();
|
||||||
@ -3297,9 +3399,9 @@ void decl_initializer(int t, int c, int first, int size_only)
|
|||||||
/* patch type size if needed */
|
/* patch type size if needed */
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
s->c = array_length;
|
s->c = array_length;
|
||||||
} else if (t & VT_STRUCT) {
|
} else if ((t & VT_STRUCT) && tok == '{') {
|
||||||
/* XXX: union needs only one init */
|
/* XXX: union needs only one init */
|
||||||
skip('{');
|
next();
|
||||||
s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
|
s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
|
||||||
f = s->next;
|
f = s->next;
|
||||||
array_length = 0;
|
array_length = 0;
|
||||||
@ -3428,14 +3530,20 @@ int decl_initializer_alloc(int t, int has_init)
|
|||||||
|
|
||||||
|
|
||||||
/* 'l' is VT_LOCAL or VT_CONST to define default storage type */
|
/* 'l' is VT_LOCAL or VT_CONST to define default storage type */
|
||||||
void decl(l)
|
void decl(int l)
|
||||||
{
|
{
|
||||||
int *a, t, b, v, u, n, addr, has_init, size, align;
|
int *a, t, b, v, u, addr, has_init, size, align;
|
||||||
Sym *sym;
|
Sym *sym;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
b = ist();
|
b = ist();
|
||||||
if (!b) {
|
if (!b) {
|
||||||
|
/* skip redundant ';' */
|
||||||
|
/* XXX: find more elegant solution */
|
||||||
|
if (tok == ';') {
|
||||||
|
next();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
/* special test for old K&R protos without explicit int
|
/* special test for old K&R protos without explicit int
|
||||||
type. Only accepted when defining global data */
|
type. Only accepted when defining global data */
|
||||||
if (l == VT_LOCAL || tok < TOK_DEFINE)
|
if (l == VT_LOCAL || tok < TOK_DEFINE)
|
||||||
@ -3450,16 +3558,17 @@ void decl(l)
|
|||||||
while (1) { /* iterate thru each declaration */
|
while (1) { /* iterate thru each declaration */
|
||||||
t = type_decl(&v, b, TYPE_DIRECT);
|
t = type_decl(&v, b, TYPE_DIRECT);
|
||||||
if (tok == '{') {
|
if (tok == '{') {
|
||||||
|
if (l == VT_LOCAL)
|
||||||
|
error("cannot use local functions");
|
||||||
if (!(t & VT_FUNC))
|
if (!(t & VT_FUNC))
|
||||||
expect("function definition");
|
expect("function definition");
|
||||||
/* patch forward references */
|
/* patch forward references */
|
||||||
if ((sym = sym_find(v)) && (sym->t & VT_FORWARD)) {
|
if ((sym = sym_find(v)) && (sym->t & VT_FORWARD)) {
|
||||||
gsym(sym->c);
|
greloc_patch(sym, ind);
|
||||||
sym->c = ind;
|
sym->t = VT_CONST | t;
|
||||||
sym->t = VT_CONST | VT_LVAL | t;
|
|
||||||
} else {
|
} else {
|
||||||
/* put function address */
|
/* put function address */
|
||||||
sym_push1(&global_stack, v, VT_CONST | VT_LVAL | t, ind);
|
sym_push1(&global_stack, v, VT_CONST | t, ind);
|
||||||
}
|
}
|
||||||
funcname = get_tok_str(v, 0);
|
funcname = get_tok_str(v, 0);
|
||||||
/* push a dummy symbol to enable local sym storage */
|
/* push a dummy symbol to enable local sym storage */
|
||||||
@ -3516,21 +3625,15 @@ void decl(l)
|
|||||||
/* save typedefed type */
|
/* save typedefed type */
|
||||||
sym_push(v, t | VT_TYPEDEF, 0);
|
sym_push(v, t | VT_TYPEDEF, 0);
|
||||||
} else if (t & VT_FUNC) {
|
} else if (t & VT_FUNC) {
|
||||||
/* XXX: incorrect to flush, but needed while
|
|
||||||
waiting for function prototypes */
|
|
||||||
/* external function definition */
|
/* external function definition */
|
||||||
external_func(v, t);
|
external_sym(v, t);
|
||||||
} else {
|
} else {
|
||||||
/* not lvalue if array */
|
/* not lvalue if array */
|
||||||
if (!(t & VT_ARRAY))
|
if (!(t & VT_ARRAY))
|
||||||
t |= VT_LVAL;
|
t |= VT_LVAL;
|
||||||
if (b & VT_EXTERN) {
|
if (b & VT_EXTERN) {
|
||||||
/* external variable */
|
/* external variable */
|
||||||
/* XXX: factorize with external function def */
|
external_sym(v, t);
|
||||||
n = (int)dlsym(NULL, get_tok_str(v, 0));
|
|
||||||
if (!n)
|
|
||||||
error("unknown external variable");
|
|
||||||
sym_push(v, VT_CONST | t, n);
|
|
||||||
} else {
|
} else {
|
||||||
u = l;
|
u = l;
|
||||||
if (t & VT_STATIC)
|
if (t & VT_STATIC)
|
||||||
@ -3566,6 +3669,30 @@ void open_dll(char *libname)
|
|||||||
error((char *)dlerror());
|
error((char *)dlerror());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reloc_external_syms(void)
|
||||||
|
{
|
||||||
|
Sym *s, *s1;
|
||||||
|
char *str;
|
||||||
|
int addr;
|
||||||
|
|
||||||
|
s = global_stack.top;
|
||||||
|
while (s != NULL) {
|
||||||
|
s1 = s->prev;
|
||||||
|
if (s->t & VT_FORWARD) {
|
||||||
|
/* if there is at least one relocation to do, then find it
|
||||||
|
and patch it */
|
||||||
|
if (s->c) {
|
||||||
|
str = get_tok_str(s->v, 0);
|
||||||
|
addr = (int)dlsym(NULL, str);
|
||||||
|
if (!addr)
|
||||||
|
error("unresolved external reference '%s'", str);
|
||||||
|
greloc_patch(s, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s = s1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* output a binary file (for testing) */
|
/* output a binary file (for testing) */
|
||||||
void build_exe(char *filename)
|
void build_exe(char *filename)
|
||||||
{
|
{
|
||||||
@ -3658,6 +3785,7 @@ int main(int argc, char **argv)
|
|||||||
decl(VT_CONST);
|
decl(VT_CONST);
|
||||||
if (tok != -1)
|
if (tok != -1)
|
||||||
expect("declaration");
|
expect("declaration");
|
||||||
|
reloc_external_syms();
|
||||||
if (outfile) {
|
if (outfile) {
|
||||||
build_exe(outfile);
|
build_exe(outfile);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user