--- /usr/src/sys/sys/cdefs.h Wed Dec 5 12:00:35 2007 +++ sys/sys/cdefs.h Wed Dec 19 21:58:24 2007 @@ -403,7 +403,10 @@ */ #ifndef __FBSDID #if !defined(lint) && !defined(STRIP_FBSDID) -#define __FBSDID(s) __IDSTRING(__CONCAT(__rcsid_,__LINE__),s) +#define __FBSDID_VARNAME __CONCAT(__srcid_, __LINE__) +#define __FBSDID(s) \ + static const char __FBSDID_VARNAME [] = #s; \ + DATA_SET(srcid_strs, __FBSDID_VARNAME) #else #define __FBSDID(s) struct __hack #endif @@ -557,5 +560,11 @@ #define __ISO_C_VISIBLE 1999 #endif #endif + +/* + * Since linker_set.h requires cdefs.h (this file) and macros defined in here, + * include it at the end. + */ +#include #endif /* !_SYS_CDEFS_H_ */ --- /usr/src/sys/kern/kern_mib.c Wed Dec 5 12:00:30 2007 +++ sys/kern/kern_mib.c Tue Dec 18 01:19:03 2007 @@ -38,6 +38,7 @@ #include __FBSDID("$FreeBSD: src/sys/kern/kern_mib.c,v 1.85 2007/12/04 12:28:07 kib Exp $"); +#include "opt_ddb.h" #include "opt_posix.h" #include "opt_config.h" @@ -307,6 +308,85 @@ SYSCTL_PROC(_kern, KERN_SECURELVL, securelevel, CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_PRISON, 0, 0, sysctl_kern_securelvl, "I", "Current secure level"); + +/* + * We're going to use __start* and __end magic symbols brought to us by + * gcc(1). + */ +SET_DECLARE(srcid_strs, const char); + +/* + * Based on __FBSDID format, skip common parts that bring no valueable + * information in this context. + */ +static void +srcid_fname(const char *id, const char **ret, int *retlen) +{ + const char *p = NULL; + int l = 0; + + KASSERT(id != NULL, ("id == NULL")); + KASSERT(ret != NULL, ("p == NULL")); + KASSERT(retlen != NULL, ("len == NULL")); + + p = strstr(id, "$FreeBSD: "); + if (p != NULL) + id += strlen("$FreeBSD: "); + l = strlen(id); + p = strstr(id, " Exp $"); + if (p != NULL) + l = p - id; + *ret = id; + *retlen = l; +} + +/* + * Return all __FBSDID tags. The output is huge. + */ +static int +sysctl_kern_srcids(SYSCTL_HANDLER_ARGS) +{ + struct sbuf *sb; + const char **ids; + const char *id; + int error, olen; + const char *p; + + sb = sbuf_new(NULL, NULL, 4096, SBUF_AUTOEXTEND); + if (sb == NULL) + return (ENOMEM); + sbuf_clear(sb); + SET_FOREACH(ids, srcid_strs) { + id = *ids; + srcid_fname(id, &p, &olen); + sbuf_printf(sb, "\n%.*s", olen, p); + } + sbuf_finish(sb); + error = sysctl_handle_string(oidp, sbuf_data(sb), + sbuf_len(sb), req); + sbuf_delete(sb); + return (error); +} +SYSCTL_PROC(_kern, OID_AUTO, srcids, CTLTYPE_STRING|CTLFLAG_RD, 0, 0, + sysctl_kern_srcids, "A", "Revision control tags for kernel sources"); + +#ifdef DDB +#include + +DB_SHOW_COMMAND(srcids, db_srcid_list) +{ + const char **ids; + const char *id; + const char *p; + int olen; + + SET_FOREACH(ids, srcid_strs) { + id = *ids; + srcid_fname(id, &p, &olen); + db_printf("%.*s\n", olen, p); + } +} +#endif #ifdef INCLUDE_CONFIG_FILE /* Actual kernel configuration options. */