use data_offset in sections instead of pointer to ease section reallocation - relocated .stabs and .bounds sections - fixed char constants casts - fixed implicit cast to unary plus - fixed type for string constants
This commit is contained in:
parent
540cd6fde7
commit
9b48237795
1 changed files with 222 additions and 154 deletions
376
tcc.c
376
tcc.c
|
@ -135,8 +135,8 @@ typedef struct SymStack {
|
||||||
#define SHF_PRIVATE 0x80000000
|
#define SHF_PRIVATE 0x80000000
|
||||||
|
|
||||||
typedef struct Section {
|
typedef struct Section {
|
||||||
unsigned char *data; /* section data */
|
unsigned long data_offset; /* current data offset */
|
||||||
unsigned char *data_ptr; /* current data pointer */
|
unsigned char *data; /* section data */
|
||||||
int sh_name; /* elf section name (only used during output) */
|
int sh_name; /* elf section name (only used during output) */
|
||||||
int sh_num; /* elf section number */
|
int sh_num; /* elf section number */
|
||||||
int sh_type; /* elf section type */
|
int sh_type; /* elf section type */
|
||||||
|
@ -197,7 +197,7 @@ typedef struct BufferedFile {
|
||||||
unsigned char *buf_end;
|
unsigned char *buf_end;
|
||||||
int fd;
|
int fd;
|
||||||
int line_num; /* current line number - here to simply code */
|
int line_num; /* current line number - here to simply code */
|
||||||
char filename[1024]; /* current filename - here to simply code */
|
char filename[1024]; /* current filename - here to simplify code */
|
||||||
unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
|
unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
|
||||||
} BufferedFile;
|
} BufferedFile;
|
||||||
|
|
||||||
|
@ -337,7 +337,7 @@ struct TCCState {
|
||||||
#define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
|
#define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
|
||||||
|
|
||||||
/* types */
|
/* types */
|
||||||
#define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
|
#define VT_STRUCT_SHIFT 12 /* structure/enum name shift (20 bits left) */
|
||||||
|
|
||||||
#define VT_INT 0 /* integer type */
|
#define VT_INT 0 /* integer type */
|
||||||
#define VT_BYTE 1 /* signed byte type */
|
#define VT_BYTE 1 /* signed byte type */
|
||||||
|
@ -594,6 +594,8 @@ static Sym *get_sym_ref(int t, Section *sec,
|
||||||
unsigned long offset, unsigned long size);
|
unsigned long offset, unsigned long size);
|
||||||
|
|
||||||
/* section generation */
|
/* section generation */
|
||||||
|
static void *section_ptr(Section *sec, unsigned long size);
|
||||||
|
static void *section_ptr_add(Section *sec, unsigned long size);
|
||||||
void put_extern_sym(Sym *sym, Section *section, unsigned long value);
|
void put_extern_sym(Sym *sym, Section *section, unsigned long value);
|
||||||
void greloc(Section *s, Sym *sym, unsigned long addr, int type);
|
void greloc(Section *s, Sym *sym, unsigned long addr, int type);
|
||||||
static int put_elf_str(Section *s, const char *sym);
|
static int put_elf_str(Section *s, const char *sym);
|
||||||
|
@ -602,7 +604,10 @@ static int put_elf_sym(Section *s,
|
||||||
int info, int other, int shndx, const char *name);
|
int info, int other, int shndx, const char *name);
|
||||||
static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
|
static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
|
||||||
int type, int symbol);
|
int type, int symbol);
|
||||||
static void put_stabs(const char *str, int type, int other, int desc, int value);
|
static void put_stabs(const char *str, int type, int other, int desc,
|
||||||
|
unsigned long value);
|
||||||
|
static void put_stabs_r(const char *str, int type, int other, int desc,
|
||||||
|
unsigned long value, Section *sec, int sym_index);
|
||||||
static void put_stabn(int type, int other, int desc, int value);
|
static void put_stabn(int type, int other, int desc, int value);
|
||||||
static void put_stabd(int type, int other, int desc);
|
static void put_stabd(int type, int other, int desc);
|
||||||
static int tcc_add_dll(TCCState *s, const char *filename, int flags);
|
static int tcc_add_dll(TCCState *s, const char *filename, int flags);
|
||||||
|
@ -777,7 +782,7 @@ Section *new_section(const char *name, int sh_type, int sh_flags)
|
||||||
error("could not mmap section '%s'", name);
|
error("could not mmap section '%s'", name);
|
||||||
#endif
|
#endif
|
||||||
sec->data = data;
|
sec->data = data;
|
||||||
sec->data_ptr = data;
|
sec->data_offset = 0;
|
||||||
|
|
||||||
/* only add section if not private */
|
/* only add section if not private */
|
||||||
if (!(sh_flags & SHF_PRIVATE)) {
|
if (!(sh_flags & SHF_PRIVATE)) {
|
||||||
|
@ -787,6 +792,20 @@ Section *new_section(const char *name, int sh_type, int sh_flags)
|
||||||
return sec;
|
return sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* reserve at least 'size' bytes in section 'sec' from sec->data_offset */
|
||||||
|
static void *section_ptr(Section *sec, unsigned long size)
|
||||||
|
{
|
||||||
|
return sec->data + sec->data_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *section_ptr_add(Section *sec, unsigned long size)
|
||||||
|
{
|
||||||
|
void *ptr;
|
||||||
|
ptr = sec->data + sec->data_offset;
|
||||||
|
sec->data_offset += size;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
/* return a reference to a section, and create it if it does not
|
/* return a reference to a section, and create it if it does not
|
||||||
exists */
|
exists */
|
||||||
Section *find_section(const char *name)
|
Section *find_section(const char *name)
|
||||||
|
@ -1668,7 +1687,7 @@ void preprocess(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read a number in base b */
|
/* read a number in base b */
|
||||||
int getn(b)
|
static int getn(int b)
|
||||||
{
|
{
|
||||||
int n, t;
|
int n, t;
|
||||||
n = 0;
|
n = 0;
|
||||||
|
@ -1690,7 +1709,7 @@ int getn(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read a character for string or char constant and eval escape codes */
|
/* read a character for string or char constant and eval escape codes */
|
||||||
int getq()
|
static int getq(void)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
|
@ -2094,7 +2113,11 @@ void next_nomacro1(void)
|
||||||
tok = TOK_CCHAR;
|
tok = TOK_CCHAR;
|
||||||
char_const:
|
char_const:
|
||||||
minp();
|
minp();
|
||||||
tokc.i = getq();
|
b = getq();
|
||||||
|
/* this cast is needed if >= 128 */
|
||||||
|
if (tok == TOK_CCHAR)
|
||||||
|
b = (char)b;
|
||||||
|
tokc.i = b;
|
||||||
if (ch != '\'')
|
if (ch != '\'')
|
||||||
expect("\'");
|
expect("\'");
|
||||||
minp();
|
minp();
|
||||||
|
@ -2718,7 +2741,7 @@ void gbound(void)
|
||||||
register value (such as structures). */
|
register value (such as structures). */
|
||||||
int gv(int rc)
|
int gv(int rc)
|
||||||
{
|
{
|
||||||
int r, r2, rc2, bit_pos, bit_size, size, align, i, data_offset;
|
int r, r2, rc2, bit_pos, bit_size, size, align, i;
|
||||||
unsigned long long ll;
|
unsigned long long ll;
|
||||||
|
|
||||||
/* NOTE: get_reg can modify vstack[] */
|
/* NOTE: get_reg can modify vstack[] */
|
||||||
|
@ -2739,27 +2762,28 @@ int gv(int rc)
|
||||||
(vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
|
(vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
|
||||||
int v;
|
int v;
|
||||||
Sym *sym;
|
Sym *sym;
|
||||||
|
int *ptr;
|
||||||
|
|
||||||
/* XXX: unify with initializers handling ? */
|
/* XXX: unify with initializers handling ? */
|
||||||
/* CPUs usually cannot use float constants, so we store them
|
/* CPUs usually cannot use float constants, so we store them
|
||||||
generically in data segment */
|
generically in data segment */
|
||||||
size = type_size(vtop->t, &align);
|
size = type_size(vtop->t, &align);
|
||||||
data_offset = data_section->data_ptr - data_section->data;
|
data_section->data_offset = (data_section->data_offset +
|
||||||
data_offset = (data_offset + align - 1) & -align;
|
align - 1) & -align;
|
||||||
/* XXX: not portable yet */
|
/* XXX: not portable yet */
|
||||||
|
ptr = section_ptr(data_section, size);
|
||||||
size = size >> 2;
|
size = size >> 2;
|
||||||
for(i=0;i<size;i++)
|
for(i=0;i<size;i++)
|
||||||
((int *)(data_section->data + data_offset))[i] = vtop->c.tab[i];
|
ptr[i] = vtop->c.tab[i];
|
||||||
|
|
||||||
v = anon_sym++;
|
v = anon_sym++;
|
||||||
sym = sym_push1(&global_stack, v, vtop->t | VT_STATIC, 0);
|
sym = sym_push1(&global_stack, v, vtop->t | VT_STATIC, 0);
|
||||||
sym->r = VT_CONST | VT_SYM;
|
sym->r = VT_CONST | VT_SYM;
|
||||||
put_extern_sym(sym, data_section, data_offset);
|
put_extern_sym(sym, data_section, data_section->data_offset);
|
||||||
|
|
||||||
vtop->r |= VT_LVAL | VT_SYM;
|
vtop->r |= VT_LVAL | VT_SYM;
|
||||||
vtop->c.sym = sym;
|
vtop->c.sym = sym;
|
||||||
data_offset += size << 2;
|
data_section->data_offset += size << 2;
|
||||||
data_section->data_ptr = data_section->data + data_offset;
|
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if (vtop->r & VT_MUSTBOUND)
|
if (vtop->r & VT_MUSTBOUND)
|
||||||
|
@ -4673,13 +4697,18 @@ void unary(void)
|
||||||
vsetc(VT_LDOUBLE, VT_CONST, &tokc);
|
vsetc(VT_LDOUBLE, VT_CONST, &tokc);
|
||||||
next();
|
next();
|
||||||
} else if (tok == TOK___FUNC__) {
|
} else if (tok == TOK___FUNC__) {
|
||||||
|
void *ptr;
|
||||||
|
int len;
|
||||||
/* special function name identifier */
|
/* special function name identifier */
|
||||||
/* generate (char *) type */
|
|
||||||
data_offset = data_section->data_ptr - data_section->data;
|
len = strlen(funcname) + 1;
|
||||||
vpush_ref(mk_pointer(VT_BYTE), data_section, data_offset);
|
/* generate char[len] type */
|
||||||
strcpy(data_section->data + data_offset, funcname);
|
t = VT_ARRAY | mk_pointer(VT_BYTE);
|
||||||
data_offset += strlen(funcname) + 1;
|
s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
|
||||||
data_section->data_ptr = data_section->data + data_offset;
|
s->c = len;
|
||||||
|
vpush_ref(t, data_section, data_section->data_offset);
|
||||||
|
ptr = section_ptr_add(data_section, len);
|
||||||
|
memcpy(ptr, funcname, len);
|
||||||
next();
|
next();
|
||||||
} else if (tok == TOK_LSTR) {
|
} else if (tok == TOK_LSTR) {
|
||||||
t = VT_INT;
|
t = VT_INT;
|
||||||
|
@ -4689,16 +4718,16 @@ void unary(void)
|
||||||
t = VT_BYTE;
|
t = VT_BYTE;
|
||||||
str_init:
|
str_init:
|
||||||
type_size(t, &align);
|
type_size(t, &align);
|
||||||
data_offset = data_section->data_ptr - data_section->data;
|
data_offset = data_section->data_offset;
|
||||||
data_offset = (data_offset + align - 1) & -align;
|
data_offset = (data_offset + align - 1) & -align;
|
||||||
fc = data_offset;
|
fc = data_offset;
|
||||||
/* we must declare it as an array first to use initializer parser */
|
/* we must declare it as an array first to use initializer parser */
|
||||||
t = VT_ARRAY | mk_pointer(t);
|
t = VT_ARRAY | mk_pointer(t);
|
||||||
decl_initializer(t, data_section, data_offset, 1, 0);
|
decl_initializer(t, data_section, data_offset, 1, 0);
|
||||||
data_offset += type_size(t, &align);
|
data_offset += type_size(t, &align);
|
||||||
/* put it as pointer */
|
/* XXX: is it correct to put it exactly as an array ? */
|
||||||
vpush_ref(t & ~VT_ARRAY, data_section, fc);
|
vpush_ref(t, data_section, fc);
|
||||||
data_section->data_ptr = data_section->data + data_offset;
|
data_section->data_offset = data_offset;
|
||||||
} else {
|
} else {
|
||||||
t = tok;
|
t = tok;
|
||||||
next();
|
next();
|
||||||
|
@ -4758,7 +4787,12 @@ void unary(void)
|
||||||
gen_op('^');
|
gen_op('^');
|
||||||
} else
|
} else
|
||||||
if (t == '+') {
|
if (t == '+') {
|
||||||
|
/* in order to force cast, we add zero */
|
||||||
unary();
|
unary();
|
||||||
|
if ((vtop->t & VT_BTYPE) == VT_PTR)
|
||||||
|
error("pointer not accepted for unary plus");
|
||||||
|
vpushi(0);
|
||||||
|
gen_op('+');
|
||||||
} else
|
} else
|
||||||
if (t == TOK_SIZEOF) {
|
if (t == TOK_SIZEOF) {
|
||||||
if (tok == '(') {
|
if (tok == '(') {
|
||||||
|
@ -5811,14 +5845,13 @@ void decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init,
|
||||||
/* XXX: currently, since we do only one pass, we cannot track
|
/* XXX: currently, since we do only one pass, we cannot track
|
||||||
'&' operators, so we add only arrays */
|
'&' operators, so we add only arrays */
|
||||||
if (do_bounds_check && (t & VT_ARRAY)) {
|
if (do_bounds_check && (t & VT_ARRAY)) {
|
||||||
int *bounds_ptr;
|
unsigned long *bounds_ptr;
|
||||||
/* add padding between regions */
|
/* add padding between regions */
|
||||||
loc--;
|
loc--;
|
||||||
/* then add local bound info */
|
/* then add local bound info */
|
||||||
bounds_ptr = (int *)lbounds_section->data_ptr;
|
bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
|
||||||
*bounds_ptr++ = addr;
|
bounds_ptr[0] = addr;
|
||||||
*bounds_ptr++ = size;
|
bounds_ptr[1] = size;
|
||||||
lbounds_section->data_ptr = (unsigned char *)bounds_ptr;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* compute section */
|
/* compute section */
|
||||||
|
@ -5829,33 +5862,29 @@ void decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init,
|
||||||
else
|
else
|
||||||
sec = bss_section;
|
sec = bss_section;
|
||||||
}
|
}
|
||||||
data_offset = sec->data_ptr - sec->data;
|
data_offset = sec->data_offset;
|
||||||
data_offset = (data_offset + align - 1) & -align;
|
data_offset = (data_offset + align - 1) & -align;
|
||||||
addr = data_offset;
|
addr = data_offset;
|
||||||
/* very important to increment global pointer at this time
|
/* very important to increment global pointer at this time
|
||||||
because initializers themselves can create new initializers */
|
because initializers themselves can create new initializers */
|
||||||
data_offset += size;
|
data_offset += size;
|
||||||
/* handles bounds */
|
/* add padding if bound check */
|
||||||
if (do_bounds_check) {
|
if (do_bounds_check)
|
||||||
int *bounds_ptr;
|
|
||||||
/* first, we need to add at least one byte between each region */
|
|
||||||
data_offset++;
|
data_offset++;
|
||||||
/* then add global bound info */
|
sec->data_offset = data_offset;
|
||||||
bounds_ptr = (int *)bounds_section->data_ptr;
|
|
||||||
/* XXX: add relocation */
|
|
||||||
*bounds_ptr++ = addr + (unsigned long)sec->data;
|
|
||||||
*bounds_ptr++ = size;
|
|
||||||
bounds_section->data_ptr = (unsigned char *)bounds_ptr;
|
|
||||||
}
|
|
||||||
sec->data_ptr = sec->data + data_offset;
|
|
||||||
}
|
}
|
||||||
if (v) {
|
if (!sec) {
|
||||||
Sym *sym;
|
if (v) {
|
||||||
|
|
||||||
if (!sec) {
|
|
||||||
/* local variable */
|
/* local variable */
|
||||||
sym_push(v, t, r, addr);
|
sym_push(v, t, r, addr);
|
||||||
} else {
|
} else {
|
||||||
|
/* push local reference */
|
||||||
|
vset(t, r, addr);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Sym *sym;
|
||||||
|
|
||||||
|
if (v) {
|
||||||
if (scope == VT_CONST) {
|
if (scope == VT_CONST) {
|
||||||
/* global scope: see if already defined */
|
/* global scope: see if already defined */
|
||||||
sym = sym_find(v);
|
sym = sym_find(v);
|
||||||
|
@ -5872,14 +5901,25 @@ void decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init,
|
||||||
sym = sym_push(v, t, r | VT_SYM, 0);
|
sym = sym_push(v, t, r | VT_SYM, 0);
|
||||||
}
|
}
|
||||||
put_extern_sym(sym, sec, addr);
|
put_extern_sym(sym, sec, addr);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!sec) {
|
|
||||||
/* push local reference */
|
|
||||||
vset(t, r, addr);
|
|
||||||
} else {
|
} else {
|
||||||
|
CValue cval;
|
||||||
|
|
||||||
/* push global reference */
|
/* push global reference */
|
||||||
vpush_ref(t, sec, addr);
|
sym = get_sym_ref(t, sec, addr, 0);
|
||||||
|
cval.sym = sym;
|
||||||
|
vsetc(t, VT_CONST | VT_SYM, &cval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* handles bounds now because the symbol must be defined
|
||||||
|
before for the relocation */
|
||||||
|
if (do_bounds_check) {
|
||||||
|
unsigned long *bounds_ptr;
|
||||||
|
|
||||||
|
greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
|
||||||
|
/* then add global bound info */
|
||||||
|
bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
|
||||||
|
bounds_ptr[0] = 0; /* relocated */
|
||||||
|
bounds_ptr[1] = size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (has_init) {
|
if (has_init) {
|
||||||
|
@ -5892,15 +5932,16 @@ void decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void put_func_debug(int t)
|
void put_func_debug(Sym *sym)
|
||||||
{
|
{
|
||||||
char buf[512];
|
char buf[512];
|
||||||
|
|
||||||
/* stabs info */
|
/* stabs info */
|
||||||
/* XXX: we put here a dummy type */
|
/* XXX: we put here a dummy type */
|
||||||
snprintf(buf, sizeof(buf), "%s:%c1",
|
snprintf(buf, sizeof(buf), "%s:%c1",
|
||||||
funcname, t & VT_STATIC ? 'f' : 'F');
|
funcname, sym->t & VT_STATIC ? 'f' : 'F');
|
||||||
put_stabs(buf, N_FUN, 0, file->line_num, ind);
|
put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
|
||||||
|
cur_text_section, sym->c);
|
||||||
func_ind = ind;
|
func_ind = ind;
|
||||||
last_ind = 0;
|
last_ind = 0;
|
||||||
last_line_num = 0;
|
last_line_num = 0;
|
||||||
|
@ -6049,7 +6090,7 @@ void decl(int l)
|
||||||
cur_text_section = ad.section;
|
cur_text_section = ad.section;
|
||||||
if (!cur_text_section)
|
if (!cur_text_section)
|
||||||
cur_text_section = text_section;
|
cur_text_section = text_section;
|
||||||
ind = (int)cur_text_section->data_ptr;
|
ind = cur_text_section->data_offset;
|
||||||
funcname = get_tok_str(v, NULL);
|
funcname = get_tok_str(v, NULL);
|
||||||
sym = sym_find(v);
|
sym = sym_find(v);
|
||||||
if (sym) {
|
if (sym) {
|
||||||
|
@ -6059,12 +6100,11 @@ void decl(int l)
|
||||||
/* put function symbol */
|
/* put function symbol */
|
||||||
sym = sym_push1(&global_stack, v, t, 0);
|
sym = sym_push1(&global_stack, v, t, 0);
|
||||||
}
|
}
|
||||||
put_extern_sym(sym, cur_text_section,
|
put_extern_sym(sym, cur_text_section, ind);
|
||||||
ind - (int)cur_text_section->data);
|
|
||||||
sym->r = VT_SYM | VT_CONST;
|
sym->r = VT_SYM | VT_CONST;
|
||||||
/* put debug symbol */
|
/* put debug symbol */
|
||||||
if (do_debug)
|
if (do_debug)
|
||||||
put_func_debug(t);
|
put_func_debug(sym);
|
||||||
/* push a dummy symbol to enable local sym storage */
|
/* push a dummy symbol to enable local sym storage */
|
||||||
sym_push1(&local_stack, 0, 0, 0);
|
sym_push1(&local_stack, 0, 0, 0);
|
||||||
gfunc_prolog(t);
|
gfunc_prolog(t);
|
||||||
|
@ -6077,7 +6117,7 @@ void decl(int l)
|
||||||
block(NULL, NULL, NULL, NULL, 0);
|
block(NULL, NULL, NULL, NULL, 0);
|
||||||
gsym(rsym);
|
gsym(rsym);
|
||||||
gfunc_epilog();
|
gfunc_epilog();
|
||||||
cur_text_section->data_ptr = (unsigned char *)ind;
|
cur_text_section->data_offset = ind;
|
||||||
sym_pop(&label_stack, NULL); /* reset label stack */
|
sym_pop(&label_stack, NULL); /* reset label stack */
|
||||||
sym_pop(&local_stack, NULL); /* reset local stack */
|
sym_pop(&local_stack, NULL); /* reset local stack */
|
||||||
/* end of function */
|
/* end of function */
|
||||||
|
@ -6136,7 +6176,7 @@ static int tcc_compile(TCCState *s)
|
||||||
{
|
{
|
||||||
Sym *define_start;
|
Sym *define_start;
|
||||||
char buf[512];
|
char buf[512];
|
||||||
int p;
|
int p, section_sym;
|
||||||
|
|
||||||
funcname = "";
|
funcname = "";
|
||||||
include_stack_ptr = include_stack;
|
include_stack_ptr = include_stack;
|
||||||
|
@ -6146,12 +6186,17 @@ static int tcc_compile(TCCState *s)
|
||||||
anon_sym = SYM_FIRST_ANOM;
|
anon_sym = SYM_FIRST_ANOM;
|
||||||
|
|
||||||
/* file info: full path + filename */
|
/* file info: full path + filename */
|
||||||
|
section_sym = 0; /* avoid warning */
|
||||||
if (do_debug) {
|
if (do_debug) {
|
||||||
|
section_sym = put_elf_sym(symtab_section, 0, 0,
|
||||||
|
ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
|
||||||
|
text_section->sh_num, NULL);
|
||||||
getcwd(buf, sizeof(buf));
|
getcwd(buf, sizeof(buf));
|
||||||
pstrcat(buf, sizeof(buf), "/");
|
pstrcat(buf, sizeof(buf), "/");
|
||||||
put_stabs(buf, N_SO, 0, 0, (unsigned long)text_section->data_ptr);
|
put_stabs_r(buf, N_SO, 0, 0,
|
||||||
put_stabs(file->filename, N_SO, 0, 0,
|
text_section->data_offset, text_section, section_sym);
|
||||||
(unsigned long)text_section->data_ptr);
|
put_stabs_r(file->filename, N_SO, 0, 0,
|
||||||
|
text_section->data_offset, text_section, section_sym);
|
||||||
}
|
}
|
||||||
/* an elf symbol of type STT_FILE must be put so that STB_LOCAL
|
/* an elf symbol of type STT_FILE must be put so that STB_LOCAL
|
||||||
symbols can be safely used */
|
symbols can be safely used */
|
||||||
|
@ -6177,7 +6222,8 @@ static int tcc_compile(TCCState *s)
|
||||||
|
|
||||||
/* end of translation unit info */
|
/* end of translation unit info */
|
||||||
if (do_debug) {
|
if (do_debug) {
|
||||||
put_stabn(N_SO, 0, 0, (unsigned long)text_section->data_ptr);
|
put_stabs_r(NULL, N_SO, 0, 0,
|
||||||
|
text_section->data_offset, text_section, section_sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reset define stack, but leave -Dsymbols (may be incorrect if
|
/* reset define stack, but leave -Dsymbols (may be incorrect if
|
||||||
|
@ -6251,14 +6297,13 @@ void tcc_undefine_symbol(TCCState *s1, const char *sym)
|
||||||
|
|
||||||
static int put_elf_str(Section *s, const char *sym)
|
static int put_elf_str(Section *s, const char *sym)
|
||||||
{
|
{
|
||||||
int c, offset;
|
int offset, len;
|
||||||
offset = s->data_ptr - s->data;
|
char *ptr;
|
||||||
for(;;) {
|
|
||||||
c = *sym++;
|
len = strlen(sym) + 1;
|
||||||
*s->data_ptr++ = c;
|
offset = s->data_offset;
|
||||||
if (c == '\0')
|
ptr = section_ptr_add(s, len);
|
||||||
break;
|
memcpy(ptr, sym, len);
|
||||||
}
|
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6287,7 +6332,7 @@ static int put_elf_sym(Section *s,
|
||||||
Elf32_Sym *sym;
|
Elf32_Sym *sym;
|
||||||
Section *hs;
|
Section *hs;
|
||||||
|
|
||||||
sym = (Elf32_Sym *)s->data_ptr;
|
sym = section_ptr_add(s, sizeof(Elf32_Sym));
|
||||||
if (name)
|
if (name)
|
||||||
name_offset = put_elf_str(s->link, name);
|
name_offset = put_elf_str(s->link, name);
|
||||||
else
|
else
|
||||||
|
@ -6302,19 +6347,21 @@ static int put_elf_sym(Section *s,
|
||||||
sym_index = sym - (Elf32_Sym *)s->data;
|
sym_index = sym - (Elf32_Sym *)s->data;
|
||||||
hs = s->hash;
|
hs = s->hash;
|
||||||
if (hs) {
|
if (hs) {
|
||||||
|
int *ptr;
|
||||||
|
ptr = section_ptr_add(hs, sizeof(int));
|
||||||
/* only add global or weak symbols */
|
/* only add global or weak symbols */
|
||||||
if (ELF32_ST_BIND(info) != STB_LOCAL) {
|
if (ELF32_ST_BIND(info) != STB_LOCAL) {
|
||||||
/* add another hashing entry */
|
/* add another hashing entry */
|
||||||
nbuckets = ((int *)hs->data)[0];
|
nbuckets = ((int *)hs->data)[0];
|
||||||
h = elf_hash(name) % nbuckets;
|
h = elf_hash(name) % nbuckets;
|
||||||
((int *)hs->data)[2 + nbuckets + sym_index] = ((int *)hs->data)[2 + h];
|
*ptr = ((int *)hs->data)[2 + h];
|
||||||
((int *)hs->data)[2 + h] = sym_index;
|
((int *)hs->data)[2 + h] = sym_index;
|
||||||
|
} else {
|
||||||
|
*ptr = 0;
|
||||||
}
|
}
|
||||||
/* but still add room for all symbols */
|
/* but still add room for all symbols */
|
||||||
((int *)hs->data)[1]++;
|
((int *)hs->data)[1]++;
|
||||||
hs->data_ptr += sizeof(int);
|
|
||||||
}
|
}
|
||||||
s->data_ptr += sizeof(Elf32_Sym);
|
|
||||||
return sym_index;
|
return sym_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6483,11 +6530,9 @@ static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
|
||||||
sr->sh_info = s->sh_num;
|
sr->sh_info = s->sh_num;
|
||||||
s->reloc = sr;
|
s->reloc = sr;
|
||||||
}
|
}
|
||||||
rel = (Elf32_Rel *)sr->data_ptr;
|
rel = section_ptr_add(sr, sizeof(Elf32_Rel));
|
||||||
/* XXX: endianness */
|
|
||||||
rel->r_offset = offset;
|
rel->r_offset = offset;
|
||||||
rel->r_info = ELF32_R_INFO(symbol, type);
|
rel->r_info = ELF32_R_INFO(symbol, type);
|
||||||
sr->data_ptr += sizeof(Elf32_Rel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* put stab debug information */
|
/* put stab debug information */
|
||||||
|
@ -6500,11 +6545,12 @@ typedef struct {
|
||||||
unsigned long n_value; /* value of symbol */
|
unsigned long n_value; /* value of symbol */
|
||||||
} Stab_Sym;
|
} Stab_Sym;
|
||||||
|
|
||||||
static void put_stabs(const char *str, int type, int other, int desc, int value)
|
static void put_stabs(const char *str, int type, int other, int desc,
|
||||||
|
unsigned long value)
|
||||||
{
|
{
|
||||||
Stab_Sym *sym;
|
Stab_Sym *sym;
|
||||||
|
|
||||||
sym = (Stab_Sym *)stab_section->data_ptr;
|
sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
|
||||||
if (str) {
|
if (str) {
|
||||||
sym->n_strx = put_elf_str(stabstr_section, str);
|
sym->n_strx = put_elf_str(stabstr_section, str);
|
||||||
} else {
|
} else {
|
||||||
|
@ -6514,8 +6560,15 @@ static void put_stabs(const char *str, int type, int other, int desc, int value)
|
||||||
sym->n_other = other;
|
sym->n_other = other;
|
||||||
sym->n_desc = desc;
|
sym->n_desc = desc;
|
||||||
sym->n_value = value;
|
sym->n_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
stab_section->data_ptr += sizeof(Stab_Sym);
|
static void put_stabs_r(const char *str, int type, int other, int desc,
|
||||||
|
unsigned long value, Section *sec, int sym_index)
|
||||||
|
{
|
||||||
|
put_stabs(str, type, other, desc, value);
|
||||||
|
put_elf_reloc(symtab_section, stab_section,
|
||||||
|
stab_section->data_offset - sizeof(unsigned long),
|
||||||
|
R_DATA_32, sym_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void put_stabn(int type, int other, int desc, int value)
|
static void put_stabn(int type, int other, int desc, int value)
|
||||||
|
@ -6538,11 +6591,11 @@ static void sort_syms(Section *s)
|
||||||
Elf32_Sym *new_syms;
|
Elf32_Sym *new_syms;
|
||||||
int nb_syms, i;
|
int nb_syms, i;
|
||||||
Elf32_Sym *p, *q;
|
Elf32_Sym *p, *q;
|
||||||
Elf32_Rel *rel;
|
Elf32_Rel *rel, *rel_end;
|
||||||
Section *sr;
|
Section *sr;
|
||||||
int type, sym_index;
|
int type, sym_index;
|
||||||
|
|
||||||
nb_syms = (s->data_ptr - s->data) / sizeof(Elf32_Sym);
|
nb_syms = s->data_offset / sizeof(Elf32_Sym);
|
||||||
new_syms = malloc(nb_syms * sizeof(Elf32_Sym));
|
new_syms = malloc(nb_syms * sizeof(Elf32_Sym));
|
||||||
if (!new_syms)
|
if (!new_syms)
|
||||||
error("memory full");
|
error("memory full");
|
||||||
|
@ -6580,8 +6633,9 @@ static void sort_syms(Section *s)
|
||||||
for(i = 1; i < nb_sections; i++) {
|
for(i = 1; i < nb_sections; i++) {
|
||||||
sr = sections[i];
|
sr = sections[i];
|
||||||
if (sr->sh_type == SHT_REL && sr->link == s) {
|
if (sr->sh_type == SHT_REL && sr->link == s) {
|
||||||
|
rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
|
||||||
for(rel = (Elf32_Rel *)sr->data;
|
for(rel = (Elf32_Rel *)sr->data;
|
||||||
rel < (Elf32_Rel *)sr->data_ptr;
|
rel < rel_end;
|
||||||
rel++) {
|
rel++) {
|
||||||
sym_index = ELF32_R_SYM(rel->r_info);
|
sym_index = ELF32_R_SYM(rel->r_info);
|
||||||
type = ELF32_R_TYPE(rel->r_info);
|
type = ELF32_R_TYPE(rel->r_info);
|
||||||
|
@ -6597,21 +6651,22 @@ static void sort_syms(Section *s)
|
||||||
/* relocate common symbols in the .bss section */
|
/* relocate common symbols in the .bss section */
|
||||||
static void relocate_common_syms(void)
|
static void relocate_common_syms(void)
|
||||||
{
|
{
|
||||||
Elf32_Sym *sym;
|
Elf32_Sym *sym, *sym_end;
|
||||||
unsigned long offset, align;
|
unsigned long offset, align;
|
||||||
|
|
||||||
|
sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
|
||||||
for(sym = (Elf32_Sym *)symtab_section->data + 1;
|
for(sym = (Elf32_Sym *)symtab_section->data + 1;
|
||||||
sym < (Elf32_Sym *)symtab_section->data_ptr;
|
sym < sym_end;
|
||||||
sym++) {
|
sym++) {
|
||||||
if (sym->st_shndx == SHN_COMMON) {
|
if (sym->st_shndx == SHN_COMMON) {
|
||||||
/* align symbol */
|
/* align symbol */
|
||||||
align = sym->st_value;
|
align = sym->st_value;
|
||||||
offset = bss_section->data_ptr - bss_section->data;
|
offset = bss_section->data_offset;
|
||||||
offset = (offset + align - 1) & -align;
|
offset = (offset + align - 1) & -align;
|
||||||
sym->st_value = offset;
|
sym->st_value = offset;
|
||||||
sym->st_shndx = bss_section->sh_num;
|
sym->st_shndx = bss_section->sh_num;
|
||||||
offset += sym->st_size;
|
offset += sym->st_size;
|
||||||
bss_section->data_ptr = bss_section->data + offset;
|
bss_section->data_offset = offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6625,13 +6680,14 @@ static void *resolve_sym(const char *sym)
|
||||||
true and output error if undefined symbol. */
|
true and output error if undefined symbol. */
|
||||||
static void relocate_syms(int do_resolve)
|
static void relocate_syms(int do_resolve)
|
||||||
{
|
{
|
||||||
Elf32_Sym *sym, *esym;
|
Elf32_Sym *sym, *esym, *sym_end;
|
||||||
int sym_bind, sh_num, sym_index;
|
int sym_bind, sh_num, sym_index;
|
||||||
const char *name;
|
const char *name;
|
||||||
unsigned long addr;
|
unsigned long addr;
|
||||||
|
|
||||||
|
sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
|
||||||
for(sym = (Elf32_Sym *)symtab_section->data + 1;
|
for(sym = (Elf32_Sym *)symtab_section->data + 1;
|
||||||
sym < (Elf32_Sym *)symtab_section->data_ptr;
|
sym < sym_end;
|
||||||
sym++) {
|
sym++) {
|
||||||
sh_num = sym->st_shndx;
|
sh_num = sym->st_shndx;
|
||||||
if (sh_num == SHN_UNDEF) {
|
if (sh_num == SHN_UNDEF) {
|
||||||
|
@ -6707,15 +6763,16 @@ static void elf_reloc(unsigned char *ptr,
|
||||||
static void relocate_section(Section *s)
|
static void relocate_section(Section *s)
|
||||||
{
|
{
|
||||||
Section *sr;
|
Section *sr;
|
||||||
Elf32_Rel *rel;
|
Elf32_Rel *rel, *rel_end;
|
||||||
Elf32_Sym *sym;
|
Elf32_Sym *sym;
|
||||||
int type, sym_index;
|
int type, sym_index;
|
||||||
unsigned char *ptr;
|
unsigned char *ptr;
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
|
|
||||||
sr = s->reloc;
|
sr = s->reloc;
|
||||||
|
rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
|
||||||
for(rel = (Elf32_Rel *)sr->data;
|
for(rel = (Elf32_Rel *)sr->data;
|
||||||
rel < (Elf32_Rel *)sr->data_ptr;
|
rel < rel_end;
|
||||||
rel++) {
|
rel++) {
|
||||||
ptr = s->data + rel->r_offset;
|
ptr = s->data + rel->r_offset;
|
||||||
|
|
||||||
|
@ -6731,11 +6788,12 @@ static void relocate_section(Section *s)
|
||||||
static void relocate_rel(Section *sr)
|
static void relocate_rel(Section *sr)
|
||||||
{
|
{
|
||||||
Section *s;
|
Section *s;
|
||||||
Elf32_Rel *rel;
|
Elf32_Rel *rel, *rel_end;
|
||||||
|
|
||||||
s = sections[sr->sh_info];
|
s = sections[sr->sh_info];
|
||||||
|
rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
|
||||||
for(rel = (Elf32_Rel *)sr->data;
|
for(rel = (Elf32_Rel *)sr->data;
|
||||||
rel < (Elf32_Rel *)sr->data_ptr;
|
rel < rel_end;
|
||||||
rel++) {
|
rel++) {
|
||||||
rel->r_offset += s->sh_addr;
|
rel->r_offset += s->sh_addr;
|
||||||
}
|
}
|
||||||
|
@ -6773,19 +6831,19 @@ static void put32(unsigned char *p, unsigned int val)
|
||||||
|
|
||||||
static void build_got(void)
|
static void build_got(void)
|
||||||
{
|
{
|
||||||
|
unsigned char *ptr;
|
||||||
|
|
||||||
/* if no got, then create it */
|
/* if no got, then create it */
|
||||||
got = new_section(".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
|
got = new_section(".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
|
||||||
got->sh_entsize = 4;
|
got->sh_entsize = 4;
|
||||||
add_elf_sym(symtab_section, 0, 4, ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT),
|
add_elf_sym(symtab_section, 0, 4, ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT),
|
||||||
got->sh_num, "_GLOBAL_OFFSET_TABLE_");
|
got->sh_num, "_GLOBAL_OFFSET_TABLE_");
|
||||||
|
ptr = section_ptr_add(got, 3 * sizeof(int));
|
||||||
/* keep space for _DYNAMIC pointer, if present */
|
/* keep space for _DYNAMIC pointer, if present */
|
||||||
got->data_ptr += 4;
|
put32(ptr, 0);
|
||||||
|
|
||||||
/* two dummy got entries */
|
/* two dummy got entries */
|
||||||
put32(got->data_ptr, 0);
|
put32(ptr + 4, 0);
|
||||||
got->data_ptr += 4;
|
put32(ptr + 8, 0);
|
||||||
put32(got->data_ptr, 0);
|
|
||||||
got->data_ptr += 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* put a got entry corresponding to a symbol in symtab_section. 'size'
|
/* put a got entry corresponding to a symbol in symtab_section. 'size'
|
||||||
|
@ -6797,6 +6855,7 @@ static void put_got_entry(int reloc_type, unsigned long size, int info,
|
||||||
const char *name;
|
const char *name;
|
||||||
Elf32_Sym *sym;
|
Elf32_Sym *sym;
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
|
int *ptr;
|
||||||
|
|
||||||
if (!got)
|
if (!got)
|
||||||
build_got();
|
build_got();
|
||||||
|
@ -6806,7 +6865,7 @@ static void put_got_entry(int reloc_type, unsigned long size, int info,
|
||||||
got_offsets[sym_index] != 0)
|
got_offsets[sym_index] != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
put_got_offset(sym_index, got->data_ptr - got->data);
|
put_got_offset(sym_index, got->data_offset);
|
||||||
|
|
||||||
if (dynsym) {
|
if (dynsym) {
|
||||||
sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
|
sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
|
||||||
|
@ -6815,24 +6874,24 @@ static void put_got_entry(int reloc_type, unsigned long size, int info,
|
||||||
/* NOTE: we put temporarily the got offset */
|
/* NOTE: we put temporarily the got offset */
|
||||||
if (reloc_type == R_386_JMP_SLOT) {
|
if (reloc_type == R_386_JMP_SLOT) {
|
||||||
nb_plt_entries++;
|
nb_plt_entries++;
|
||||||
offset = got->data_ptr - got->data;
|
offset = got->data_offset;
|
||||||
}
|
}
|
||||||
index = put_elf_sym(dynsym, offset,
|
index = put_elf_sym(dynsym, offset,
|
||||||
size, info, 0, sym->st_shndx, name);
|
size, info, 0, sym->st_shndx, name);
|
||||||
/* put a got entry */
|
/* put a got entry */
|
||||||
put_elf_reloc(dynsym, got,
|
put_elf_reloc(dynsym, got,
|
||||||
got->data_ptr - got->data,
|
got->data_offset,
|
||||||
reloc_type, index);
|
reloc_type, index);
|
||||||
}
|
}
|
||||||
put32(got->data_ptr, 0);
|
ptr = section_ptr_add(got, sizeof(int));
|
||||||
got->data_ptr += 4;
|
*ptr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* build GOT and PLT entries */
|
/* build GOT and PLT entries */
|
||||||
static void build_got_entries(void)
|
static void build_got_entries(void)
|
||||||
{
|
{
|
||||||
Section *s, *symtab;
|
Section *s, *symtab;
|
||||||
Elf32_Rel *rel;
|
Elf32_Rel *rel, *rel_end;
|
||||||
Elf32_Sym *sym;
|
Elf32_Sym *sym;
|
||||||
int i, type, reloc_type, sym_index;
|
int i, type, reloc_type, sym_index;
|
||||||
|
|
||||||
|
@ -6844,8 +6903,9 @@ static void build_got_entries(void)
|
||||||
if (s->link != symtab_section)
|
if (s->link != symtab_section)
|
||||||
continue;
|
continue;
|
||||||
symtab = s->link;
|
symtab = s->link;
|
||||||
|
rel_end = (Elf32_Rel *)(s->data + s->data_offset);
|
||||||
for(rel = (Elf32_Rel *)s->data;
|
for(rel = (Elf32_Rel *)s->data;
|
||||||
rel < (Elf32_Rel *)s->data_ptr;
|
rel < rel_end;
|
||||||
rel++) {
|
rel++) {
|
||||||
type = ELF32_R_TYPE(rel->r_info);
|
type = ELF32_R_TYPE(rel->r_info);
|
||||||
switch(type) {
|
switch(type) {
|
||||||
|
@ -6882,7 +6942,7 @@ static Section *new_section_hash(const char *name, int sh_flags,
|
||||||
((int *)hash->data)[0] = nb_buckets;
|
((int *)hash->data)[0] = nb_buckets;
|
||||||
((int *)hash->data)[1] = 1;
|
((int *)hash->data)[1] = 1;
|
||||||
hash->sh_entsize = sizeof(int);
|
hash->sh_entsize = sizeof(int);
|
||||||
hash->data_ptr += (2 + nb_buckets + 1) * sizeof(int);
|
section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
|
||||||
symtab->hash = hash;
|
symtab->hash = hash;
|
||||||
hash->link = symtab;
|
hash->link = symtab;
|
||||||
return hash;
|
return hash;
|
||||||
|
@ -6892,24 +6952,24 @@ static Section *new_section_hash(const char *name, int sh_flags,
|
||||||
static void put_dt(Section *dynamic, int dt, unsigned long val)
|
static void put_dt(Section *dynamic, int dt, unsigned long val)
|
||||||
{
|
{
|
||||||
Elf32_Dyn *dyn;
|
Elf32_Dyn *dyn;
|
||||||
dyn = (Elf32_Dyn *)dynamic->data_ptr;
|
dyn = section_ptr_add(dynamic, sizeof(Elf32_Dyn));
|
||||||
dyn->d_tag = dt;
|
dyn->d_tag = dt;
|
||||||
dyn->d_un.d_val = val;
|
dyn->d_un.d_val = val;
|
||||||
dynamic->data_ptr += sizeof(Elf32_Dyn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add tcc runtime libraries */
|
/* add tcc runtime libraries */
|
||||||
static void tcc_add_runtime(TCCState *s1)
|
static void tcc_add_runtime(TCCState *s1)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
unsigned long *ptr;
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "libtcc1.o");
|
snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "libtcc1.o");
|
||||||
tcc_add_file(s1, buf);
|
tcc_add_file(s1, buf);
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if (do_bounds_check) {
|
if (do_bounds_check) {
|
||||||
/* XXX: add an object file to do that */
|
/* XXX: add an object file to do that */
|
||||||
*(int *)bounds_section->data_ptr = 0;
|
ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
|
||||||
bounds_section->data_ptr += sizeof(int);
|
*ptr = 0;
|
||||||
add_elf_sym(symtab_section, 0, 0,
|
add_elf_sym(symtab_section, 0, 0,
|
||||||
ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
|
ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
|
||||||
bounds_section->sh_num, "__bounds_start");
|
bounds_section->sh_num, "__bounds_start");
|
||||||
|
@ -6928,15 +6988,15 @@ static void tcc_add_runtime(TCCState *s1)
|
||||||
}
|
}
|
||||||
/* add various standard linker symbols */
|
/* add various standard linker symbols */
|
||||||
add_elf_sym(symtab_section,
|
add_elf_sym(symtab_section,
|
||||||
text_section->data_ptr - text_section->data, 0,
|
text_section->data_offset, 0,
|
||||||
ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
|
ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
|
||||||
text_section->sh_num, "_etext");
|
text_section->sh_num, "_etext");
|
||||||
add_elf_sym(symtab_section,
|
add_elf_sym(symtab_section,
|
||||||
data_section->data_ptr - data_section->data, 0,
|
data_section->data_offset, 0,
|
||||||
ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
|
ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
|
||||||
data_section->sh_num, "_edata");
|
data_section->sh_num, "_edata");
|
||||||
add_elf_sym(symtab_section,
|
add_elf_sym(symtab_section,
|
||||||
bss_section->data_ptr - bss_section->data, 0,
|
bss_section->data_offset, 0,
|
||||||
ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
|
ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
|
||||||
bss_section->sh_num, "_end");
|
bss_section->sh_num, "_end");
|
||||||
}
|
}
|
||||||
|
@ -6962,7 +7022,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
Elf32_Shdr shdr, *sh;
|
Elf32_Shdr shdr, *sh;
|
||||||
Elf32_Phdr *phdr, *ph;
|
Elf32_Phdr *phdr, *ph;
|
||||||
Section *interp, *plt, *dynamic, *dynstr, *hash;
|
Section *interp, *plt, *dynamic, *dynstr, *hash;
|
||||||
unsigned char *saved_dynamic_data_ptr;
|
unsigned long saved_dynamic_data_offset;
|
||||||
Elf32_Sym *sym;
|
Elf32_Sym *sym;
|
||||||
int type, file_type;
|
int type, file_type;
|
||||||
unsigned long rel_addr, rel_size;
|
unsigned long rel_addr, rel_size;
|
||||||
|
@ -6980,7 +7040,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
plt = NULL; /* avoid warning */
|
plt = NULL; /* avoid warning */
|
||||||
hash = NULL; /* avoid warning */
|
hash = NULL; /* avoid warning */
|
||||||
dynstr = NULL; /* avoid warning */
|
dynstr = NULL; /* avoid warning */
|
||||||
saved_dynamic_data_ptr = NULL; /* avoid warning */
|
saved_dynamic_data_offset = 0; /* avoid warning */
|
||||||
|
|
||||||
if (file_type != TCC_OUTPUT_OBJ) {
|
if (file_type != TCC_OUTPUT_OBJ) {
|
||||||
|
|
||||||
|
@ -6989,14 +7049,15 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
if (!static_link) {
|
if (!static_link) {
|
||||||
const char *name;
|
const char *name;
|
||||||
int sym_index, index;
|
int sym_index, index;
|
||||||
Elf32_Sym *esym;
|
Elf32_Sym *esym, *sym_end;
|
||||||
|
|
||||||
if (file_type == TCC_OUTPUT_EXE) {
|
if (file_type == TCC_OUTPUT_EXE) {
|
||||||
|
char *ptr;
|
||||||
/* add interpreter section only if executable */
|
/* add interpreter section only if executable */
|
||||||
interp = new_section(".interp", SHT_PROGBITS, SHF_ALLOC);
|
interp = new_section(".interp", SHT_PROGBITS, SHF_ALLOC);
|
||||||
interp->sh_addralign = 1;
|
interp->sh_addralign = 1;
|
||||||
strcpy(interp->data_ptr, elf_interp);
|
ptr = section_ptr_add(interp, sizeof(elf_interp));
|
||||||
interp->data_ptr += sizeof(elf_interp);
|
strcpy(ptr, elf_interp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add dynamic symbol table */
|
/* add dynamic symbol table */
|
||||||
|
@ -7025,8 +7086,10 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
dynamic symbols. If a symbol STT_FUNC is found, then we
|
dynamic symbols. If a symbol STT_FUNC is found, then we
|
||||||
add it in the PLT. If a symbol STT_OBJECT is found, we
|
add it in the PLT. If a symbol STT_OBJECT is found, we
|
||||||
add it in the .bss section with a suitable relocation */
|
add it in the .bss section with a suitable relocation */
|
||||||
|
sym_end = (Elf32_Sym *)(symtab_section->data +
|
||||||
|
symtab_section->data_offset);
|
||||||
for(sym = (Elf32_Sym *)symtab_section->data + 1;
|
for(sym = (Elf32_Sym *)symtab_section->data + 1;
|
||||||
sym < (Elf32_Sym *)symtab_section->data_ptr;
|
sym < sym_end;
|
||||||
sym++) {
|
sym++) {
|
||||||
if (sym->st_shndx == SHN_UNDEF) {
|
if (sym->st_shndx == SHN_UNDEF) {
|
||||||
name = symtab_section->link->data + sym->st_name;
|
name = symtab_section->link->data + sym->st_name;
|
||||||
|
@ -7040,7 +7103,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
sym - (Elf32_Sym *)symtab_section->data);
|
sym - (Elf32_Sym *)symtab_section->data);
|
||||||
} else if (type == STT_OBJECT) {
|
} else if (type == STT_OBJECT) {
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
offset = bss_section->data_ptr - bss_section->data;
|
offset = bss_section->data_offset;
|
||||||
/* XXX: which alignment ? */
|
/* XXX: which alignment ? */
|
||||||
offset = (offset + 8 - 1) & -8;
|
offset = (offset + 8 - 1) & -8;
|
||||||
index = put_elf_sym(dynsym, offset, esym->st_size,
|
index = put_elf_sym(dynsym, offset, esym->st_size,
|
||||||
|
@ -7049,7 +7112,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
put_elf_reloc(dynsym, bss_section,
|
put_elf_reloc(dynsym, bss_section,
|
||||||
offset, R_386_COPY, index);
|
offset, R_386_COPY, index);
|
||||||
offset += esym->st_size;
|
offset += esym->st_size;
|
||||||
bss_section->data_ptr = bss_section->data + offset;
|
bss_section->data_offset = offset;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* STT_NOTYPE or STB_WEAK undefined symbols
|
/* STT_NOTYPE or STB_WEAK undefined symbols
|
||||||
|
@ -7068,8 +7131,10 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
|
|
||||||
/* now look at unresolved dynamic symbols and export
|
/* now look at unresolved dynamic symbols and export
|
||||||
corresponding symbol */
|
corresponding symbol */
|
||||||
|
sym_end = (Elf32_Sym *)(dynsymtab_section->data +
|
||||||
|
dynsymtab_section->data_offset);
|
||||||
for(sym = (Elf32_Sym *)dynsymtab_section->data + 1;
|
for(sym = (Elf32_Sym *)dynsymtab_section->data + 1;
|
||||||
sym < (Elf32_Sym *)dynsymtab_section->data_ptr;
|
sym < sym_end;
|
||||||
sym++) {
|
sym++) {
|
||||||
if (sym->st_shndx == SHN_UNDEF) {
|
if (sym->st_shndx == SHN_UNDEF) {
|
||||||
name = dynsymtab_section->link->data + sym->st_name;
|
name = dynsymtab_section->link->data + sym->st_name;
|
||||||
|
@ -7088,7 +7153,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
build_got_entries();
|
build_got_entries();
|
||||||
|
|
||||||
/* update PLT/GOT sizes so that we can allocate their space */
|
/* update PLT/GOT sizes so that we can allocate their space */
|
||||||
plt->data_ptr += 16 * (nb_plt_entries + 1);
|
plt->data_offset += 16 * (nb_plt_entries + 1);
|
||||||
|
|
||||||
/* add a list of needed dlls */
|
/* add a list of needed dlls */
|
||||||
for(i = 0; i < nb_loaded_dlls; i++) {
|
for(i = 0; i < nb_loaded_dlls; i++) {
|
||||||
|
@ -7098,8 +7163,8 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add necessary space for other entries */
|
/* add necessary space for other entries */
|
||||||
saved_dynamic_data_ptr = dynamic->data_ptr;
|
saved_dynamic_data_offset = dynamic->data_offset;
|
||||||
dynamic->data_ptr += 8 * 9;
|
dynamic->data_offset += 8 * 9;
|
||||||
} else {
|
} else {
|
||||||
/* still need to build got entries in case of static link */
|
/* still need to build got entries in case of static link */
|
||||||
build_got_entries();
|
build_got_entries();
|
||||||
|
@ -7143,7 +7208,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
for(i = 1; i < nb_sections; i++) {
|
for(i = 1; i < nb_sections; i++) {
|
||||||
s = sections[i];
|
s = sections[i];
|
||||||
s->sh_name = put_elf_str(strsec, s->name);
|
s->sh_name = put_elf_str(strsec, s->name);
|
||||||
s->sh_size = s->data_ptr - s->data;
|
s->sh_size = s->data_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate program segment headers */
|
/* allocate program segment headers */
|
||||||
|
@ -7264,6 +7329,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
if (dynamic) {
|
if (dynamic) {
|
||||||
int plt_offset;
|
int plt_offset;
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
|
Elf32_Sym *sym_end;
|
||||||
|
|
||||||
ph = &phdr[phnum - 1];
|
ph = &phdr[phnum - 1];
|
||||||
|
|
||||||
|
@ -7280,42 +7346,41 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
put32(got->data, dynamic->sh_addr);
|
put32(got->data, dynamic->sh_addr);
|
||||||
|
|
||||||
/* compute the PLT */
|
/* compute the PLT */
|
||||||
plt->data_ptr = plt->data;
|
plt->data_offset = 0;
|
||||||
|
|
||||||
/* first plt entry */
|
/* first plt entry */
|
||||||
p = plt->data_ptr;
|
p = section_ptr_add(plt, 16);
|
||||||
p[0] = 0xff; /* pushl got + 4 */
|
p[0] = 0xff; /* pushl got + 4 */
|
||||||
p[1] = 0x35;
|
p[1] = 0x35;
|
||||||
put32(p + 2, got->sh_addr + 4);
|
put32(p + 2, got->sh_addr + 4);
|
||||||
p[6] = 0xff; /* jmp *(got + 8) */
|
p[6] = 0xff; /* jmp *(got + 8) */
|
||||||
p[7] = 0x25;
|
p[7] = 0x25;
|
||||||
put32(p + 8, got->sh_addr + 8);
|
put32(p + 8, got->sh_addr + 8);
|
||||||
plt->data_ptr += 16;
|
|
||||||
|
|
||||||
/* relocation symbols in .dynsym and build PLT. */
|
/* relocation symbols in .dynsym and build PLT. */
|
||||||
plt_offset = 0;
|
plt_offset = 0;
|
||||||
|
sym_end = (Elf32_Sym *)(dynsym->data + dynsym->data_offset);
|
||||||
for(sym = (Elf32_Sym *)dynsym->data + 1;
|
for(sym = (Elf32_Sym *)dynsym->data + 1;
|
||||||
sym < (Elf32_Sym *)dynsym->data_ptr;
|
sym < sym_end;
|
||||||
sym++) {
|
sym++) {
|
||||||
type = ELF32_ST_TYPE(sym->st_info);
|
type = ELF32_ST_TYPE(sym->st_info);
|
||||||
if (sym->st_shndx == SHN_UNDEF) {
|
if (sym->st_shndx == SHN_UNDEF) {
|
||||||
if (type == STT_FUNC) {
|
if (type == STT_FUNC) {
|
||||||
/* one more entry in PLT */
|
/* one more entry in PLT */
|
||||||
p = plt->data_ptr;
|
p = section_ptr_add(plt, 16);
|
||||||
p[0] = 0xff; /* jmp *(got + x) */
|
p[0] = 0xff; /* jmp *(got + x) */
|
||||||
p[1] = 0x25;
|
p[1] = 0x25;
|
||||||
put32(p + 2, got->sh_addr + sym->st_value);
|
put32(p + 2, got->sh_addr + sym->st_value);
|
||||||
p[6] = 0x68; /* push $xxx */
|
p[6] = 0x68; /* push $xxx */
|
||||||
put32(p + 7, plt_offset);
|
put32(p + 7, plt_offset);
|
||||||
p[11] = 0xe9; /* jmp plt_start */
|
p[11] = 0xe9; /* jmp plt_start */
|
||||||
put32(p + 12, -(plt->data_ptr + 16 - plt->data));
|
put32(p + 12, -(plt->data_offset));
|
||||||
|
|
||||||
/* patch symbol value to point to plt */
|
/* patch symbol value to point to plt */
|
||||||
sym->st_value = plt->sh_addr + p - plt->data;
|
sym->st_value = plt->sh_addr + p - plt->data;
|
||||||
|
|
||||||
plt_offset += 8;
|
plt_offset += 8;
|
||||||
plt->data_ptr += 16;
|
}
|
||||||
}
|
|
||||||
} else if (sym->st_shndx < SHN_LORESERVE) {
|
} else if (sym->st_shndx < SHN_LORESERVE) {
|
||||||
/* do symbol relocation */
|
/* do symbol relocation */
|
||||||
sym->st_value += sections[sym->st_shndx]->sh_addr;
|
sym->st_value += sections[sym->st_shndx]->sh_addr;
|
||||||
|
@ -7323,11 +7388,11 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
}
|
}
|
||||||
/* put dynamic section entries */
|
/* put dynamic section entries */
|
||||||
|
|
||||||
dynamic->data_ptr = saved_dynamic_data_ptr;
|
dynamic->data_offset = saved_dynamic_data_offset;
|
||||||
put_dt(dynamic, DT_HASH, hash->sh_addr);
|
put_dt(dynamic, DT_HASH, hash->sh_addr);
|
||||||
put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
|
put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
|
||||||
put_dt(dynamic, DT_SYMTAB, dynsym->sh_addr);
|
put_dt(dynamic, DT_SYMTAB, dynsym->sh_addr);
|
||||||
put_dt(dynamic, DT_STRSZ, dynstr->data_ptr - dynstr->data);
|
put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
|
||||||
put_dt(dynamic, DT_SYMENT, sizeof(Elf32_Sym));
|
put_dt(dynamic, DT_SYMENT, sizeof(Elf32_Sym));
|
||||||
put_dt(dynamic, DT_REL, rel_addr);
|
put_dt(dynamic, DT_REL, rel_addr);
|
||||||
put_dt(dynamic, DT_RELSZ, rel_size);
|
put_dt(dynamic, DT_RELSZ, rel_size);
|
||||||
|
@ -7363,12 +7428,12 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
/* XXX: ignore sections with allocated relocations ? */
|
/* XXX: ignore sections with allocated relocations ? */
|
||||||
for(i = 1; i < nb_sections; i++) {
|
for(i = 1; i < nb_sections; i++) {
|
||||||
s = sections[i];
|
s = sections[i];
|
||||||
if ((s->sh_flags & SHF_ALLOC)
|
if (s->reloc && s != got)
|
||||||
&& s->reloc && s != got)
|
|
||||||
relocate_section(s);
|
relocate_section(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* relocate relocation entries */
|
/* relocate relocation entries if the relocation tables are
|
||||||
|
allocated in the executable */
|
||||||
for(i = 1; i < nb_sections; i++) {
|
for(i = 1; i < nb_sections; i++) {
|
||||||
s = sections[i];
|
s = sections[i];
|
||||||
if ((s->sh_flags & SHF_ALLOC) &&
|
if ((s->sh_flags & SHF_ALLOC) &&
|
||||||
|
@ -7434,7 +7499,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
fputc(0, f);
|
fputc(0, f);
|
||||||
offset++;
|
offset++;
|
||||||
}
|
}
|
||||||
size = s->data_ptr - s->data;
|
size = s->data_offset;
|
||||||
fwrite(s->data, 1, size, f);
|
fwrite(s->data, 1, size, f);
|
||||||
offset += size;
|
offset += size;
|
||||||
}
|
}
|
||||||
|
@ -7502,7 +7567,7 @@ static int tcc_load_object_file(TCCState *s1,
|
||||||
char *sh_name, *name;
|
char *sh_name, *name;
|
||||||
SectionMergeInfo *sm_table, *sm;
|
SectionMergeInfo *sm_table, *sm;
|
||||||
Elf32_Sym *sym, *symtab;
|
Elf32_Sym *sym, *symtab;
|
||||||
Elf32_Rel *rel;
|
Elf32_Rel *rel, *rel_end;
|
||||||
Section *s;
|
Section *s;
|
||||||
|
|
||||||
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
|
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
|
||||||
|
@ -7585,21 +7650,23 @@ static int tcc_load_object_file(TCCState *s1,
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* align start of section */
|
/* align start of section */
|
||||||
offset = s->data_ptr - s->data;
|
offset = s->data_offset;
|
||||||
size = sh->sh_addralign - 1;
|
size = sh->sh_addralign - 1;
|
||||||
offset = (offset + size) & ~size;
|
offset = (offset + size) & ~size;
|
||||||
if (sh->sh_addralign > s->sh_addralign)
|
if (sh->sh_addralign > s->sh_addralign)
|
||||||
s->sh_addralign = sh->sh_addralign;
|
s->sh_addralign = sh->sh_addralign;
|
||||||
s->data_ptr = s->data + offset;
|
s->data_offset = offset;
|
||||||
sm_table[i].offset = offset;
|
sm_table[i].offset = offset;
|
||||||
sm_table[i].s = s;
|
sm_table[i].s = s;
|
||||||
/* concatenate sections */
|
/* concatenate sections */
|
||||||
size = sh->sh_size;
|
size = sh->sh_size;
|
||||||
if (sh->sh_type != SHT_NOBITS) {
|
if (sh->sh_type != SHT_NOBITS) {
|
||||||
|
unsigned char *ptr;
|
||||||
lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
|
lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
|
||||||
read(fd, s->data_ptr, size);
|
ptr = section_ptr(s, size);
|
||||||
|
read(fd, ptr, size);
|
||||||
}
|
}
|
||||||
s->data_ptr += size;
|
s->data_offset += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* second short pass to update sh_link and sh_info fields of new
|
/* second short pass to update sh_link and sh_info fields of new
|
||||||
|
@ -7655,8 +7722,9 @@ static int tcc_load_object_file(TCCState *s1,
|
||||||
case SHT_REL:
|
case SHT_REL:
|
||||||
/* take relocation offset information */
|
/* take relocation offset information */
|
||||||
offseti = sm_table[sh->sh_info].offset;
|
offseti = sm_table[sh->sh_info].offset;
|
||||||
|
rel_end = (Elf32_Rel *)(s->data + s->data_offset);
|
||||||
for(rel = (Elf32_Rel *)(s->data + offset);
|
for(rel = (Elf32_Rel *)(s->data + offset);
|
||||||
rel < (Elf32_Rel *)s->data_ptr;
|
rel < rel_end;
|
||||||
rel++) {
|
rel++) {
|
||||||
int type;
|
int type;
|
||||||
unsigned sym_index;
|
unsigned sym_index;
|
||||||
|
@ -7945,7 +8013,7 @@ static void rt_printline(unsigned long wanted_pc)
|
||||||
last_pc = 0xffffffff;
|
last_pc = 0xffffffff;
|
||||||
last_line_num = 1;
|
last_line_num = 1;
|
||||||
sym = (Stab_Sym *)stab_section->data + 1;
|
sym = (Stab_Sym *)stab_section->data + 1;
|
||||||
sym_end = (Stab_Sym *)stab_section->data_ptr;
|
sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
|
||||||
while (sym < sym_end) {
|
while (sym < sym_end) {
|
||||||
switch(sym->n_type) {
|
switch(sym->n_type) {
|
||||||
/* function start or end */
|
/* function start or end */
|
||||||
|
@ -8098,7 +8166,7 @@ int tcc_run(TCCState *s1, int argc, char **argv)
|
||||||
/* relocate each section */
|
/* relocate each section */
|
||||||
for(i = 1; i < nb_sections; i++) {
|
for(i = 1; i < nb_sections; i++) {
|
||||||
s = sections[i];
|
s = sections[i];
|
||||||
if ((s->sh_flags & SHF_ALLOC) && s->reloc)
|
if (s->reloc)
|
||||||
relocate_section(s);
|
relocate_section(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue