diff options
author | Ian Moffett <ian@osmora.org> | 2025-04-10 00:57:43 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-04-10 01:24:11 -0400 |
commit | d869a6b0c3315de350799f4f1fdd4bc3538b0855 (patch) | |
tree | da2efecc1f950a1cadb2adac834d2a02e9669f93 | |
parent | fcdf12d4b12bcbfe604c9ba683796042fff26eb2 (diff) |
core: Add core impl
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r-- | src/core.c | 182 | ||||
-rw-r--r-- | src/include/ldo/ldo.h | 58 | ||||
-rw-r--r-- | src/include/ldo/object.h | 80 | ||||
-rw-r--r-- | src/main.c | 41 | ||||
-rw-r--r-- | src/object.c | 93 |
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_ */ @@ -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; +} |