#include #include #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 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); } if (first->read != seg->read || first->write != seg->write || first->execute != seg->execute) { ERROR("segment '%s' doest not have matching RWX", ent->name); } } else { ent->off = seg->new_off; ent->vaddr = seg->new_vaddr; } ent->parts[ent->len++] = seg; 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; }