summaryrefslogtreecommitdiff
path: root/mld/link.c
blob: 2593806991c6f23d80e787c1d6cd785a69ad0b57 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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;
}