Index: sys/conf/ldscript.amd64 =================================================================== --- sys/conf/ldscript.amd64 +++ sys/conf/ldscript.amd64 @@ -74,6 +74,11 @@ PROVIDE (etext = .); .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } .rodata1 : { *(.rodata1) } + .note.gnu.build-id : { + PROVIDE (__build_id_start = .); + *(.note.gnu.build-id) + PROVIDE (__build_id_end = .); + } .eh_frame_hdr : { *(.eh_frame_hdr) } .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } Index: sys/conf/ldscript.arm =================================================================== --- sys/conf/ldscript.arm +++ sys/conf/ldscript.arm @@ -27,6 +27,11 @@ .gnu.version : { *(.gnu.version) } .gnu.version_d : { *(.gnu.version_d) } .gnu.version_r : { *(.gnu.version_r) } + .note.gnu.build-id : { + PROVIDE (__build_id_start = .); + *(.note.gnu.build-id) + PROVIDE (__build_id_end = .); + } .rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) } .rela.text : Index: sys/conf/ldscript.arm64 =================================================================== --- sys/conf/ldscript.arm64 +++ sys/conf/ldscript.arm64 @@ -27,6 +27,11 @@ .gnu.version : { *(.gnu.version) } .gnu.version_d : { *(.gnu.version_d) } .gnu.version_r : { *(.gnu.version_r) } + .note.gnu.build-id : { + PROVIDE (__build_id_start = .); + *(.note.gnu.build-id) + PROVIDE (__build_id_end = .); + } .rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) } .rela.text : Index: sys/conf/ldscript.i386 =================================================================== --- sys/conf/ldscript.i386 +++ sys/conf/ldscript.i386 @@ -62,6 +62,11 @@ PROVIDE (etext = .); .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } .rodata1 : { *(.rodata1) } + .note.gnu.build-id : { + PROVIDE (__build_id_start = .); + *(.note.gnu.build-id) + PROVIDE (__build_id_end = .); + } .eh_frame_hdr : { *(.eh_frame_hdr) } .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } Index: sys/conf/ldscript.mips =================================================================== --- sys/conf/ldscript.mips +++ sys/conf/ldscript.mips @@ -63,6 +63,11 @@ .gnu.version : { *(.gnu.version) } .gnu.version_d : { *(.gnu.version_d) } .gnu.version_r : { *(.gnu.version_r) } + .note.gnu.build-id : { + PROVIDE (__build_id_start = .); + *(.note.gnu.build-id) + PROVIDE (__build_id_end = .); + } .rel.init : { *(.rel.init) } .rela.init : { *(.rela.init) } .rel.text : Index: sys/conf/ldscript.mips.cfe =================================================================== --- sys/conf/ldscript.mips.cfe +++ sys/conf/ldscript.mips.cfe @@ -192,6 +192,11 @@ PROVIDE (etext = .); .rodata : { *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) } .rodata1 : { *(.rodata1) } + .note.gnu.build-id : { + PROVIDE (__build_id_start = .); + *(.note.gnu.build-id) + PROVIDE (__build_id_end = .); + } .reginfo : { *(.reginfo) } .sdata2 : { *(.sdata2) *(.sdata2.*) *(.gnu.linkonce.s2.*) } .sbss2 : { *(.sbss2) *(.sbss2.*) *(.gnu.linkonce.sb2.*) } Index: sys/conf/ldscript.mips.mips64 =================================================================== --- sys/conf/ldscript.mips.mips64 +++ sys/conf/ldscript.mips.mips64 @@ -176,6 +176,11 @@ PROVIDE (etext = .); .rodata : { *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) } .rodata1 : { *(.rodata1) } + .note.gnu.build-id : { + PROVIDE (__build_id_start = .); + *(.note.gnu.build-id) + PROVIDE (__build_id_end = .); + } .reginfo : { *(.reginfo) } .sdata2 : { *(.sdata2) *(.sdata2.*) *(.gnu.linkonce.s2.*) } .sbss2 : { *(.sbss2) *(.sbss2.*) *(.gnu.linkonce.sb2.*) } Index: sys/conf/ldscript.mips.octeon1 =================================================================== --- sys/conf/ldscript.mips.octeon1 +++ sys/conf/ldscript.mips.octeon1 @@ -23,6 +23,12 @@ *(.rodata) . = ALIGN(32); } + + .note.gnu.build-id : { + PROVIDE (__build_id_start = .); + *(.note.gnu.build-id) + PROVIDE (__build_id_end = .); + } .data : { _rwdata = .; Index: sys/conf/ldscript.powerpc =================================================================== --- sys/conf/ldscript.powerpc +++ sys/conf/ldscript.powerpc @@ -55,6 +55,11 @@ .fini : { *(.fini) } =0 .rodata : { *(.rodata) *(.gnu.linkonce.r*) } .rodata1 : { *(.rodata1) } + .note.gnu.build-id : { + PROVIDE (__build_id_start = .); + *(.note.gnu.build-id) + PROVIDE (__build_id_end = .); + } .sdata2 : { *(.sdata2) } .sbss2 : { *(.sbss2) } /* Adjust the address for the data segment to the next page up. */ Index: sys/conf/ldscript.powerpc64 =================================================================== --- sys/conf/ldscript.powerpc64 +++ sys/conf/ldscript.powerpc64 @@ -46,6 +46,11 @@ .gnu.version : { *(.gnu.version) } .gnu.version_d : { *(.gnu.version_d) } .gnu.version_r : { *(.gnu.version_r) } + .note.gnu.build-id : { + PROVIDE (__build_id_start = .); + *(.note.gnu.build-id) + PROVIDE (__build_id_end = .); + } .rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) } .rela.data : Index: sys/conf/ldscript.powerpcspe =================================================================== --- sys/conf/ldscript.powerpcspe +++ sys/conf/ldscript.powerpcspe @@ -55,6 +55,11 @@ .fini : { *(.fini) } =0 .rodata : { *(.rodata) *(.gnu.linkonce.r*) } .rodata1 : { *(.rodata1) } + .note.gnu.build-id : { + PROVIDE (__build_id_start = .); + *(.note.gnu.build-id) + PROVIDE (__build_id_end = .); + } .sdata2 : { *(.sdata2) } .sbss2 : { *(.sbss2) } /* Adjust the address for the data segment to the next page up. */ Index: sys/conf/ldscript.riscv =================================================================== --- sys/conf/ldscript.riscv +++ sys/conf/ldscript.riscv @@ -27,6 +27,11 @@ .gnu.version : { *(.gnu.version) } .gnu.version_d : { *(.gnu.version_d) } .gnu.version_r : { *(.gnu.version_r) } + .note.gnu.build-id : { + PROVIDE (__build_id_start = .); + *(.note.gnu.build-id) + PROVIDE (__build_id_end = .); + } .rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) } .rela.text : Index: sys/conf/ldscript.sparc64 =================================================================== --- sys/conf/ldscript.sparc64 +++ sys/conf/ldscript.sparc64 @@ -146,6 +146,11 @@ PROVIDE (etext = .); .rodata : { *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) } .rodata1 : { *(.rodata1) } + .note.gnu.build-id : { + PROVIDE (__build_id_start = .); + *(.note.gnu.build-id) + PROVIDE (__build_id_end = .); + } .sdata2 : { *(.sdata2) *(.sdata2.*) *(.gnu.linkonce.s2.*) } .sbss2 : { *(.sbss2) *(.sbss2.*) *(.gnu.linkonce.sb2.*) } . = ALIGN(0x2000) + (. & (0x2000 - 1)); Index: sys/kern/kern_mib.c =================================================================== --- sys/kern/kern_mib.c +++ sys/kern/kern_mib.c @@ -481,6 +481,50 @@ CTLTYPE_INT | CTLFLAG_CAPRD | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, sysctl_osreldate, "I", "Kernel release date"); +/* + * The build-id is copied from the ELF section .note.gnu.build-id. The linker + * script defines two variables to expose the beginning and end. LLVM + * currently uses a SHA-1 hash, but other formats can be supported by checking + * the length of the section. + */ + +extern char __build_id_start[]; +extern char __build_id_end[]; + +static int +sysctl_build_id(SYSCTL_HANDLER_ARGS) +{ + uintptr_t sectionlen = (uintptr_t)(__build_id_end - __build_id_start); + int hashlen; + char buf[41]; + + /* + * The ELF note section has a four byte length for the vendor name, + * four byte length for the value, and a four byte vendor specific + * type. The name for the build id is "GNU\0". We skip the first 16 + * bytes to read the build hash. We will return the remaining bytes up + * to 20 (SHA-1) hash size. If the hash happens to be a custom number + * of bytes we will pad the value with zeros, as the section should be + * four byte aligned. + */ + if (sectionlen <= 0x10 || sectionlen > 0x24) { + return (ENOENT); + } + + + hashlen = sectionlen - 0x10; + for (int i = 0; i < hashlen; i++) { + uint8_t c = __build_id_start[i+0x10]; + snprintf(&buf[2*i], 3, "%02x", c); + } + + return (SYSCTL_OUT(req, buf, strlen(buf) + 1)); +} + +SYSCTL_PROC(_kern, OID_AUTO, build_id, + CTLTYPE_STRING | CTLFLAG_CAPRD | CTLFLAG_RD | CTLFLAG_MPSAFE, + NULL, 0, sysctl_build_id, "A", "Operating system build-id"); + SYSCTL_NODE(_kern, OID_AUTO, features, CTLFLAG_RD, 0, "Kernel Features"); #ifdef COMPAT_FREEBSD4 Index: usr.bin/uname/uname.c =================================================================== --- usr.bin/uname/uname.c +++ usr.bin/uname/uname.c @@ -67,9 +67,10 @@ #define IFLAG 0x40 #define UFLAG 0x80 #define KFLAG 0x100 +#define BFLAG 0x200 typedef void (*get_t)(void); -static get_t get_ident, get_platform, get_hostname, get_arch, +static get_t get_buildid, get_ident, get_platform, get_hostname, get_arch, get_release, get_sysname, get_kernvers, get_uservers, get_version; static void native_ident(void); @@ -81,11 +82,13 @@ static void native_version(void); static void native_kernvers(void); static void native_uservers(void); +static void native_buildid(void); static void print_uname(u_int); static void setup_get(void); static void usage(void); -static char *ident, *platform, *hostname, *arch, *release, *sysname, *version, *kernvers, *uservers; +static char *buildid, *ident, *platform, *hostname, *arch, + *release, *sysname, *version, *kernvers, *uservers; static int space; int @@ -97,10 +100,13 @@ setup_get(); flags = 0; - while ((ch = getopt(argc, argv, "aiKmnoprsUv")) != -1) + while ((ch = getopt(argc, argv, "abiKmnoprsUv")) != -1) switch(ch) { case 'a': - flags |= (MFLAG | NFLAG | RFLAG | SFLAG | VFLAG); + flags |= (BFLAG | MFLAG | NFLAG | RFLAG | SFLAG | VFLAG); + break; + case 'b': + flags |= BFLAG; break; case 'i': flags |= IFLAG; @@ -169,6 +175,7 @@ CHECK_ENV("i", ident); CHECK_ENV("K", kernvers); CHECK_ENV("U", uservers); + CHECK_ENV("b", buildid); } #define PRINT_FLAG(flags,flag,var) \ @@ -194,6 +201,7 @@ PRINT_FLAG(flags, IFLAG, ident); PRINT_FLAG(flags, KFLAG, kernvers); PRINT_FLAG(flags, UFLAG, uservers); + PRINT_FLAG(flags, BFLAG, buildid); printf("\n"); } @@ -261,6 +269,9 @@ NATIVE_SYSCTLNAME_GET(ident, "kern.ident") { } NATIVE_SET; +NATIVE_SYSCTLNAME_GET(buildid, "kern.build_id") { +} NATIVE_SET; + static void native_uservers(void) { @@ -282,6 +293,6 @@ static void usage(void) { - fprintf(stderr, "usage: uname [-aiKmnoprsUv]\n"); + fprintf(stderr, "usage: uname [-abiKmnoprsUv]\n"); exit(1); }