mips/masm/sectab.c
2024-09-11 12:06:09 -04:00

167 lines
3.4 KiB
C

#include <string.h>
#include <stdlib.h>
#include <mips.h>
#include <merror.h>
#include <mlimits.h>
#include "asm.h"
#define SECTBL_INIT_LEN 8
static const char inital_section[MAX_LEX_LENGTH] = "data";
int sectab_init(struct section_table *sectab)
{
sectab->size = SECTBL_INIT_LEN;
sectab->len = 0;
sectab->sections = malloc(sizeof(struct section) * SECTBL_INIT_LEN);
if (sectab->sections == NULL) {
ERROR("cannot alloc");
return M_ERROR;
}
if (sectab_alloc(sectab, &sectab->current, inital_section))
return M_ERROR;
return M_SUCCESS;
}
void sectab_free(struct section_table *sectab)
{
for (size_t i = 0; i < sectab->len; i++) {
reltab_free(&sectab->sections[i].reltab);
free(sectab->sections[i].entries);
}
free(sectab->sections);
}
struct section_settings {
const char *name;
bool read;
bool write;
bool execute;
size_t align;
};
static struct section_settings default_section_settings[] = {
{"data", true, true, false, 1},
{"bss", true, true, false, 1},
{"rodata", true, false, false, 1},
{"text", true, false, true, 4},
};
int sectab_alloc(struct section_table *sectab, struct section **res,
const char name[MAX_LEX_LENGTH])
{
if (sectab->len >= sectab->size) {
sectab->size *= 2;
sectab->sections = realloc(sectab->sections,
sizeof(struct section) * sectab->size);
if (sectab->sections == NULL) {
ERROR("cannot realloc");
return M_ERROR;
}
}
/* set the sectio defaults */
struct section *sec;
sec = &sectab->sections[sectab->len];
strcpy(sec->name,name);
sec->len = 0;
sec->size = SECTBL_INIT_LEN;
sec->alignment = 1;
sec->read = true;
sec->write = true;
sec->execute = false;
sec->index = sectab->len;
sec->entries = malloc(sizeof(struct section_entry) * SECTBL_INIT_LEN);
if (reltab_init(&sec->reltab))
return M_ERROR;
/* overwrite the default if the given name has their own
* defaults */
for (int i = 0; i < 4; i++) {
struct section_settings *set = &default_section_settings[i];
if (strcmp(set->name, name) == 0) {
sec->read = set->read;
sec->write = set->write;
sec->execute = set->execute;
sec->alignment = set->align;
break;
}
}
if (sec->entries == NULL) {
ERROR("cannot alloc");
return M_ERROR;
}
sectab->len++;
*res = sec;
return M_SUCCESS;
}
int sectab_get(struct section_table *sectab, struct section **sec,
const char name[MAX_LEX_LENGTH])
{
for (size_t i = 0; i < sectab->len; i++) {
struct section *temp = &sectab->sections[i];
if (strcmp(name, temp->name) == 0) {
if (sec != NULL)
*sec = temp;
return M_SUCCESS;
}
}
return M_ERROR;
}
int sec_push(struct section *section, struct section_entry entry)
{
if (section->len >= section->size) {
section->size *= 2;
void *new = realloc(section->entries,
sizeof(struct section_entry) * section->size);
if (new == NULL) {
ERROR("cannot realloc");
return M_ERROR;
}
section->entries = new;
}
section->entries[section->len++] = entry;
return M_SUCCESS;
}
size_t sec_size(struct section *sec)
{
size_t n = 0;
for (size_t i = 0; i < sec->len; i++) {
size_t t = sec->entries[i].size;
size_t m = t % sec->alignment;
if (m)
t += sec->alignment - m;
n += t;
}
return n;
}
size_t sec_index(struct section *sec, size_t idx)
{
size_t n = 0;
for (size_t i = 0; i < idx; i++) {
size_t t = sec->entries[i].size;
size_t m = t % sec->alignment;
if (m)
t += sec->alignment - m;
n += t;
}
return n;
}