tcc-stupidos/libtcc/object/coff.c

347 lines
6.4 KiB
C
Raw Normal View History

2025-02-14 16:47:45 +00:00
#include "utils/string.h"
#include <stddef.h>
#include <stdint.h>
2025-02-11 19:16:44 +00:00
#include <string.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif /* !HAVE_CONFIG_H */
#include <tcc/state.h>
#include <tcc/memory.h>
2025-02-11 12:07:04 +00:00
#include <tcc/object/coff.h>
2025-02-11 19:16:44 +00:00
#include <tcc/state.h>
2025-02-11 12:07:04 +00:00
2025-02-14 16:47:45 +00:00
#define ALIGN_UP(val, alignment) ((val + alignment - 1) & -alignment)
2025-02-11 12:07:04 +00:00
#define COFF_DEFAULT_ENTRYNAME "_start"
2025-02-11 19:16:44 +00:00
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);
2025-02-14 16:47:45 +00:00
s1->rodata_section = coff_new_section(s1, ".rodata", COFF_STYP_RODATA);
2025-02-11 19:16:44 +00:00
2025-02-14 16:47:45 +00:00
s1->symtab = tcc_mallocz(sizeof(TCCSymtab)); /* create new symtab */
/* add dummy symbols */
s1->symtab->nsym++;
s1->symtab->syms = tcc_mallocz(sizeof(COFFSym));
2025-02-11 19:16:44 +00:00
}
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);
2025-02-14 16:47:45 +00:00
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);
2025-02-11 19:16:44 +00:00
}
2025-02-11 12:07:04 +00:00
int
2025-02-11 19:16:44 +00:00
tcc_output_coff(TCCState2 *s1, FILE *f)
2025-02-11 12:07:04 +00:00
{
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;
2025-02-11 19:16:44 +00:00
if (s1->output_type == /*TCC_OUTPUT_EXE*/666)
2025-02-11 12:07:04 +00:00
{
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;
}
2025-02-11 19:16:44 +00:00
//aouthdr.entry = get_sym_addr(s1, entry_name, 1, 0);
2025-02-11 12:07:04 +00:00
if (s1->nb_errors)
{
return (-1);
}
}
return (0);
}
int
2025-02-11 19:16:44 +00:00
coff_output_object(TCCState2 *s, const char *filename)
2025-02-11 12:07:04 +00:00
{
2025-02-11 19:16:44 +00:00
return (0);
2025-02-11 12:07:04 +00:00
}
int
2025-02-11 19:16:44 +00:00
coff_output_exe(TCCState2 *s, const char *filename)
2025-02-11 12:07:04 +00:00
{
2025-02-11 19:16:44 +00:00
return (0);
}
2025-02-11 12:07:04 +00:00
2025-02-11 19:16:44 +00:00
int
coff_load_object(TCCState2 *s, int fd, size_t file_offset)
{
COFFFileHeader chdr;
return (0);
2025-02-11 12:07:04 +00:00
}