-config LIBUKLIBID
+menuconfig LIBUKLIBID
bool "uklibid: Library identifier"
- default n
+ default y
# FIXME: We actually depend on <uk/assert.h> but lib/ukdebug also
# depends on us. If we specify the dependency here, it creates a
# circular dependency that KConfig doesn't like. However, we
# build, so we comment out the dependency here. Of course, this
# is not accurate.
#select LIBUKDEBUG
+
+if LIBUKLIBID
+config LIBUKLIBID_INFO
+ bool "Embedded library metadata"
+ default y
+
+ if LIBUKLIBID_INFO
+ menu "Global metadata"
+ config LIBUKLIBID_INFO_UKFULLVERSION
+ bool "Full unikraft version"
+ default y
+ help
+ If enabled, the full Unikraft version including
+ Git SHA is embedded. Otherwise, only the short
+ Unikraft version is stored.
+
+ config LIBUKLIBID_INFO_UKCODENAME
+ bool "Unikraft codename"
+ help
+ If enabled, the Unikraft release codename is
+ stored as part of the global metadata
+ information.
+
+ config LIBUKLIBID_INFO_COMPILER
+ bool "Compiler (CC) information"
+ help
+ Enables storing the C compiler ($(CC)) that was
+ used for during compilation for the unikernel
+ image.
+ endmenu
+
+ menu "Per library metadata"
+ config LIBUKLIBID_INFO_LIB_UKVERSION
+ bool "Unikraft version"
+ help
+ If enabled, the Unikraft version is included
+ to each library.
+
+ config LIBUKLIBID_INFO_LIB_UKFULLVERSION
+ bool "Full version"
+ depends on LIBUKLIBID_INFO_LIB_UKVERSION
+ help
+ Instead of the short Unikraft version, the full
+ Unikraft version including Git SHA is embedded
+ to each library.
+
+ config LIBUKLIBID_INFO_LIB_UKCODENAME
+ bool "Unikraft codename"
+ help
+ If enabled, the Unikraft release codename is
+ stored as part of each library metadata
+ information.
+
+ config LIBUKLIBID_INFO_LIB_COMPILER
+ bool "Compiler (CC) information"
+ default y
+ help
+ Enables storing the C compiler ($(CC)) that was
+ used for each library.
+ endmenu
+endif
LIBUKLIBID_EXPORTSYMS_AWKINCLUDES-y += $(LIBUKLIBID_BUILD)/libraries.in
LIBUKLIBID_EXPORTS-y += $(LIBUKLIBID_BUILD)/exportsyms.uk
+EACHOLIB_SRCS-$(CONFIG_LIBUKLIBID_INFO) += $(LIBUKLIBID_BASE)/libinfo.S|libuklibid
+ASFLAGS += -D__LIBUKLIBID_COMPILER__="$(CC_INFO)"
+LIBUKLIBID_SRCS-$(CONFIG_LIBUKLIBID_INFO) += $(LIBUKLIBID_BASE)/infosec.ld
+LIBUKLIBID_SRCS-$(CONFIG_LIBUKLIBID_INFO) += $(LIBUKLIBID_BASE)/libinfo.S|global
+LIBUKLIBID_LIBINFO_GLOBAL_FLAGS-y += -D__GLOBALINFO__
+
UK_PREPARE-$(CONFIG_LIBUKLIBID) += $(LIBUKLIBID_BUILD)/libraries.in.new
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause */
+/* Copyright (c) 2023, Unikraft GmbH and The Unikraft Authors.
+ * Licensed under the BSD-3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ */
+#ifndef __UK_LIBID_INFO_H__
+#define __UK_LIBID_INFO_H__
+
+#include <uk/arch/types.h>
+#include <uk/essentials.h>
+
+/*
+ * Library information is stored in the special section " .uk_libinfo". For
+ * each library there is one `struct uk_libid_info_hdr` generated. Each header
+ * can contain multiple `struct uk_libid_info_rec` records. A library name
+ * record (`UKLI_REC_LIBNAME`) is the only mandatory record type for each
+ * library.
+ * Additionally, a single header is created for global information, which
+ * differs from the library headers in that it does not contain a record for a
+ * library name.
+ *
+ * Layout for each information header:
+ *
+ * _____________
+ * +--------------------------+ \
+ * | struct uk_libid_info_hdr | |
+ * | | > hdr->len
+ * +--------------------------+ |
+ * | struct uk_libid_info_rec | |
+ * +--------------------------+ -. |
+ * | struct uk_libid_info_rec | > rec->len |
+ * | | | |
+ * +--------------------------+ -` |
+ * : . . . : :
+ * +--------------------------+ |
+ * | struct uk_libid_info_rec | |
+ * | | |
+ * +--------------------------+ ____________/
+ */
+
+/*
+ * NOTE: The layout version needs only be updated if the structs
+ * `uk_libid_info_rec` and `uk_libid_info_hdr` are updated.
+ */
+ #define UKLI_LAYOUT 0x0001
+
+/*
+ * NOTE: In order to keep backwards compatibility with pre-compiled
+ * libraries, this list should only be extended with new entries.
+ */
+#define UKLI_REC_LIBNAME 0x0001 /* C-string, absent for global hdr */
+#define UKLI_REC_COMMENT 0x0002 /* C-string */
+#define UKLI_REC_VERSION 0x0003 /* C-string */
+#define UKLI_REC_LICENSE 0x0004 /* C-string */
+#define UKLI_REC_GITDESC 0x0005 /* C-string */
+#define UKLI_REC_UKVERSION 0x0006 /* C-string, Unikraft version only */
+#define UKLI_REC_UKFULLVERSION 0x0007 /* C-string, UK version with gitsha */
+#define UKLI_REC_UKCODENAME 0x0008 /* C-string */
+#define UKLI_REC_UKCONFIG 0x0009 /* binary data */
+#define UKLI_REC_UKCONFIGGZ 0x000A /* binary data */
+#define UKLI_REC_COMPILER 0x000B /* C-string */
+#define UKLI_REC_COMPILEDATE 0x000C /* C-string */
+#define UKLI_REC_COMPILEDBY 0x000D /* C-string */
+#define UKLI_REC_COMPILEDBYASSOC 0x000E /* C-string */
+#define UKLI_REC_COMPILEOPTS 0x000F /* __u32 flags */
+
+#if !__ASSEMBLY__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct uk_libid_info_rec {
+ __u16 type; /* record type */
+ __u32 len; /* including record header */
+ char data[]; /* raw data */
+} __packed __align(1);
+
+/*
+ * NOTE: Due to binary cross-compatibility, the sizes, offsets, data types and
+ * meanings must remain the same regardless of the layout version:
+ * `len` and `version`.
+ */
+struct uk_libid_info_hdr {
+ __u32 len; /* including header */
+ __u16 version; /* layout version */
+ struct uk_libid_info_rec recs[];
+} __packed __align(1);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !__ASSEMBLY__ */
+#endif /* __UK_LIBID_INFO_H__ */
--- /dev/null
+SECTIONS
+{
+ . = ALIGN(1);
+ .uk_libinfo :
+ {
+ KEEP (*(.uk_libinfo))
+ }
+}
+INSERT AFTER .rodata;
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause */
+/* Copyright (c) 2023, Unikraft GmbH and The Unikraft Authors.
+ * Licensed under the BSD-3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ */
+#include <uk/config.h>
+#include <uk/libid/info.h>
+#include <uk/arch/types.h>
+
+#define RECORD(type, data) \
+ .align 1 ; \
+1: .__u16 type /* type */ ; \
+ .__u32 2f - 1b /* len */ ; \
+ data /* data[] */ ; \
+2: .align 1
+
+.pushsection .uk_libinfo, "a"
+ .align 1
+3: .__u32 4f - 3b /* len */
+ .__u16 UKLI_LAYOUT /* version */
+
+#if __GLOBALINFO__
+ /* Only one global header per unikernel is generated */
+ /* NOTE: Global metadata do not have a libname record */
+#if CONFIG_LIBUKLIBID_INFO_UKFULLVERSION
+ RECORD(UKLI_REC_UKFULLVERSION, .asciz STRINGIFY(UK_FULLVERSION))
+#else /* !CONFIG_LIBUKLIBID_INFO_UKFULLVERSION */
+ RECORD(UKLI_REC_UKVERSION, .asciz STRINGIFY(UK_VERSION))
+#endif /* !CONFIG_LIBUKLIBID_INFO_UKFULLVERSION */
+#if CONFIG_LIBUKLIBID_INFO_UKCODENAME
+ RECORD(UKLI_REC_UKCODENAME, .asciz STRINGIFY(UK_CODENAME))
+#endif /* CONFIG_LIBUKLIBID_INFO_UKCODENAME */
+#if CONFIG_LIBUKLIBID_INFO_COMPILER
+ RECORD(UKLI_REC_COMPILER,
+ .asciz STRINGIFY(__LIBUKLIBID_COMPILER__))
+#endif /* CONFIG_LIBUKLIBID_INFO_COMPILER */
+
+#else /* !__GLOBALINFO__ */
+ /* Records per library */
+ /* NOTE: The libname record is mandatory */
+ RECORD(UKLI_REC_LIBNAME, .asciz STRINGIFY(__LIBNAME__))
+#if CONFIG_LIBUKLIBID_INFO_LIB_UKVERSION
+#if CONFIG_LIBUKLIBID_INFO_LIB_UKFULLVERSION
+ RECORD(UKLI_REC_UKFULLVERSION, .asciz STRINGIFY(UK_FULLVERSION))
+#else /* !CONFIG_LIBUKLIBID_INFO_LIB_UKVERSION */
+ RECORD(UKLI_REC_UKVERSION, .asciz STRINGIFY(UK_VERSION))
+#endif /* !CONFIG_LIBUKLIBID_INFO_LIB_UKVERSION */
+#endif /* CONFIG_LIBUKLIBID_INFO_LIB_UKVERSION */
+#if CONFIG_LIBUKLIBID_INFO_LIB_UKCODENAME
+ RECORD(UKLI_REC_UKCODENAME, .asciz STRINGIFY(UK_CODENAME))
+#endif /* CONFIG_LIBUKLIBID_INFO_LIB_UKCODENAME */
+#if CONFIG_LIBUKLIBID_INFO_LIB_COMPILER
+ RECORD(UKLI_REC_COMPILER,
+ .asciz STRINGIFY(__LIBUKLIBID_COMPILER__))
+#endif /* CONFIG_LIBUKLIBID_INFO_COMPILER */
+#endif /* !__GLOBALINFO__ */
+
+4: .align 1
+.popsection