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;
|
|
|
|
}
|