Alien-TinyCC
view release on metacpan or search on metacpan
src/libtcc.c view on Meta::CPAN
ST_FUNC void section_realloc(Section *sec, unsigned long new_size)
{
unsigned long size;
unsigned char *data;
size = sec->data_allocated;
if (size == 0)
size = 1;
while (size < new_size)
size = size * 2;
data = tcc_realloc(sec->data, size);
memset(data + sec->data_allocated, 0, size - sec->data_allocated);
sec->data = data;
sec->data_allocated = size;
}
/* reserve at least 'size' bytes in section 'sec' from
sec->data_offset. */
ST_FUNC void *section_ptr_add(Section *sec, unsigned long size)
{
unsigned long offset, offset1;
offset = sec->data_offset;
offset1 = offset + size;
if (offset1 > sec->data_allocated)
section_realloc(sec, offset1);
sec->data_offset = offset1;
return sec->data + offset;
}
/* reserve at least 'size' bytes from section start */
ST_FUNC void section_reserve(Section *sec, unsigned long size)
{
if (size > sec->data_allocated)
section_realloc(sec, size);
if (size > sec->data_offset)
sec->data_offset = size;
}
/* return a reference to a section, and create it if it does not
exists */
ST_FUNC Section *find_section(TCCState *s1, const char *name)
{
Section *sec;
int i;
for(i = 1; i < s1->nb_sections; i++) {
sec = s1->sections[i];
if (!strcmp(name, sec->name))
return sec;
}
/* sections are created as PROGBITS */
return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
}
/* update sym->c so that it points to an external symbol in section
'section' with value 'value' */
ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
addr_t value, unsigned long size,
int can_add_underscore)
{
int sym_type, sym_bind, sh_num, info, other;
ElfW(Sym) *esym;
const char *name;
char buf1[256];
if (section == NULL)
sh_num = SHN_UNDEF;
else if (section == SECTION_ABS)
sh_num = SHN_ABS;
else
sh_num = section->sh_num;
if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
sym_type = STT_FUNC;
} else if ((sym->type.t & VT_BTYPE) == VT_VOID) {
sym_type = STT_NOTYPE;
} else {
sym_type = STT_OBJECT;
}
if (sym->type.t & VT_STATIC)
sym_bind = STB_LOCAL;
else {
if (sym->type.t & VT_WEAK)
sym_bind = STB_WEAK;
else
sym_bind = STB_GLOBAL;
}
if (!sym->c) {
name = get_tok_str(sym->v, NULL);
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check) {
char buf[32];
/* XXX: avoid doing that for statics ? */
/* if bound checking is activated, we change some function
names by adding the "__bound" prefix */
switch(sym->v) {
#ifdef TCC_TARGET_PE
/* XXX: we rely only on malloc hooks */
case TOK_malloc:
case TOK_free:
case TOK_realloc:
case TOK_memalign:
case TOK_calloc:
#endif
case TOK_memcpy:
case TOK_memmove:
case TOK_memset:
case TOK_strlen:
case TOK_strcpy:
case TOK_alloca:
strcpy(buf, "__bound_");
strcat(buf, name);
name = buf;
break;
}
}
#endif
other = 0;
#ifdef TCC_TARGET_PE
if (sym->type.t & VT_EXPORT)
other |= 1;
if (sym_type == STT_FUNC && sym->type.ref) {
int attr = sym->type.ref->r;
if (FUNC_EXPORT(attr))
other |= 1;
if (FUNC_CALL(attr) == FUNC_STDCALL && can_add_underscore) {
sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr) * PTR_SIZE);
name = buf1;
other |= 2;
can_add_underscore = 0;
}
} else {
if (find_elf_sym(tcc_state->dynsymtab_section, name))
other |= 4;
if (sym->type.t & VT_IMPORT)
other |= 4;
}
#endif
if (tcc_state->leading_underscore && can_add_underscore) {
buf1[0] = '_';
pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
name = buf1;
}
if (sym->asm_label) {
name = sym->asm_label;
}
info = ELFW(ST_INFO)(sym_bind, sym_type);
sym->c = add_elf_sym(symtab_section, value, size, info, other, sh_num, name);
} else {
esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
esym->st_value = value;
esym->st_size = size;
esym->st_shndx = sh_num;
}
}
ST_FUNC void put_extern_sym(Sym *sym, Section *section,
addr_t value, unsigned long size)
{
put_extern_sym2(sym, section, value, size, 1);
}
/* add a new relocation entry to symbol 'sym' in section 's' */
ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type)
{
int c = 0;
if (sym) {
if (0 == sym->c)
put_extern_sym(sym, NULL, 0, 0);
c = sym->c;
}
/* now we can add ELF relocation info */
put_elf_reloc(symtab_section, s, offset, type, c);
}
/********************************************************/
static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
{
int len;
len = strlen(buf);
vsnprintf(buf + len, buf_size - len, fmt, ap);
}
static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
strcat_vprintf(buf, buf_size, fmt, ap);
va_end(ap);
}
static void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
{
char buf[2048];
BufferedFile **pf, *f;
buf[0] = '\0';
/* use upper file if inline ":asm:" or token ":paste:" */
for (f = file; f && f->filename[0] == ':'; f = f->prev)
;
if (f) {
for(pf = s1->include_stack; pf < s1->include_stack_ptr; pf++)
strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
(*pf)->filename, (*pf)->line_num);
if (f->line_num > 0) {
strcat_printf(buf, sizeof(buf), "%s:%d: ",
( run in 1.506 second using v1.01-cache-2.11-cpan-2398b32b56e )