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

tcc-xref
bellard 2002-07-27 14:05:37 +00:00
parent 540cd6fde7
commit 9b48237795
1 changed files with 222 additions and 154 deletions

376
tcc.c
View File

@ -135,8 +135,8 @@ typedef struct SymStack {
#define SHF_PRIVATE 0x80000000
typedef struct Section {
unsigned char *data; /* section data */
unsigned char *data_ptr; /* current data pointer */
unsigned long data_offset; /* current data offset */
unsigned char *data; /* section data */
int sh_name; /* elf section name (only used during output) */
int sh_num; /* elf section number */
int sh_type; /* elf section type */
@ -197,7 +197,7 @@ typedef struct BufferedFile {
unsigned char *buf_end;
int fd;
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 */
} BufferedFile;
@ -337,7 +337,7 @@ struct TCCState {
#define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
/* 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_BYTE 1 /* signed byte type */
@ -594,6 +594,8 @@ static Sym *get_sym_ref(int t, Section *sec,
unsigned long offset, unsigned long size);
/* 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 greloc(Section *s, Sym *sym, unsigned long addr, int type);
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);
static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
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_stabd(int type, int other, int desc);
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);
#endif
sec->data = data;
sec->data_ptr = data;
sec->data_offset = 0;
/* only add section if not private */
if (!(sh_flags & SHF_PRIVATE)) {
@ -787,6 +792,20 @@ Section *new_section(const char *name, int sh_type, int sh_flags)
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
exists */
Section *find_section(const char *name)
@ -1668,7 +1687,7 @@ void preprocess(void)
}
/* read a number in base b */
int getn(b)
static int getn(int b)
{
int n, t;
n = 0;
@ -1690,7 +1709,7 @@ int getn(b)
}
/* read a character for string or char constant and eval escape codes */
int getq()
static int getq(void)
{
int c;
@ -2094,7 +2113,11 @@ void next_nomacro1(void)
tok = TOK_CCHAR;
char_const:
minp();
tokc.i = getq();
b = getq();
/* this cast is needed if >= 128 */
if (tok == TOK_CCHAR)
b = (char)b;
tokc.i = b;
if (ch != '\'')
expect("\'");
minp();
@ -2718,7 +2741,7 @@ void gbound(void)
register value (such as structures). */
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;
/* NOTE: get_reg can modify vstack[] */
@ -2739,27 +2762,28 @@ int gv(int rc)
(vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
int v;
Sym *sym;
int *ptr;
/* XXX: unify with initializers handling ? */
/* CPUs usually cannot use float constants, so we store them
generically in data segment */
size = type_size(vtop->t, &align);
data_offset = data_section->data_ptr - data_section->data;
data_offset = (data_offset + align - 1) & -align;
data_section->data_offset = (data_section->data_offset +
align - 1) & -align;
/* XXX: not portable yet */
ptr = section_ptr(data_section, size);
size = size >> 2;
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++;
sym = sym_push1(&global_stack, v, vtop->t | VT_STATIC, 0);
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->c.sym = sym;
data_offset += size << 2;
data_section->data_ptr = data_section->data + data_offset;
data_section->data_offset += size << 2;
}
#ifdef CONFIG_TCC_BCHECK
if (vtop->r & VT_MUSTBOUND)
@ -4673,13 +4697,18 @@ void unary(void)
vsetc(VT_LDOUBLE, VT_CONST, &tokc);
next();
} else if (tok == TOK___FUNC__) {
void *ptr;
int len;
/* special function name identifier */
/* generate (char *) type */
data_offset = data_section->data_ptr - data_section->data;
vpush_ref(mk_pointer(VT_BYTE), data_section, data_offset);
strcpy(data_section->data + data_offset, funcname);
data_offset += strlen(funcname) + 1;
data_section->data_ptr = data_section->data + data_offset;
len = strlen(funcname) + 1;
/* generate char[len] type */
t = VT_ARRAY | mk_pointer(VT_BYTE);
s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
s->c = len;
vpush_ref(t, data_section, data_section->data_offset);
ptr = section_ptr_add(data_section, len);
memcpy(ptr, funcname, len);
next();
} else if (tok == TOK_LSTR) {
t = VT_INT;
@ -4689,16 +4718,16 @@ void unary(void)
t = VT_BYTE;
str_init:
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;
fc = data_offset;
/* we must declare it as an array first to use initializer parser */
t = VT_ARRAY | mk_pointer(t);
decl_initializer(t, data_section, data_offset, 1, 0);
data_offset += type_size(t, &align);
/* put it as pointer */
vpush_ref(t & ~VT_ARRAY, data_section, fc);
data_section->data_ptr = data_section->data + data_offset;
/* XXX: is it correct to put it exactly as an array ? */
vpush_ref(t, data_section, fc);
data_section->data_offset = data_offset;
} else {
t = tok;
next();
@ -4758,7 +4787,12 @@ void unary(void)
gen_op('^');
} else
if (t == '+') {
/* in order to force cast, we add zero */
unary();
if ((vtop->t & VT_BTYPE) == VT_PTR)
error("pointer not accepted for unary plus");
vpushi(0);
gen_op('+');
} else
if (t == TOK_SIZEOF) {
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
'&' operators, so we add only arrays */
if (do_bounds_check && (t & VT_ARRAY)) {
int *bounds_ptr;
unsigned long *bounds_ptr;
/* add padding between regions */
loc--;
/* then add local bound info */
bounds_ptr = (int *)lbounds_section->data_ptr;
*bounds_ptr++ = addr;
*bounds_ptr++ = size;
lbounds_section->data_ptr = (unsigned char *)bounds_ptr;
bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
bounds_ptr[0] = addr;
bounds_ptr[1] = size;
}
} else {
/* compute section */
@ -5829,33 +5862,29 @@ void decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init,
else
sec = bss_section;
}
data_offset = sec->data_ptr - sec->data;
data_offset = sec->data_offset;
data_offset = (data_offset + align - 1) & -align;
addr = data_offset;
/* very important to increment global pointer at this time
because initializers themselves can create new initializers */
data_offset += size;
/* handles bounds */
if (do_bounds_check) {
int *bounds_ptr;
/* first, we need to add at least one byte between each region */
/* add padding if bound check */
if (do_bounds_check)
data_offset++;
/* then add global bound info */
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;
sec->data_offset = data_offset;
}
if (v) {
Sym *sym;
if (!sec) {
if (!sec) {
if (v) {
/* local variable */
sym_push(v, t, r, addr);
} else {
/* push local reference */
vset(t, r, addr);
}
} else {
Sym *sym;
if (v) {
if (scope == VT_CONST) {
/* global scope: see if already defined */
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);
}
put_extern_sym(sym, sec, addr);
}
} else {
if (!sec) {
/* push local reference */
vset(t, r, addr);
} else {
CValue cval;
/* 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) {
@ -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];
/* stabs info */
/* XXX: we put here a dummy type */
snprintf(buf, sizeof(buf), "%s:%c1",
funcname, t & VT_STATIC ? 'f' : 'F');
put_stabs(buf, N_FUN, 0, file->line_num, ind);
funcname, sym->t & VT_STATIC ? 'f' : 'F');
put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
cur_text_section, sym->c);
func_ind = ind;
last_ind = 0;
last_line_num = 0;
@ -6049,7 +6090,7 @@ void decl(int l)
cur_text_section = ad.section;
if (!cur_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);
sym = sym_find(v);
if (sym) {
@ -6059,12 +6100,11 @@ void decl(int l)
/* put function symbol */
sym = sym_push1(&global_stack, v, t, 0);
}
put_extern_sym(sym, cur_text_section,
ind - (int)cur_text_section->data);
put_extern_sym(sym, cur_text_section, ind);
sym->r = VT_SYM | VT_CONST;
/* put debug symbol */
if (do_debug)
put_func_debug(t);
put_func_debug(sym);
/* push a dummy symbol to enable local sym storage */
sym_push1(&local_stack, 0, 0, 0);
gfunc_prolog(t);
@ -6077,7 +6117,7 @@ void decl(int l)
block(NULL, NULL, NULL, NULL, 0);
gsym(rsym);
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(&local_stack, NULL); /* reset local stack */
/* end of function */
@ -6136,7 +6176,7 @@ static int tcc_compile(TCCState *s)
{
Sym *define_start;
char buf[512];
int p;
int p, section_sym;
funcname = "";
include_stack_ptr = include_stack;
@ -6146,12 +6186,17 @@ static int tcc_compile(TCCState *s)
anon_sym = SYM_FIRST_ANOM;
/* file info: full path + filename */
section_sym = 0; /* avoid warning */
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));
pstrcat(buf, sizeof(buf), "/");
put_stabs(buf, N_SO, 0, 0, (unsigned long)text_section->data_ptr);
put_stabs(file->filename, N_SO, 0, 0,
(unsigned long)text_section->data_ptr);
put_stabs_r(buf, N_SO, 0, 0,
text_section->data_offset, text_section, section_sym);
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
symbols can be safely used */
@ -6177,7 +6222,8 @@ static int tcc_compile(TCCState *s)
/* end of translation unit info */
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
@ -6251,14 +6297,13 @@ void tcc_undefine_symbol(TCCState *s1, const char *sym)
static int put_elf_str(Section *s, const char *sym)
{
int c, offset;
offset = s->data_ptr - s->data;
for(;;) {
c = *sym++;
*s->data_ptr++ = c;
if (c == '\0')
break;
}
int offset, len;
char *ptr;
len = strlen(sym) + 1;
offset = s->data_offset;
ptr = section_ptr_add(s, len);
memcpy(ptr, sym, len);
return offset;
}
@ -6287,7 +6332,7 @@ static int put_elf_sym(Section *s,
Elf32_Sym *sym;
Section *hs;
sym = (Elf32_Sym *)s->data_ptr;
sym = section_ptr_add(s, sizeof(Elf32_Sym));
if (name)
name_offset = put_elf_str(s->link, name);
else
@ -6302,19 +6347,21 @@ static int put_elf_sym(Section *s,
sym_index = sym - (Elf32_Sym *)s->data;
hs = s->hash;
if (hs) {
int *ptr;
ptr = section_ptr_add(hs, sizeof(int));
/* only add global or weak symbols */
if (ELF32_ST_BIND(info) != STB_LOCAL) {
/* add another hashing entry */
nbuckets = ((int *)hs->data)[0];
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;
} else {
*ptr = 0;
}
/* but still add room for all symbols */
((int *)hs->data)[1]++;
hs->data_ptr += sizeof(int);
}
s->data_ptr += sizeof(Elf32_Sym);
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;
s->reloc = sr;
}
rel = (Elf32_Rel *)sr->data_ptr;
/* XXX: endianness */
rel = section_ptr_add(sr, sizeof(Elf32_Rel));
rel->r_offset = offset;
rel->r_info = ELF32_R_INFO(symbol, type);
sr->data_ptr += sizeof(Elf32_Rel);
}
/* put stab debug information */
@ -6500,11 +6545,12 @@ typedef struct {
unsigned long n_value; /* value of symbol */
} 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;
sym = (Stab_Sym *)stab_section->data_ptr;
sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
if (str) {
sym->n_strx = put_elf_str(stabstr_section, str);
} 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_desc = desc;
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)
@ -6538,11 +6591,11 @@ static void sort_syms(Section *s)
Elf32_Sym *new_syms;
int nb_syms, i;
Elf32_Sym *p, *q;
Elf32_Rel *rel;
Elf32_Rel *rel, *rel_end;
Section *sr;
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));
if (!new_syms)
error("memory full");
@ -6580,8 +6633,9 @@ static void sort_syms(Section *s)
for(i = 1; i < nb_sections; i++) {
sr = sections[i];
if (sr->sh_type == SHT_REL && sr->link == s) {
rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
for(rel = (Elf32_Rel *)sr->data;
rel < (Elf32_Rel *)sr->data_ptr;
rel < rel_end;
rel++) {
sym_index = ELF32_R_SYM(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 */
static void relocate_common_syms(void)
{
Elf32_Sym *sym;
Elf32_Sym *sym, *sym_end;
unsigned long offset, align;
sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
for(sym = (Elf32_Sym *)symtab_section->data + 1;
sym < (Elf32_Sym *)symtab_section->data_ptr;
sym < sym_end;
sym++) {
if (sym->st_shndx == SHN_COMMON) {
/* align symbol */
align = sym->st_value;
offset = bss_section->data_ptr - bss_section->data;
offset = bss_section->data_offset;
offset = (offset + align - 1) & -align;
sym->st_value = offset;
sym->st_shndx = bss_section->sh_num;
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. */
static void relocate_syms(int do_resolve)
{
Elf32_Sym *sym, *esym;
Elf32_Sym *sym, *esym, *sym_end;
int sym_bind, sh_num, sym_index;
const char *name;
unsigned long addr;
sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
for(sym = (Elf32_Sym *)symtab_section->data + 1;
sym < (Elf32_Sym *)symtab_section->data_ptr;
sym < sym_end;
sym++) {
sh_num = sym->st_shndx;
if (sh_num == SHN_UNDEF) {
@ -6707,15 +6763,16 @@ static void elf_reloc(unsigned char *ptr,
static void relocate_section(Section *s)
{
Section *sr;
Elf32_Rel *rel;
Elf32_Rel *rel, *rel_end;
Elf32_Sym *sym;
int type, sym_index;
unsigned char *ptr;
unsigned long val;
sr = s->reloc;
rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
for(rel = (Elf32_Rel *)sr->data;
rel < (Elf32_Rel *)sr->data_ptr;
rel < rel_end;
rel++) {
ptr = s->data + rel->r_offset;
@ -6731,11 +6788,12 @@ static void relocate_section(Section *s)
static void relocate_rel(Section *sr)
{
Section *s;
Elf32_Rel *rel;
Elf32_Rel *rel, *rel_end;
s = sections[sr->sh_info];
rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
for(rel = (Elf32_Rel *)sr->data;
rel < (Elf32_Rel *)sr->data_ptr;
rel < rel_end;
rel++) {
rel->r_offset += s->sh_addr;
}
@ -6773,19 +6831,19 @@ static void put32(unsigned char *p, unsigned int val)
static void build_got(void)
{
unsigned char *ptr;
/* if no got, then create it */
got = new_section(".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
got->sh_entsize = 4;
add_elf_sym(symtab_section, 0, 4, ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT),
got->sh_num, "_GLOBAL_OFFSET_TABLE_");
ptr = section_ptr_add(got, 3 * sizeof(int));
/* keep space for _DYNAMIC pointer, if present */
got->data_ptr += 4;
put32(ptr, 0);
/* two dummy got entries */
put32(got->data_ptr, 0);
got->data_ptr += 4;
put32(got->data_ptr, 0);
got->data_ptr += 4;
put32(ptr + 4, 0);
put32(ptr + 8, 0);
}
/* 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;
Elf32_Sym *sym;
unsigned long offset;
int *ptr;
if (!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)
return;
put_got_offset(sym_index, got->data_ptr - got->data);
put_got_offset(sym_index, got->data_offset);
if (dynsym) {
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 */
if (reloc_type == R_386_JMP_SLOT) {
nb_plt_entries++;
offset = got->data_ptr - got->data;
offset = got->data_offset;
}
index = put_elf_sym(dynsym, offset,
size, info, 0, sym->st_shndx, name);
/* put a got entry */
put_elf_reloc(dynsym, got,
got->data_ptr - got->data,
got->data_offset,
reloc_type, index);
}
put32(got->data_ptr, 0);
got->data_ptr += 4;
ptr = section_ptr_add(got, sizeof(int));
*ptr = 0;
}
/* build GOT and PLT entries */
static void build_got_entries(void)
{
Section *s, *symtab;
Elf32_Rel *rel;
Elf32_Rel *rel, *rel_end;
Elf32_Sym *sym;
int i, type, reloc_type, sym_index;
@ -6844,8 +6903,9 @@ static void build_got_entries(void)
if (s->link != symtab_section)
continue;
symtab = s->link;
rel_end = (Elf32_Rel *)(s->data + s->data_offset);
for(rel = (Elf32_Rel *)s->data;
rel < (Elf32_Rel *)s->data_ptr;
rel < rel_end;
rel++) {
type = ELF32_R_TYPE(rel->r_info);
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)[1] = 1;
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;
hash->link = symtab;
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)
{
Elf32_Dyn *dyn;
dyn = (Elf32_Dyn *)dynamic->data_ptr;
dyn = section_ptr_add(dynamic, sizeof(Elf32_Dyn));
dyn->d_tag = dt;
dyn->d_un.d_val = val;
dynamic->data_ptr += sizeof(Elf32_Dyn);
}
/* add tcc runtime libraries */
static void tcc_add_runtime(TCCState *s1)
{
char buf[1024];
unsigned long *ptr;
snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "libtcc1.o");
tcc_add_file(s1, buf);
#ifdef CONFIG_TCC_BCHECK
if (do_bounds_check) {
/* XXX: add an object file to do that */
*(int *)bounds_section->data_ptr = 0;
bounds_section->data_ptr += sizeof(int);
ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
*ptr = 0;
add_elf_sym(symtab_section, 0, 0,
ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
bounds_section->sh_num, "__bounds_start");
@ -6928,15 +6988,15 @@ static void tcc_add_runtime(TCCState *s1)
}
/* add various standard linker symbols */
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),
text_section->sh_num, "_etext");
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),
data_section->sh_num, "_edata");
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),
bss_section->sh_num, "_end");
}
@ -6962,7 +7022,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
Elf32_Shdr shdr, *sh;
Elf32_Phdr *phdr, *ph;
Section *interp, *plt, *dynamic, *dynstr, *hash;
unsigned char *saved_dynamic_data_ptr;
unsigned long saved_dynamic_data_offset;
Elf32_Sym *sym;
int type, file_type;
unsigned long rel_addr, rel_size;
@ -6980,7 +7040,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
plt = NULL; /* avoid warning */
hash = 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) {
@ -6989,14 +7049,15 @@ int tcc_output_file(TCCState *s1, const char *filename)
if (!static_link) {
const char *name;
int sym_index, index;
Elf32_Sym *esym;
Elf32_Sym *esym, *sym_end;
if (file_type == TCC_OUTPUT_EXE) {
char *ptr;
/* add interpreter section only if executable */
interp = new_section(".interp", SHT_PROGBITS, SHF_ALLOC);
interp->sh_addralign = 1;
strcpy(interp->data_ptr, elf_interp);
interp->data_ptr += sizeof(elf_interp);
ptr = section_ptr_add(interp, sizeof(elf_interp));
strcpy(ptr, elf_interp);
}
/* 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
add it in the PLT. If a symbol STT_OBJECT is found, we
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;
sym < (Elf32_Sym *)symtab_section->data_ptr;
sym < sym_end;
sym++) {
if (sym->st_shndx == SHN_UNDEF) {
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);
} else if (type == STT_OBJECT) {
unsigned long offset;
offset = bss_section->data_ptr - bss_section->data;
offset = bss_section->data_offset;
/* XXX: which alignment ? */
offset = (offset + 8 - 1) & -8;
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,
offset, R_386_COPY, index);
offset += esym->st_size;
bss_section->data_ptr = bss_section->data + offset;
bss_section->data_offset = offset;
}
} else {
/* 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
corresponding symbol */
sym_end = (Elf32_Sym *)(dynsymtab_section->data +
dynsymtab_section->data_offset);
for(sym = (Elf32_Sym *)dynsymtab_section->data + 1;
sym < (Elf32_Sym *)dynsymtab_section->data_ptr;
sym < sym_end;
sym++) {
if (sym->st_shndx == SHN_UNDEF) {
name = dynsymtab_section->link->data + sym->st_name;
@ -7088,7 +7153,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
build_got_entries();
/* 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 */
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 */
saved_dynamic_data_ptr = dynamic->data_ptr;
dynamic->data_ptr += 8 * 9;
saved_dynamic_data_offset = dynamic->data_offset;
dynamic->data_offset += 8 * 9;
} else {
/* still need to build got entries in case of static link */
build_got_entries();
@ -7143,7 +7208,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
for(i = 1; i < nb_sections; i++) {
s = sections[i];
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 */
@ -7264,6 +7329,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
if (dynamic) {
int plt_offset;
unsigned char *p;
Elf32_Sym *sym_end;
ph = &phdr[phnum - 1];
@ -7280,42 +7346,41 @@ int tcc_output_file(TCCState *s1, const char *filename)
put32(got->data, dynamic->sh_addr);
/* compute the PLT */
plt->data_ptr = plt->data;
plt->data_offset = 0;
/* first plt entry */
p = plt->data_ptr;
p = section_ptr_add(plt, 16);
p[0] = 0xff; /* pushl got + 4 */
p[1] = 0x35;
put32(p + 2, got->sh_addr + 4);
p[6] = 0xff; /* jmp *(got + 8) */
p[7] = 0x25;
put32(p + 8, got->sh_addr + 8);
plt->data_ptr += 16;
/* relocation symbols in .dynsym and build PLT. */
plt_offset = 0;
sym_end = (Elf32_Sym *)(dynsym->data + dynsym->data_offset);
for(sym = (Elf32_Sym *)dynsym->data + 1;
sym < (Elf32_Sym *)dynsym->data_ptr;
sym < sym_end;
sym++) {
type = ELF32_ST_TYPE(sym->st_info);
if (sym->st_shndx == SHN_UNDEF) {
if (type == STT_FUNC) {
/* one more entry in PLT */
p = plt->data_ptr;
p = section_ptr_add(plt, 16);
p[0] = 0xff; /* jmp *(got + x) */
p[1] = 0x25;
put32(p + 2, got->sh_addr + sym->st_value);
p[6] = 0x68; /* push $xxx */
put32(p + 7, plt_offset);
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 */
sym->st_value = plt->sh_addr + p - plt->data;
plt_offset += 8;
plt->data_ptr += 16;
}
}
} else if (sym->st_shndx < SHN_LORESERVE) {
/* do symbol relocation */
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 */
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_STRTAB, dynstr->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_REL, rel_addr);
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 ? */
for(i = 1; i < nb_sections; i++) {
s = sections[i];
if ((s->sh_flags & SHF_ALLOC)
&& s->reloc && s != got)
if (s->reloc && s != got)
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++) {
s = sections[i];
if ((s->sh_flags & SHF_ALLOC) &&
@ -7434,7 +7499,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
fputc(0, f);
offset++;
}
size = s->data_ptr - s->data;
size = s->data_offset;
fwrite(s->data, 1, size, f);
offset += size;
}
@ -7502,7 +7567,7 @@ static int tcc_load_object_file(TCCState *s1,
char *sh_name, *name;
SectionMergeInfo *sm_table, *sm;
Elf32_Sym *sym, *symtab;
Elf32_Rel *rel;
Elf32_Rel *rel, *rel_end;
Section *s;
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
@ -7585,21 +7650,23 @@ static int tcc_load_object_file(TCCState *s1,
goto fail;
/* align start of section */
offset = s->data_ptr - s->data;
offset = s->data_offset;
size = sh->sh_addralign - 1;
offset = (offset + size) & ~size;
if (sh->sh_addralign > s->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].s = s;
/* concatenate sections */
size = sh->sh_size;
if (sh->sh_type != SHT_NOBITS) {
unsigned char *ptr;
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
@ -7655,8 +7722,9 @@ static int tcc_load_object_file(TCCState *s1,
case SHT_REL:
/* take relocation offset information */
offseti = sm_table[sh->sh_info].offset;
rel_end = (Elf32_Rel *)(s->data + s->data_offset);
for(rel = (Elf32_Rel *)(s->data + offset);
rel < (Elf32_Rel *)s->data_ptr;
rel < rel_end;
rel++) {
int type;
unsigned sym_index;
@ -7945,7 +8013,7 @@ static void rt_printline(unsigned long wanted_pc)
last_pc = 0xffffffff;
last_line_num = 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) {
switch(sym->n_type) {
/* function start or end */
@ -8098,7 +8166,7 @@ int tcc_run(TCCState *s1, int argc, char **argv)
/* relocate each section */
for(i = 1; i < nb_sections; i++) {
s = sections[i];
if ((s->sh_flags & SHF_ALLOC) && s->reloc)
if (s->reloc)
relocate_section(s);
}