mips/mld/segtab.c

152 lines
3.1 KiB
C
Raw Normal View History

2024-09-22 20:02:42 +00:00
#include <stdlib.h>
#include <merror.h>
#include "link.h"
#define SEGTAB_INIT_SIZE 8
int segtab_init(struct segment_table *segtab)
{
segtab->len = 0;
segtab->size = SEGTAB_INIT_SIZE;
segtab->entries = malloc(sizeof(struct segment_table_entry) *
SEGTAB_INIT_SIZE);
if (segtab->entries == NULL) {
PERROR("cannot alloc");
return M_ERROR;
}
return M_SUCCESS;
}
void segtab_free(struct segment_table *segtab)
{
for (uint32_t i = 0; i < segtab->len; i++) {
segtab_ent_free(&segtab->entries[i]);
}
free(segtab->entries);
}
/* create a new entry with <seg> as its first segment part */
int segtab_push(struct segment_table *segtab, struct segment_table_entry **res,
struct segment *seg)
{
if (segtab->len >= segtab->size) {
uint32_t size = segtab->size * 2;
void *new = realloc(segtab->entries,
sizeof(struct segment_table_entry) * size);
if (new == NULL) {
PERROR("cannot relloc");
return M_ERROR;
}
segtab->size = size;
segtab->entries = new;
}
struct segment_table_entry ent;
if (segtab_ent_init(&ent))
return M_ERROR;
ent.name = seg->name;
ent.vaddr = seg->vaddr;
ent.off = seg->off;
if (segtab_ent_push(&ent, seg)) {
segtab_ent_free(&ent);
return M_ERROR;
}
segtab->entries[segtab->len] = ent;
if (res != NULL)
*res = &segtab->entries[segtab->len];
segtab->len++;
return M_SUCCESS;
}
/* find a segment table entry with a given name */
int segtab_get(struct segment_table *segtab, struct segment_table_entry **ent,
const char *name)
{
for (uint32_t i = 0; i < segtab->len; i++) {
const char *segname = segtab->entries[i].name;
if (strcmp(name, segname) != 0)
continue;
*ent = &segtab->entries[i];
return M_SUCCESS;
}
return M_ERROR;
}
int segtab_ent_init(struct segment_table_entry *ent)
{
ent->len = 0;
ent->size = SEGTAB_INIT_SIZE;
ent->parts = malloc(sizeof(struct segment *) *
SEGTAB_INIT_SIZE);
if (ent->parts == NULL) {
PERROR("cannot alloc");
return M_ERROR;
}
return M_SUCCESS;
}
void segtab_ent_free(struct segment_table_entry *ent)
{
free(ent->parts);
}
int segtab_ent_push(struct segment_table_entry *ent, struct segment *seg)
{
if (ent->len >= ent->size) {
uint32_t size = ent->size * 2;
void *new = realloc(ent->parts,
sizeof(struct segment *) * size);
if (new == NULL) {
PERROR("cannot relloc");
return M_ERROR;
}
ent->size = size;
ent->parts = new;
}
if (ent->len > 0) {
struct segment *first = ent->parts[0];
if (first->align != seg->align) {
ERROR("segment '%s' doest not have matching alignment",
ent->name);
2024-09-22 20:44:54 +00:00
return M_ERROR;
2024-09-22 20:02:42 +00:00
}
if (first->read != seg->read ||
first->write != seg->write ||
first->execute != seg->execute) {
ERROR("segment '%s' doest not have matching RWX",
ent->name);
2024-09-22 20:44:54 +00:00
return M_ERROR;
2024-09-22 20:02:42 +00:00
}
} else {
ent->off = seg->new_off;
ent->vaddr = seg->new_vaddr;
}
ent->parts[ent->len++] = seg;
2024-09-23 03:39:22 +00:00
seg->ent = ent;
2024-09-22 20:02:42 +00:00
return M_SUCCESS;
}
uint32_t segtab_ent_size(struct segment_table_entry *ent)
{
uint32_t size = 0;
for (uint32_t i = 0; i < ent->len; i++) {
size += ent->parts[i]->size;
}
return size;
}