summaryrefslogtreecommitdiff
path: root/mld/link.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--mld/link.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/mld/link.c b/mld/link.c
new file mode 100644
index 0000000..2593806
--- /dev/null
+++ b/mld/link.c
@@ -0,0 +1,62 @@
+#include <stdlib.h>
+#include <merror.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "link.h"
+
+static int load_objects(struct linker *linker)
+{
+ linker->objects = malloc(sizeof(struct object) *
+ linker->args->in_count);
+ linker->obj_len = 0;
+
+ if (linker->objects == NULL) {
+ ERROR("cannot alloc");
+ return M_ERROR;
+ }
+
+ for (int i = 0; i < linker->args->in_count; i++) {
+ char *path = linker->args->in_files[i];
+ struct object *obj = &linker->objects[linker->obj_len];
+
+ // check for duplicate
+ for (size_t j = 0; j < linker->obj_len; j++) {
+ const char *dupname = linker->objects[j].name;
+ struct stat st, st2;
+ if (stat(path, &st) || stat(dupname, &st2))
+ continue;
+ if (st.st_ino == st2.st_ino)
+ goto skip_obj;
+ }
+
+ // load obj file
+ linker->obj_len++;
+ if (object_load(obj, path))
+ return M_ERROR;
+skip_obj:
+ }
+
+ return M_SUCCESS;
+}
+
+static void linker_free(struct linker *linker)
+{
+ if (linker->objects != NULL) {
+ for (size_t i = 0; i < linker->obj_len; i++)
+ object_free(&linker->objects[i]);
+ free(linker->objects);
+ }
+}
+
+int link_files(struct linker_arguments args) {
+ struct linker linker;
+ linker.args = &args;
+ int res = M_SUCCESS;
+
+ if (res == M_SUCCESS)
+ res = load_objects(&linker);
+
+ linker_free(&linker);
+ return res;
+}