ld: implement an actual program loader
This commit is contained in:
211
sys/ld/image-list.c
Normal file
211
sys/ld/image-list.c
Normal file
@@ -0,0 +1,211 @@
|
||||
#include "image-list.h"
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
#include <mango/log.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static BTREE_DEFINE_SIMPLE_GET(
|
||||
struct image_list_entry,
|
||||
uint64_t,
|
||||
e_node,
|
||||
e_hash,
|
||||
get_entry);
|
||||
static BTREE_DEFINE_SIMPLE_INSERT(
|
||||
struct image_list_entry,
|
||||
e_node,
|
||||
e_hash,
|
||||
put_entry);
|
||||
|
||||
void image_list_init(struct image_list *list)
|
||||
{
|
||||
memset(list, 0x0, sizeof *list);
|
||||
}
|
||||
|
||||
void image_list_cleanup(struct image_list *list)
|
||||
{
|
||||
}
|
||||
|
||||
extern struct image_list_bucket *convert_to_bucket(
|
||||
struct btree *tree,
|
||||
struct image_list_leaf *leaf)
|
||||
{
|
||||
btree_delete(tree, &leaf->l_base.e_node);
|
||||
|
||||
struct image_list_bucket *bucket = malloc(sizeof *bucket);
|
||||
if (!bucket) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bucket->b_base.e_hash = leaf->l_base.e_hash;
|
||||
bucket->b_base.e_type = IMAGE_LIST_ENTRY_BUCKET;
|
||||
put_entry(tree, &bucket->b_base);
|
||||
|
||||
queue_push_back(&bucket->b_items, &leaf->l_base.e_entry);
|
||||
|
||||
return bucket;
|
||||
}
|
||||
|
||||
extern void image_list_put(
|
||||
struct image_list *list,
|
||||
struct image_list_leaf *item)
|
||||
{
|
||||
uint64_t hash = hash_string(item->l_name);
|
||||
item->l_base.e_type = IMAGE_LIST_ENTRY_LEAF;
|
||||
item->l_base.e_hash = hash;
|
||||
|
||||
struct image_list_entry *entry = get_entry(&list->l_items, hash);
|
||||
if (!entry) {
|
||||
put_entry(&list->l_items, &item->l_base);
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry->e_type == IMAGE_LIST_ENTRY_BUCKET) {
|
||||
struct image_list_bucket *bucket
|
||||
= (struct image_list_bucket *)entry;
|
||||
queue_push_back(&bucket->b_items, &item->l_base.e_entry);
|
||||
return;
|
||||
}
|
||||
|
||||
struct image_list_leaf *leaf = (struct image_list_leaf *)entry;
|
||||
struct image_list_bucket *bucket
|
||||
= convert_to_bucket(&list->l_items, leaf);
|
||||
if (!bucket) {
|
||||
return;
|
||||
}
|
||||
|
||||
queue_push_back(&bucket->b_items, &item->l_base.e_entry);
|
||||
}
|
||||
|
||||
extern struct image_list_leaf *image_list_get(
|
||||
struct image_list *list,
|
||||
const char *name)
|
||||
{
|
||||
uint64_t hash = hash_string(name);
|
||||
struct image_list_entry *entry = get_entry(&list->l_items, hash);
|
||||
if (!entry) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (entry->e_type) {
|
||||
case IMAGE_LIST_ENTRY_LEAF: {
|
||||
struct image_list_leaf *leaf = (struct image_list_leaf *)entry;
|
||||
if (!strcmp(leaf->l_name, name)) {
|
||||
return leaf;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case IMAGE_LIST_ENTRY_BUCKET: {
|
||||
struct image_list_bucket *bucket
|
||||
= (struct image_list_bucket *)entry;
|
||||
struct queue_entry *cur = queue_first(&bucket->b_items);
|
||||
while (cur) {
|
||||
struct image_list_leaf *leaf = QUEUE_CONTAINER(
|
||||
struct image_list_leaf,
|
||||
l_base.e_entry,
|
||||
cur);
|
||||
if (!strcmp(leaf->l_name, name)) {
|
||||
return leaf;
|
||||
}
|
||||
|
||||
cur = queue_next(cur);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void image_list_iterator_begin(
|
||||
struct image_list_iterator *it,
|
||||
struct image_list *list)
|
||||
{
|
||||
memset(it, 0x0, sizeof *it);
|
||||
struct btree_node *node = btree_first(&list->l_items);
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
it->it_cur = QUEUE_CONTAINER(
|
||||
struct image_list_entry,
|
||||
e_node,
|
||||
node);
|
||||
if (it->it_cur->e_type == IMAGE_LIST_ENTRY_LEAF) {
|
||||
it->it_leaf = (struct image_list_leaf *)it->it_cur;
|
||||
return;
|
||||
}
|
||||
|
||||
struct image_list_bucket *bucket
|
||||
= (struct image_list_bucket *)it->it_cur;
|
||||
struct queue_entry *entry = queue_first(&bucket->b_items);
|
||||
if (!entry) {
|
||||
node = btree_next(node);
|
||||
continue;
|
||||
}
|
||||
|
||||
it->it_leaf = QUEUE_CONTAINER(
|
||||
struct image_list_leaf,
|
||||
l_base.e_entry,
|
||||
entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void image_list_iterator_move_next(struct image_list_iterator *it)
|
||||
{
|
||||
if (!it->it_cur || !it->it_leaf) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (it->it_cur->e_type == IMAGE_LIST_ENTRY_LEAF) {
|
||||
/* current entry is a leaf */
|
||||
struct queue_entry *next
|
||||
= queue_next(&it->it_leaf->l_base.e_entry);
|
||||
if (next) {
|
||||
it->it_leaf = QUEUE_CONTAINER(
|
||||
struct image_list_leaf,
|
||||
l_base.e_entry,
|
||||
next);
|
||||
}
|
||||
}
|
||||
|
||||
struct btree_node *node = btree_next(&it->it_cur->e_node);
|
||||
if (!node) {
|
||||
it->it_cur = NULL;
|
||||
it->it_leaf = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
it->it_cur = BTREE_CONTAINER(
|
||||
struct image_list_entry,
|
||||
e_node,
|
||||
node);
|
||||
if (it->it_cur->e_type == IMAGE_LIST_ENTRY_LEAF) {
|
||||
/* next entry is a leaf */
|
||||
it->it_leaf = (struct image_list_leaf *)it->it_cur;
|
||||
return;
|
||||
}
|
||||
|
||||
struct image_list_bucket *bucket
|
||||
= (struct image_list_bucket *)it->it_cur;
|
||||
struct queue_entry *entry = queue_first(&bucket->b_items);
|
||||
if (!entry) {
|
||||
continue;
|
||||
}
|
||||
|
||||
it->it_leaf = QUEUE_CONTAINER(
|
||||
struct image_list_leaf,
|
||||
l_base.e_entry,
|
||||
entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user