#include "utils/string.h" #include #include #include #ifdef HAVE_CONFIG_H # include "config.h" #endif /* !HAVE_CONFIG_H */ #include #include #include #include #define ALIGN_UP(val, alignment) ((val + alignment - 1) & -alignment) #define COFF_DEFAULT_ENTRYNAME "_start" void dynarray_add(void *ptab, int *nb_ptr, void *data); void dynarray_reset(void *pp, int *n); static TCCSection * coff_new_section(TCCState2 *s1, const char *name, int flags) { TCCSection *sec; sec = tcc_mallocz(sizeof(TCCSection)); sec->state = s1; strncpy(sec->name, name, 8); /* truncate section name */ sec->flags = flags; sec->secnum = s1->nb_sections; dynarray_add(&s1->sections, &s1->nb_sections, sec); return (sec); } static void coff_free_section(TCCSection *s) { if (!s) return; tcc_free(s->data); s->data = NULL; s->data_allocated = s->data_offset = 0; } void coff_new(TCCState2 *s1) { dynarray_add(&s1->sections, &s1->nb_sections, NULL); s1->text_section = coff_new_section(s1, ".text", COFF_STYP_TEXT); s1->data_section = coff_new_section(s1, ".data", COFF_STYP_DATA); s1->bss_section = coff_new_section(s1, ".bss", COFF_STYP_BSS); s1->rodata_section = coff_new_section(s1, ".rodata", COFF_STYP_RODATA); s1->symtab = tcc_mallocz(sizeof(TCCSymtab)); /* create new symtab */ /* add dummy symbols */ s1->symtab->nsym++; s1->symtab->syms = tcc_mallocz(sizeof(COFFSym)); } void coff_delete(TCCState2 *s1) { int i; for (i = 1; i < s1->nb_sections; i++) { coff_free_section(s1->sections[i]); } dynarray_reset(&s1->sections, &s1->nb_sections); if (s1->symtab != NULL) { tcc_free(s1->symtab->strtab.tab); tcc_free(s1->symtab->syms); tcc_free(s1->symtab); s1->symtab = NULL; } } void coff_begin_file(TCCState2 *s1) { TCCSection *sec; int i; for (i = 1; i < s1->nb_sections; i++) { sec = s1->sections[i]; sec->offset = sec->data_offset; } } void coff_section_realloc(TCCSection *sec, size_t new_size) { size_t size; uint8_t *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; } size_t coff_section_add(TCCSection *sec, size_t size, int align) { size_t offset; size_t offset1; offset = ALIGN_UP(sec->data_offset, align); offset1 = offset + size; if (sec->flags != COFF_STYP_BSS && offset1 > sec->data_allocated) { coff_section_realloc(sec, offset1); } sec->data_offset = offset1; if (align > sec->addralign) { sec->addralign = align; } return (offset); } /* reserve at least 'size' bytes in section 'sec' from sec->data_offset. */ void * coff_section_ptr_add(TCCSection *sec, size_t size) { return (sec->data + coff_section_add(sec, size, 1)); } static TCCSection * coff_have_section(TCCState2 *s1, const char *name) { TCCSection *sec; int i; for (i = 1; i < s1->nb_sections; i++) { sec = s1->sections[i]; if (strncmp(name, sec->name, 8) == 0) { return (sec); } } return (NULL); } /* return a reference to a section, and create it if it does not exists */ TCCSection * coff_find_section(TCCState2 *s1, const char *name) { TCCSection *sec; sec = coff_have_section(s1, name); if (sec != NULL) { return (sec); } return (coff_new_section(s1, name, COFF_STYP_TEXT)); } /* * --------------------------------------------------------------------------- * Symbols * --------------------------------------------------------------------------- */ int coff_add_sym(TCCState2 *s1, uint32_t value, const char *name, size_t size, int16_t scnum, uint16_t type, int8_t sclass) { size_t symidx; size_t strtaboffset; COFFSym *sym; char *ptr; symidx = s1->symtab->nsym; s1->symtab->nsym++; s1->symtab->syms = tcc_realloc(s1->symtab->syms, sizeof(COFFSym) * s1->symtab->nsym); sym = &(s1->symtab->syms[symidx]); if (size > 8) { strtaboffset = ALIGN_UP(s1->symtab->strtab.len, 1); s1->symtab->strtab.len += strtaboffset + size + 1; ptr = s1->symtab->strtab.tab; s1->symtab->strtab.tab = tcc_realloc(ptr, s1->symtab->strtab.len); ptr += strtaboffset; memcpy(ptr, name, size + 1); sym->n.n.zeroes = 0x0; sym->n.n.offset = strtaboffset; } else { memset(sym->n.name, 0, 8); memcpy(sym->n.name, name, size); } return (symidx); } int coff_find_sym(TCCState2 *s1, const char *name) { size_t symidx; size_t len; COFFSym *sym; const char *str; len = strlen(name); for (symidx = 1; symidx < s1->symtab->nsym; symidx++) { sym = &(s1->symtab->syms[symidx]); if ((len > 8 && sym->n.n.zeroes != 0) || (len <= 8 && sym->n.n.zeroes == 0)) { continue; } else if (len > 8) { str = s1->symtab->strtab.tab + sym->n.n.offset; if (strcmp(name, str) == 0) { return (symidx); } } else { if (strncmp(name, sym->n.name, 8) == 0) { return (symidx); } } } return (0); } uint32_t coff_get_sym_addr(TCCState2 *s1, const char *name, int err, int forc) { COFFSym *sym; int sym_idx; char buf[256]; if (forc && s1->leading_underscore) { buf[0] = '_'; pstrcpy(buf + 1, sizeof(buf) - 1, name); name = buf; } sym_idx = coff_find_sym(s1, name); sym = &((COFFSym *)s1->symtab->syms)[sym_idx]; if (sym_idx == 0 || sym->scnum == COFF_N_UNDEF) { if (err) { //_tcc_error_noabort("%s not defined", name); } return ((uint32_t)-1); } return (sym->value); } int tcc_output_coff(TCCState2 *s1, FILE *f) { COFFFileHeader coffhdr; AOutHeader aouthdr; COFFSectionHeader coffsec; const char *entry_name = COFF_DEFAULT_ENTRYNAME; memset(&coffhdr, 0, sizeof(COFFFileHeader)); coffhdr.flags = COFF_F_LITTLE | COFF_F_LNNO; coffhdr.magic = COFF_MAGIC; coffhdr.nscns = s1->nb_sections; if (s1->output_type == /*TCC_OUTPUT_EXE*/666) { coffhdr.flags |= COFF_F_RELFLG | COFF_F_EXEC | COFF_F_LSYMS; coffhdr.nsyms = 0; memset(&aouthdr, 0, sizeof(AOutHeader)); aouthdr.magic = AOUT_ZMAGIC; coffhdr.opthdr = sizeof(AOutHeader); if (s1->entryname != NULL) { entry_name = s1->entryname; } //aouthdr.entry = get_sym_addr(s1, entry_name, 1, 0); if (s1->nb_errors) { return (-1); } } return (0); } int coff_output_object(TCCState2 *s, const char *filename) { return (0); } int coff_output_exe(TCCState2 *s, const char *filename) { return (0); } int coff_load_object(TCCState2 *s, int fd, size_t file_offset) { COFFFileHeader chdr; return (0); }