Add a build-id to the kernel
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 27 May 2016 21:24:13 +0000 (17:24 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 16 Jun 2016 15:48:39 +0000 (11:48 -0400)
Since KFS is linked into the kernel, changes in KFS will result in changes
to the build-id.  That limitations will go away once we support a real
initramfs.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
Makefile
kern/arch/riscv/kernel.ld
kern/arch/x86/kernel64.ld
kern/build_id.ld [new file with mode: 0644]
kern/drivers/dev/version.c

index 1f6e62c..c35ce4d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -539,6 +539,7 @@ $(ext2_bdev_obj): $(ext2-bdev)
 quiet_cmd_link-akaros = LINK    $@
       cmd_link-akaros = $(CONFIG_SHELL) scripts/link-kernel.sh $@ \
                         kern/arch/$(ARCH)/$(KERNEL_LD) $(LDFLAGS_KERNEL) \
+                        --build-id=sha1 \
                         $(akaros-deps) $(gcc-lib) $(kern_cpio_obj) \
                         $(ext2_bdev_obj); \
                         $(ARCH_POST_LINK_CMD)
index bfc8796..56acaa6 100644 (file)
@@ -15,6 +15,7 @@ SECTIONS
        PROVIDE(etext = .);     /* Define the 'etext' symbol to this value */
 
        INCLUDE kern/linker_tables.ld
+       INCLUDE kern/build_id.ld
 
        .rodata : {
                *(.rodata .rodata.* .gnu.linkonce.r.*)
index d56eef3..392a2f9 100644 (file)
@@ -33,6 +33,7 @@ SECTIONS
        PROVIDE(etext = .);     /* Define the 'etext' symbol to this value */
 
        INCLUDE kern/linker_tables.ld
+       INCLUDE kern/build_id.ld
 
        .rodata : {
                *(.rodata .rodata.* .gnu.linkonce.r.*)
diff --git a/kern/build_id.ld b/kern/build_id.ld
new file mode 100644 (file)
index 0000000..d2c826b
--- /dev/null
@@ -0,0 +1,9 @@
+/* this is INCLUDEd into the arch-specific ld scripts */
+
+       .note.gnu.build-id :
+       {
+               . = ALIGN(4);
+               PROVIDE(__note_build_id_start = .);
+               *(.note.gnu.build-id)
+               PROVIDE(__note_build_id_end = .);
+       }
index a8ed8db..129ad0b 100644 (file)
 
 enum {
        Kverdirqid = 0,
+       Kverbuildid,
        Kverdate,
        Kvercommitid,
        Kverversion,
        Kverversionname,
+       BUILD_ID_SZ = 20,
+       BUILD_ID_OFFSET = 16,
 };
 
 struct dev verdevtab;
 static struct dirtab vertab[] = {
        {".",                           {Kverdirqid,            0, QTDIR}, 0,   DMDIR|0550},
+       {"build_id",            {Kverbuildid},          0,      0444},
        {"date",                        {Kverdate},                     0,      0444},
        {"commitid",            {Kvercommitid},         0,      0444},
        {"version",                     {Kverversion},          0,      0444},
        {"version_name",        {Kverversionname},      0,      0444},
 };
 
+extern char __note_build_id_start[];
+extern char __note_build_id_end[];
+
+static char *get_build_id_start(void)
+{
+       return __note_build_id_start + BUILD_ID_OFFSET;
+}
+
+static size_t build_id_sz(void)
+{
+       return __note_build_id_end - get_build_id_start();
+}
+
 static long ver_emit_nlstr(char *dest, const char *src, long size,
                                                   long offset)
 {
@@ -59,6 +76,7 @@ static struct chan *ver_attach(char *spec)
 static void ver_init(void)
 {
        /* Our devtab's length params are wrong - need to stitch them up. */
+       vertab[Kverbuildid].length = build_id_sz();
        vertab[Kverdate].length = ver_get_file_size(build_info_date);
        vertab[Kvercommitid].length = ver_get_file_size(build_info_commitid);
        vertab[Kverversion].length = ver_get_file_size(build_info_version);
@@ -98,11 +116,36 @@ static void ver_close(struct chan *c)
 
 }
 
+/* Returns a char representing the lowest 4 bits of x */
+static char num_to_nibble(int x)
+{
+       return "0123456789abcdef"[x % 16];
+}
+
+static ssize_t read_buildid(void *va, long n, off64_t off)
+{
+       /* Each build_id byte needs 2 chars, and 1 for the \0 */
+       char build_id[BUILD_ID_SZ * 2 + 1] = {0};
+       uint8_t hi, lo;
+       uint8_t *b = (uint8_t*)get_build_id_start();
+
+       for (int i = 0; i < BUILD_ID_SZ; i++) {
+               hi = *b >> 4;
+               lo = *b & 0xf;
+               build_id[i * 2 + 0] = num_to_nibble(hi);
+               build_id[i * 2 + 1] = num_to_nibble(lo);
+               b++;
+       }
+       return readmem(off, va, n, build_id, sizeof(build_id));
+}
+
 static long ver_read(struct chan *c, void *va, long n, int64_t off)
 {
        switch ((int) c->qid.path) {
        case Kverdirqid:
                return devdirread(c, va, n, vertab, ARRAY_SIZE(vertab), devgen);
+       case Kverbuildid:
+               return read_buildid(va, n, off);
        case Kverdate:
                if (build_info_date)
                        return ver_emit_nlstr(va, build_info_date, n, (long) off);