aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2025-04-10 00:57:43 -0400
committerIan Moffett <ian@osmora.org>2025-04-10 01:24:11 -0400
commitd869a6b0c3315de350799f4f1fdd4bc3538b0855 (patch)
treeda2efecc1f950a1cadb2adac834d2a02e9669f93
parentfcdf12d4b12bcbfe604c9ba683796042fff26eb2 (diff)
core: Add core impl
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r--src/core.c182
-rw-r--r--src/include/ldo/ldo.h58
-rw-r--r--src/include/ldo/object.h80
-rw-r--r--src/main.c41
-rw-r--r--src/object.c93
5 files changed, 451 insertions, 3 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);
+}
diff --git a/src/include/ldo/ldo.h b/src/include/ldo/ldo.h
new file mode 100644
index 0000000..e7618f7
--- /dev/null
+++ b/src/include/ldo/ldo.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#ifndef LDO_H_
+#define LDO_H_
+
+#include <stdint.h>
+#include <ldo/file.h>
+
+/* Machine types */
+#define LDO_X86_64 0x0000
+#define LDO_AARCH64 0x0001
+#define LDO_PPC64 0x0002
+#define LDO_UNKNOWN 0x0003
+
+#define LDO_F_VERBOSE (1 << 0)
+
+/* Verbose log */
+#define vlog(...) do { \
+ if ((ldo_rtflags() & LDO_F_VERBOSE) != 0) { \
+ printf(__VA_ARGS__); \
+ } \
+ } while (0);
+
+typedef uint16_t ldo_flags_t;
+typedef uint8_t ldo_mach_t;
+
+ldo_flags_t ldo_rtflags(void);
+void ldo_load(const char *pathname);
+int ldo_init(void);
+
+#endif /* !LDO_H_ */
diff --git a/src/include/ldo/object.h b/src/include/ldo/object.h
new file mode 100644
index 0000000..773bafe
--- /dev/null
+++ b/src/include/ldo/object.h
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+#ifndef OBJECT_H_
+#define OBJECT_H_
+
+#include <sys/queue.h>
+#include <stddef.h>
+
+/* Pin it here, can be adjusted (XXX: careful!) */
+#define OBJQ_MAXCAP 1024
+
+/* Default cap */
+#define OBJQ_CAP 512
+
+/*
+ * Represents "static array" objects to be
+ * queued up before being injected into its
+ * resulting file's .static_array section.
+ *
+ * @pathname: Object file pathname.
+ * @cdata: Compressed data buffer.
+ * @size: Size of compressed data.
+ * @real_size: Size of data when decompressed.
+ */
+struct sarry_obj {
+ const char *name;
+ const char *cdata;
+ size_t size;
+ size_t real_size;
+ TAILQ_ENTRY(sarry_obj) link;
+};
+
+/*
+ * Represents a "static array" object queue
+ * which holds one or more "static array"
+ * objects. Once filled, all compressed objects
+ * are injected into a final ELF.
+ *
+ * @q: TAILQ head.
+ * @count: Number of objects.
+ * @cap: Object queue capacity.
+ */
+struct sarry_objq {
+ TAILQ_HEAD(, sarry_obj) q;
+ size_t count;
+ size_t cap;
+};
+
+int sarry_init_objq(struct sarry_objq *qp, size_t cap);
+int sarry_objq_in(struct sarry_objq *qp, struct sarry_obj *op);
+int sarry_objq_flush(struct sarry_objq *qp, struct sarry_obj *op);
+
+#endif /* !OBJECT_H_ */
diff --git a/src/main.c b/src/main.c
index bec0265..30612a7 100644
--- a/src/main.c
+++ b/src/main.c
@@ -28,24 +28,59 @@
*/
#include <stdio.h>
-#include <ldo/elf.h>
+#include <unistd.h>
#include <ldo/file.h>
+#include <ldo/ldo.h>
+
+static ldo_flags_t flags = 0;
static void
usage(const char *argv0)
{
- fprintf(stderr, "Usage: %s <*.o>\n", argv0);
+ fprintf(stderr, "Usage: %s <*.oo>\n", argv0);
+}
+
+/*
+ * Get linker runtime flags
+ */
+ldo_flags_t
+ldo_rtflags(void)
+{
+ return flags;
}
int
main(int argc, char **argv)
{
- struct ldo_file *lfp;
+ char c;
+ int i;
if (argc < 2) {
usage(argv[0]);
return -1;
}
+ while ((c = getopt(argc, argv, "hv")) >= 0) {
+ switch (c) {
+ case 'h':
+ usage(argv[0]);
+ return 0;
+ case 'v':
+ flags |= LDO_F_VERBOSE;
+ break;
+ case '?':
+ fprintf(stderr, "Bad argument: -%c\n", optopt);
+ break;
+ }
+ }
+
+ ldo_init();
+
+ /* Load object files */
+ if (optind < argc) {
+ for (i = optind; i < argc; ++i) {
+ ldo_load(argv[i]);
+ }
+ }
return 0;
}
diff --git a/src/object.c b/src/object.c
new file mode 100644
index 0000000..4200ad6
--- /dev/null
+++ b/src/object.c
@@ -0,0 +1,93 @@
+/*
+ * 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/queue.h>
+#include <sys/errno.h>
+#include <ldo/object.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <math.h>
+
+/*
+ * Initialize an object queue.
+ *
+ * @qp: Object queue pointer.
+ * @cap: Capacity
+ *
+ * XXX: `cap' must be a power-of-two and must not exceed
+ * OBJQ_MAXCAP.
+ */
+int
+sarry_init_objq(struct sarry_objq *qp, size_t cap)
+{
+ uint8_t e;
+
+ /*
+ * Power-of-two sizes are good for block
+ * based processing
+ */
+ if ((OBJQ_MAXCAP & 1) != 0) {
+ fprintf(stderr, "OBJQ_MAXCAP is not a power of two\n");
+ return -EINVAL;
+ }
+
+ /* Ensure `cap' doesn't exceed the limit */
+ if (cap > OBJQ_MAXCAP) {
+ e = log2(OBJQ_MAXCAP);
+ fprintf(stderr, "cap exceeds OBJQ_MAXCAP, rejecting...\n");
+ fprintf(stderr, "cap must be <= 2^%d (%d) entries\n", e, cap);
+ return -EINVAL;
+ }
+
+ TAILQ_INIT(&qp->q);
+ qp->count = 0;
+ qp->cap = cap;
+}
+
+/*
+ * Insert an object into an object queue.
+ *
+ * @qp: Object queue pointer.
+ * @op: Object pointer.
+ */
+int
+sarry_objq_in(struct sarry_objq *qp, struct sarry_obj *op)
+{
+ size_t new_count;
+
+ new_count = (qp->count + 1);
+ if (new_count > OBJQ_MAXCAP) {
+ fprintf(stderr, "sarry_insert: object queue full\n");
+ return -ENOSPC;
+ }
+
+ TAILQ_INSERT_TAIL(&qp->q, op, link);
+ ++qp->count;
+ return 0;
+}