aboutsummaryrefslogtreecommitdiff
path: root/src/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core.c')
-rw-r--r--src/core.c182
1 files changed, 182 insertions, 0 deletions
diff --git a/src/core.c b/src/core.c
new file mode 100644
index 0000000..fc1bf70
--- /dev/null
+++ b/src/core.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2025 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <ldo/ldo.h>
+#include <ldo/file.h>
+#include <ldo/elf.h>
+#include <ldo/object.h>
+#include <ldo/cdefs.h>
+#include <lz4.h>
+
+/*
+ * Too many defines for one arch, just simplify
+ * it and use __PPC64__, fucking hell.
+ */
+#if defined(__ppc64__) || defined(_ARCH_PPC64)
+#if !defined(__PPC64__)
+#define __PPC64__
+#endif /* !defined(__PPC64__) */
+#endif /* defined(__ppc64__) || ... */
+
+static struct sarry_objq objq;
+
+/*
+ * Machine string map, LDO machine defines
+ * are mapped one-to-one.
+ */
+static const char *machstrmap[] = {
+ [LDO_X86_64] = "x86_64",
+ [LDO_AARCH64] = "aarch64",
+ [LDO_PPC64] = "ppc64",
+ [LDO_UNKNOWN] = "unknown"
+};
+
+__always_inline
+static inline const char *
+ldo_machstr(ldo_mach_t type)
+{
+ if (type > LDO_UNKNOWN)
+ type = LDO_UNKNOWN;
+
+ return machstrmap[type];
+}
+
+/*
+ * Returns an LDO machine type for the
+ * current platform.
+ */
+__always_inline static inline ldo_mach_t
+getmach(void)
+{
+#if defined(__x86_64__) || defined(_M_X64)
+ return LDO_X86_64;
+#elif defined(__aarch64__) || defined(_M_ARM64)
+ return LDO_AARCH64;
+#elif defined(__PPC64__)
+ return LDO_PPC64;
+#else
+ /* At this point bail the hell out */
+ printf("Unknown machine... please run machchk.sh\n");
+ return LDO_UNKNOWN;
+#endif
+}
+
+/*
+ * Returns an LDO machine type for the target
+ * ELF platform.
+ */
+static inline ldo_mach_t
+ldo_elf64_mach(const Elf64_Ehdr *eh)
+{
+ switch (eh->e_machine) {
+ case EM_X86_64:
+ return LDO_X86_64;
+ case EM_AARCH64:
+ return LDO_X86_64;
+ case EM_PPC64:
+ return LDO_PPC64;
+ }
+
+ return LDO_UNKNOWN;
+}
+
+/*
+ * Perform preliminary checks on the ELF header
+ * and warn/error as needed.
+ */
+static inline int
+ldo_elf64_chk(const Elf64_Ehdr *eh)
+{
+ ldo_mach_t target, current;
+ const char *tstr, *cstr;
+
+ /* Ensure magic is correct */
+ if (eh->e_ident[EI_MAG0] != ELFMAG0)
+ return -ENOEXEC;
+ if (eh->e_ident[EI_MAG1] != ELFMAG1)
+ return -ENOEXEC;
+ if (eh->e_ident[EI_MAG2] != ELFMAG2)
+ return -ENOEXEC;
+ if (eh->e_ident[EI_MAG3] != ELFMAG3)
+ return -ENOEXEC;
+
+ target = ldo_elf64_mach(eh);
+ current = ldo_elf64_mach(eh);
+
+ tstr = ldo_machstr(target);
+ cstr = ldo_machstr(current);
+ vlog("target=%s, current=%s\n", tstr, cstr);
+
+ if (target != current) {
+ fprintf(stdout, "warn: target %s will not run on %s\n", tstr, cstr);
+ }
+
+ return 0;
+}
+
+void
+ldo_load(const char *pathname)
+{
+ Elf64_Ehdr *eh;
+ struct ldo_file *lfp;
+ int err;
+
+ if ((lfp = ldo_open(pathname, O_RDONLY)) == NULL) {
+ fprintf(stderr, "ldo_load: failed to open \"%s\"\n", pathname);
+ return;
+ }
+
+ eh = (Elf64_Ehdr *)LDO_BUFSTREAM(lfp->data);
+ err = ldo_elf64_chk(eh);
+
+ /* Make sure our checks went fine */
+ if (err == -ENOEXEC) {
+ fprintf(stderr, "ldo_load: bad magic for \"%s\"\n", pathname);
+ return;
+ }
+ if (err < 0) {
+ fprintf(stderr, "ldo_load: failed to load obj (retval=%d)\n", err);
+ return;
+ }
+
+ vlog("entrypoint=0x%llx\n", eh->e_entry);
+ vlog("program headers: %d\n", eh->e_phnum);
+ vlog("section headers: %d\n", eh->e_shnum);
+ ldo_close(lfp);
+}
+
+int
+ldo_init(void)
+{
+ vlog("Initializing object queue...\n");
+ return sarry_init_objq(&objq, OBJQ_CAP);
+}