--- /usr/src/sys/amd64/include/asm.h Mon Oct 15 22:19:03 2007 +++ src/sys/amd64/include/asm.h Thu Dec 27 14:44:16 2007 @@ -83,7 +83,11 @@ #undef __FBSDID #if !defined(lint) && !defined(STRIP_FBSDID) -#define __FBSDID(s) .ident s +#define __FBSDID(s) \ + .section set_srcid,"a",@progbits; \ + .p2align 0; \ + .asciz #s; \ + .previous #else #define __FBSDID(s) /* nothing */ #endif /* not lint and not STRIP_FBSDID */ --- /usr/src/sys/arm/include/asm.h Mon Oct 15 22:19:06 2007 +++ src/sys/arm/include/asm.h Thu Dec 27 14:44:16 2007 @@ -104,7 +104,11 @@ #undef __FBSDID #if !defined(lint) && !defined(STRIP_FBSDID) -#define __FBSDID(s) .ident s +#define __FBSDID(s) \ + .section set_srcid,"a",@progbits; \ + .p2align 0; \ + .asciz #s; \ + .previous #else #define __FBSDID(s) /* nothing */ #endif --- /usr/src/sys/i386/include/asm.h Mon Oct 15 22:21:10 2007 +++ src/sys/i386/include/asm.h Thu Dec 27 14:44:17 2007 @@ -93,7 +93,11 @@ #undef __FBSDID #if !defined(lint) && !defined(STRIP_FBSDID) -#define __FBSDID(s) .ident s +#define __FBSDID(s) \ + .section set_srcid,"a",@progbits; \ + .p2align 0; \ + .asciz #s; \ + .previous #else #define __FBSDID(s) /* nothing */ #endif /* not lint and not STRIP_FBSDID */ --- /usr/src/sys/ia64/include/asm.h Mon Jan 31 09:16:12 2005 +++ src/sys/ia64/include/asm.h Thu Dec 27 14:44:17 2007 @@ -182,7 +182,11 @@ * ID tag macros */ #if !defined(lint) && !defined(STRIP_FBSDID) -#define __FBSDID(s) .ident s +#define __FBSDID(s) \ + .section set_srcid,"a",@progbits; \ + .p2align 0; \ + .asciz #s; \ + .previous #else #define __FBSDID(s) /* nothing */ #endif /* not lint and not STRIP_FBSDID */ --- /usr/src/sys/kern/kern_mib.c Wed Dec 5 12:00:30 2007 +++ src/sys/kern/kern_mib.c Thu Dec 27 14:44:17 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,106 @@ SYSCTL_PROC(_kern, KERN_SECURELVL, securelevel, CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_PRISON, 0, 0, sysctl_kern_securelvl, "I", "Current secure level"); + +/* + * If STRIP_FBSDID is defined it means we should save as much as + * possible in terms of the kernel size. Handle "kern.srcids" and "show + * srcids" DDB command only in !STRIP_FBSDID case. Otherwise, we'd need + * at least one thing lying in the srcid magic section so that we + * wouldn't be getting an error about __(start|stop)_set_srcid being + * undefined due to non-existent .srcid section; and it all would be + * just to get useless output.. + */ +#ifndef STRIP_FBSDID + +/* + * Based on __FBSDID format, skip common parts that bring no valueable + * information in this context. + */ +static void __unused +srcid_fname(char *id, char **ret, int *retlen) +{ + 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; +} + + +/* + * Magic generated by the gcc(1) to mark the section ranges with special + * variable names. + */ +extern char __start_set_srcid[]; +extern char __stop_set_srcid[]; + +#define FBSDID_BEGIN (&__start_set_srcid[0]) +#define FBSDID_END (&__stop_set_srcid[0]) + +/* + * Return all __FBSDID tags. The output is huge. + */ +static int +sysctl_kern_srcids(SYSCTL_HANDLER_ARGS) +{ + char *bid = FBSDID_BEGIN; + char *eid = FBSDID_END; + char *s; + int idlen; + char *id; + int error = 0; + + for (s = bid; s < eid; s++) { + srcid_fname(s, &id, &idlen); + error = sysctl_handle_opaque(oidp, "\n", 1, req); + if (error) + break; + error = sysctl_handle_opaque(oidp, id, idlen, req); + if (error) + break; + s += strlen(s); + } + error = sysctl_handle_opaque(oidp, "\0", 1, req); + if (error) + return (error); + 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) +{ + char *bid = FBSDID_BEGIN; + char *eid = FBSDID_END; + char *s; + int slen; + int idlen; + char *id; + + for (s = bid; s < eid; s++) { + srcid_fname(s, &id, &idlen); + db_printf("%.*s\n", idlen, id); + slen = strlen(s); + s += slen; + } +} +#endif +#endif /* STRIP_FBSDID */ #ifdef INCLUDE_CONFIG_FILE /* Actual kernel configuration options. */ --- /usr/src/sys/powerpc/include/asm.h Fri Jan 7 03:29:19 2005 +++ src/sys/powerpc/include/asm.h Thu Dec 27 14:44:21 2007 @@ -79,7 +79,11 @@ #undef __FBSDID #if !defined(lint) && !defined(STRIP_FBSDID) -#define __FBSDID(s) .ident s +#define __FBSDID(s) \ + .section set_srcid,"a",@progbits; \ + .p2align 0; \ + .asciz #s; \ + .previous #else #define __FBSDID(s) /* nothing */ #endif /* not lint and not STRIP_FBSDID */ --- /usr/src/sys/sparc64/include/asm.h Wed Apr 7 07:00:00 2004 +++ src/sys/sparc64/include/asm.h Thu Dec 27 14:44:21 2007 @@ -101,7 +101,11 @@ #undef __FBSDID #if !defined(lint) && !defined(STRIP_FBSDID) -#define __FBSDID(s) .ident s +#define __FBSDID(s) \ + .section set_srcid,"a",@progbits; \ + .p2align 0; \ + .asciz #s; \ + .previous #else #define __FBSDID(s) /* nothing */ #endif /* not lint and not STRIP_FBSDID */ --- /usr/src/sys/sun4v/include/asm.h Thu Nov 23 03:25:16 2006 +++ src/sys/sun4v/include/asm.h Thu Dec 27 14:44:21 2007 @@ -108,7 +108,11 @@ #undef __FBSDID #if !defined(lint) && !defined(STRIP_FBSDID) -#define __FBSDID(s) .ident s +#define __FBSDID(s) \ + .section set_srcid,"a",@progbits; \ + .p2align 0; \ + .asciz #s; \ + .previous #else #define __FBSDID(s) /* nothing */ #endif /* not lint and not STRIP_FBSDID */ --- /usr/src/sys/sys/cdefs.h Wed Dec 5 12:00:35 2007 +++ src/sys/sys/cdefs.h Thu Dec 27 18:15:28 2007 @@ -403,11 +403,32 @@ */ #ifndef __FBSDID #if !defined(lint) && !defined(STRIP_FBSDID) -#define __FBSDID(s) __IDSTRING(__CONCAT(__rcsid_,__LINE__),s) + +/* + * ARM is somehow special.. + */ +#ifdef __arm__ +#define FBSDID_SECTYPE "%%progbits" #else -#define __FBSDID(s) struct __hack +#define FBSDID_SECTYPE "@progbits" +#endif + +#if !defined(__i386__) && !defined (__amd64__) && !defined (__ia64__) +#define FBSDID_SECTION() \ + __asm__(".section \"set_srcid\",\"a\"," FBSDID_SECTYPE) +#else /* otherwise, for __i386__, __amd64__ or __ia64__ we have: */ +#define FBSDID_SECTION() \ + __asm__(".section set_srcid,\"a\",@progbits") #endif +#define __FBSDID(s) \ + FBSDID_SECTION(); \ + __asm__(".p2align 0"); \ + __asm__(".asciz " #s); \ + __asm__(".previous"); +#else /* defined(line) || defined(STRIP_FBSDID) */ +#define __FBSDID(s) struct __hack #endif +#endif /* __FBSDID */ #ifndef __RCSID #ifndef NO__RCSID diff -ur /usr/src/usr.sbin/config/config.8 src/usr.sbin/config/config.8 --- /usr/src/usr.sbin/config/config.8 Mon Apr 30 10:55:43 2007 +++ src/usr.sbin/config/config.8 Thu Dec 27 16:15:27 2007 @@ -28,7 +28,7 @@ .\" @(#)config.8 8.2 (Berkeley) 4/19/94 .\" $FreeBSD: src/usr.sbin/config/config.8,v 1.46 2007/05/12 19:38:18 wkoszek Exp $ .\" -.Dd May 8, 2007 +.Dd December 27, 2007 .Dt CONFIG 8 .Os .Sh NAME @@ -40,6 +40,7 @@ .Op Fl d Ar destdir .Ar SYSTEM_NAME .Nm +.Op Fl i .Op Fl x Ar kernel .Sh DESCRIPTION .\" This is the old version of the @@ -100,6 +101,28 @@ This option makes sense only if .Cd "options INCLUDE_CONFIG_FILE" entry was present in your configuration file. +.It Fl i +This flag can't be used separately. It works in conjunction +with +.Fl x +flag. It makes +.Nm +to print revision control system tags embedded in a +.Ar kernel +binary file. In order to print both the kernel configuration +file and revision control system tags, flag +.Fl i +can be specified twice. +Please note that revision control data is not preserved if +.Ar kernel +was built with +.Cd STRIP_FBSDID +environment variable set. This option provides the very same +functionality as the +.Xr ident 1 +tool, but can be used on before +.Pa /usr +directory is mounted. .It Fl p Configure a system for profiling; for example, .Xr kgmon 8 Only in /usr/src/usr.sbin/config: config.h.orig Only in /usr/src/usr.sbin/config: config.y.orig Only in /usr/src/usr.sbin/config: kernconf.tmpl.orig diff -ur /usr/src/usr.sbin/config/main.c src/usr.sbin/config/main.c --- /usr/src/usr.sbin/config/main.c Thu May 17 06:53:52 2007 +++ src/usr.sbin/config/main.c Thu Dec 27 14:44:27 2007 @@ -90,6 +90,7 @@ static void usage(void); static void cleanheaders(char *); static void kernconfdump(const char *); +static void srciddump(const char *file); struct hdr_list { char *h_name; @@ -105,13 +106,14 @@ { struct stat buf; - int ch, len; + int ch, flag_i, len; char *p; char xxx[MAXPATHLEN]; char *kernfile; + flag_i = 0; kernfile = NULL; - while ((ch = getopt(argc, argv, "Cd:gpVx:")) != -1) + while ((ch = getopt(argc, argv, "Cd:gipVx:")) != -1) switch (ch) { case 'C': filebased = 1; @@ -125,6 +127,9 @@ case 'g': debugging++; break; + case 'i': + flag_i++; + break; case 'p': profiling++; break; @@ -141,7 +146,15 @@ argc -= optind; argv += optind; + if (flag_i >= 1 && kernfile == NULL) + err(EXIT_FAILURE, "-i works only if -x is specified. See " + "config(8)"); if (kernfile != NULL) { + if (flag_i >= 1) { + srciddump(kernfile); + if (flag_i > 1) + exit(EXIT_SUCCESS); + } kernconfdump(kernfile); exit(EXIT_SUCCESS); } @@ -638,19 +651,56 @@ htab = hl; } +enum { + OPT_PRINT_DEFINED = 0, + OPT_PRINT_UNDEFINED = 1, +}; + +/* + * Map between optional ELF section and it's respective kernel compile + * time option. + */ +static struct { + const char *sectname; + const char *optname; + int onlack; +} optsects[] = { + /* + * "kern_conf" (embedded kernel file) is in the kernel binary + * when INCLUDE_CONFIG_FILE is defined. + */ + { "kern_conf", "INCLUDE_CONFIG_FILE", OPT_PRINT_UNDEFINED }, + + /* + * "srcid" section responsible for __FBSDID() handling is present if + * STRIP_FBSDID was *not* passed to the kernel at build stage. + */ + { "srcid", "STRIP_FBSDID", OPT_PRINT_DEFINED }, +}; + +#define SECTION_KERN_CONF 0 +#define SECTION_SRCIDS 1 +#define SECTION_MAX 1 + /* * This one is quick hack. Will be probably moved to elf(3) interface. * It takes kernel configuration file name, passes it as an argument to * elfdump -a, which output is parsed by some UNIX tools... */ static void -kernconfdump(const char *file) +section_dump(const char *file, int sectid) { struct stat st; FILE *fp, *pp; - int error, len, osz, r; + int error, len, neg, osz, r; unsigned int off, size; char *cmd, *o; + const char *optname, *sectname; + + assert(sectid >= 0 && sectid <= SECTION_MAX && "wrong sectid!"); + optname = optsects[sectid].optname; + sectname = optsects[sectid].sectname; + neg = (optsects[sectid].onlack == OPT_PRINT_UNDEFINED); r = open(file, O_RDONLY); if (r == -1) @@ -668,8 +718,9 @@ if (o == NULL) errx(EXIT_FAILURE, "Couldn't allocate memory"); /* ELF note section header. */ - asprintf(&cmd, "/usr/bin/elfdump -c %s | grep -A 5 kern_conf" - "| tail -2 | cut -d ' ' -f 2 | paste - - -", file); + asprintf(&cmd, "/usr/bin/elfdump -c %s | grep -A 5 %s" + "| tail -2 | cut -d ' ' -f 2 | paste - - -", file, + sectname); if (cmd == NULL) errx(EXIT_FAILURE, "asprintf() failed"); pp = popen(cmd, "r"); @@ -681,13 +732,28 @@ r = sscanf(o, "%d\t%d", &off, &size); free(o); if (r != 2) - errx(EXIT_FAILURE, "File %s doesn't contain configuration " - "file. Either unsupported, or not compiled with " - "INCLUDE_CONFIG_FILE", file); + errx(EXIT_FAILURE, "File %s doesn't provide required " + "data.\nLooks like the kernel option %s was %s " + "defined at build time.\n", file, optname, + neg == 1 ? "not" : ""); r = fseek(fp, off, SEEK_CUR); if (r != 0) errx(EXIT_FAILURE, "fseek() failed"); while ((r = fgetc(fp)) != EOF && size-- > 0) fputc(r, stdout); fclose(fp); +} + +static void +kernconfdump(const char *file) +{ + + section_dump(file, SECTION_KERN_CONF); +} + +static void +srciddump(const char *file) +{ + + section_dump(file, SECTION_SRCIDS); } Only in /usr/src/usr.sbin/config: main.c.orig Only in /usr/src/usr.sbin/config: old.main.c Only in /usr/src/usr.sbin/config: trigraph