From 4a2ff67c88211026afcbdbc190c13f705dae1b59 Mon Sep 17 00:00:00 2001 From: Michael Tokarev Date: Tue, 13 Oct 2009 22:22:46 +0200 Subject: kbuild: fix bzImage build for x86 As has been discussed previously (and Sam has been CC'ed), the fix is still incorrect. It replaces "echo -ne" with "/bin/echo -ne", but neither of the two are guaranteed to support the necessary arguments and necessary (hexadecimal) escape sequences. What should be used here is printf(1). The trivial patch below (on top of these kbuild changes) fixes this issue. Signed-Off-By: Michael Tokarev Signed-off-by: Sam Ravnborg Signed-off-by: Michal Marek --- scripts/Makefile.lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index ffdafb26f539..d9f0cb837400 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -208,7 +208,7 @@ cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -f -9 > $@) || \ # Bzip2 and LZMA do not include size in file... so we have to fake that; # append the size as a 32-bit littleendian number as gzip does. -size_append = /bin/echo -ne $(shell \ +size_append = printf $(shell \ dec_size=0; \ for F in $1; do \ fsize=$$(stat -c "%s" $$F); \ -- cgit v1.2.3 From c95fa08a3e17c3f2983c4cbf409f5c9ae47b7dec Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sat, 17 Oct 2009 22:47:31 +0200 Subject: kbuild: do not check for include/asm-$ARCH No architectures uses include/asm-$ARCH now. So drop check for location of include files Signed-off-by: Sam Ravnborg Signed-off-by: Michal Marek --- scripts/headers.sh | 2 -- 1 file changed, 2 deletions(-) (limited to 'scripts') diff --git a/scripts/headers.sh b/scripts/headers.sh index 0308ecc10d5b..1ddcdd38d97f 100755 --- a/scripts/headers.sh +++ b/scripts/headers.sh @@ -8,8 +8,6 @@ do_command() { if [ -f ${srctree}/arch/$2/include/asm/Kbuild ]; then make ARCH=$2 KBUILD_HEADERS=$1 headers_$1 - elif [ -f ${srctree}/include/asm-$2/Kbuild ]; then - make ARCH=$2 KBUILD_HEADERS=$1 headers_$1 else printf "Ignoring arch: %s\n" ${arch} fi -- cgit v1.2.3 From 264a26838056fc2d759f58bec2e720e01fcb1bdb Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 18 Oct 2009 00:49:24 +0200 Subject: kbuild: move autoconf.h to include/generated Signed-off-by: Sam Ravnborg Signed-off-by: Michal Marek --- scripts/basic/fixdep.c | 10 +++++----- scripts/kconfig/confdata.c | 2 +- scripts/mkcompile_h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c index 6bf21f83837d..ea26b23de082 100644 --- a/scripts/basic/fixdep.c +++ b/scripts/basic/fixdep.c @@ -16,15 +16,15 @@ * tells make when to remake a file. * * To use this list as-is however has the drawback that virtually - * every file in the kernel includes . + * every file in the kernel includes autoconf.h. * - * If the user re-runs make *config, linux/autoconf.h will be + * If the user re-runs make *config, autoconf.h will be * regenerated. make notices that and will rebuild every file which * includes autoconf.h, i.e. basically all files. This is extremely * annoying if the user just changed CONFIG_HIS_DRIVER from n to m. * * So we play the same trick that "mkdep" played before. We replace - * the dependency on linux/autoconf.h by a dependency on every config + * the dependency on autoconf.h by a dependency on every config * option which is mentioned in any of the listed prequisites. * * kconfig populates a tree in include/config/ with an empty file @@ -73,7 +73,7 @@ * cmd_ = * * and then basically copies the ..d file to stdout, in the - * process filtering out the dependency on linux/autoconf.h and adding + * process filtering out the dependency on autoconf.h and adding * dependencies on include/config/my/option.h for every * CONFIG_MY_OPTION encountered in any of the prequisites. * @@ -324,7 +324,7 @@ static void parse_dep_file(void *map, size_t len) p++; } memcpy(s, m, p-m); s[p-m] = 0; - if (strrcmp(s, "include/linux/autoconf.h") && + if (strrcmp(s, "include/generated/autoconf.h") && strrcmp(s, "arch/um/include/uml-config.h") && strrcmp(s, ".ver")) { printf(" %s \\\n", s); diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index b55e72ff2fc6..797a7410f690 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -776,7 +776,7 @@ int conf_write_autoconf(void) name = getenv("KCONFIG_AUTOHEADER"); if (!name) - name = "include/linux/autoconf.h"; + name = "include/generated/autoconf.h"; if (rename(".tmpconfig.h", name)) return 1; name = conf_get_autoconfig_name(); diff --git a/scripts/mkcompile_h b/scripts/mkcompile_h index bce3d0fe6fbd..23dbad80cce9 100755 --- a/scripts/mkcompile_h +++ b/scripts/mkcompile_h @@ -14,7 +14,7 @@ vecho() { [ "${quiet}" = "silent_" ] || echo "$@" ; } # So "sudo make install" won't change the "compiled by " # do "compiled by root" -if [ -r $TARGET -a ! -O include/linux/autoconf.h ]; then +if [ -r $TARGET -a ! -O include/generated/autoconf.h ]; then vecho " SKIPPED $TARGET" exit 0 fi -- cgit v1.2.3 From 91d161857ce9672bd2a8cd99ff712a67186e2e76 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Tue, 24 Nov 2009 09:11:37 -0600 Subject: scripts/package: tar-pkg: use tar --owner=root Use the --owner= and --group= options to make sure the entries in the built tar file are owned by root. Without this change, a careless sysadmin using the tar-pkg target can easily end up installing a kernel that is writable by the unprivileged user account used to build the kernel. Test that these options are understood before using them so that non-GNU versions of tar can still be used if the operator is appropriately cautious. Signed-off-by: Jonathan Nieder Signed-off-by: Michal Marek --- scripts/package/buildtar | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/package/buildtar b/scripts/package/buildtar index b1fd48db1640..51b2aa0acb82 100644 --- a/scripts/package/buildtar +++ b/scripts/package/buildtar @@ -101,7 +101,11 @@ esac # ( cd "${tmpdir}" - tar cf - . | ${compress} > "${tarball}${file_ext}" + opts= + if tar --owner=root --group=root --help >/dev/null 2>&1; then + opts="--owner=root --group=root" + fi + tar cf - . $opts | ${compress} > "${tarball}${file_ext}" ) echo "Tarball successfully created in ${tarball}${file_ext}" -- cgit v1.2.3 From 05ba4488a51edde95df3f89987fdcdbca7c3cebb Mon Sep 17 00:00:00 2001 From: Jonathan Nieder Date: Tue, 24 Nov 2009 09:14:41 -0600 Subject: scripts/package: add KBUILD_PKG_ROOTCMD variable Let the deb-pkg target acquire (fake) root privileges before running commands that need them. Without such privileges, deb-pkg errors out because chown fails. The new KBUILD_PKG_ROOTCMD variable, if defined, is used as a command to run other commands with possibly fake elevated privileges. Since this is not needed for the tar-pkg and rpm-pkg targets, it is only used by deb-pkg. If it is not defined, the behavior is as before, and the user will have to rerun make as root. In other words, as a shortcut, instead of running 'make oldconfig && make && fakeroot -u make deb-pkg', one can use the single command 'make oldconfig deb-pkg KBUILD_PKG_ROOTCMD="fakeroot -u"'. Suggested-by: Ryan Anderson Signed-off-by: Jonathan Nieder Signed-off-by: Michal Marek --- scripts/package/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/package/Makefile b/scripts/package/Makefile index f67cc885c807..5c0b43aaf63b 100644 --- a/scripts/package/Makefile +++ b/scripts/package/Makefile @@ -79,7 +79,8 @@ clean-files += $(objtree)/binkernel.spec # --------------------------------------------------------------------------- deb-pkg: FORCE $(MAKE) KBUILD_SRC= - $(CONFIG_SHELL) $(srctree)/scripts/package/builddeb + $(KBUILD_PKG_ROOTCMD) $(CONFIG_SHELL) \ + $(srctree)/scripts/package/builddeb clean-dirs += $(objtree)/debian/ -- cgit v1.2.3 From db1d18657c96cc675596077cb60ef50fbe1947f8 Mon Sep 17 00:00:00 2001 From: Jonathan Nieder Date: Tue, 24 Nov 2009 09:21:56 -0600 Subject: scripts/package: deb-pkg: use fakeroot if available Running "make deb-pkg" requires setting KBUILD_PKG_ROOTCMD or becoming root oneself or it errors out. Unless already running as root or KBUILD_PKG_ROOTCMD is already set, use fakeroot as a good default. With this patch applied, you can run "make oldconfig deb-pkg" as an ordinary user to build a binary package for an updated kernel tree and it should just work. fakeroot is too zealous by default in treating files as owned by root. Its wrapped stat() sets st_uid and st_gid to 0 for all files, which causes Git to go on a wild goose chase if CONFIG_LOCALVERSION_AUTO is set, checking if any file's content has changed along with its stat information. Avoid this by telling fakeroot to use the actual owner and group for preexisting files, by passing it the -u option. Signed-off-by: Jonathan Nieder Signed-off-by: Michal Marek --- scripts/package/Makefile | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/package/Makefile b/scripts/package/Makefile index 5c0b43aaf63b..62fcc3a7f4d3 100644 --- a/scripts/package/Makefile +++ b/scripts/package/Makefile @@ -77,10 +77,27 @@ clean-files += $(objtree)/binkernel.spec # Deb target # --------------------------------------------------------------------------- +quiet_cmd_builddeb = BUILDDEB + cmd_builddeb = set -e; \ + test `id -u` = 0 || \ + test -n "$(KBUILD_PKG_ROOTCMD)" || { \ + which fakeroot >/dev/null 2>&1 && \ + KBUILD_PKG_ROOTCMD="fakeroot -u"; \ + } || { \ + echo; \ + echo "builddeb must be run as root (or using fakeroot)."; \ + echo "KBUILD_PKG_ROOTCMD is unset and fakeroot not found."; \ + echo "Try setting KBUILD_PKG_ROOTCMD to a command to acquire"; \ + echo "root privileges (e.g., 'fakeroot -u' or 'sudo')."; \ + false; \ + } && \ + \ + $$KBUILD_PKG_ROOTCMD $(CONFIG_SHELL) \ + $(srctree)/scripts/package/builddeb + deb-pkg: FORCE $(MAKE) KBUILD_SRC= - $(KBUILD_PKG_ROOTCMD) $(CONFIG_SHELL) \ - $(srctree)/scripts/package/builddeb + $(call cmd,builddeb) clean-dirs += $(objtree)/debian/ -- cgit v1.2.3 From 32197c7ffb06b1319850f8fdfa1a49d32a63b79b Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Wed, 25 Nov 2009 15:14:49 +0100 Subject: kbuild: create include/generated in silentoldconfig The toplevel Makefile creates the directory if it runs silentoldconfig automatically, but if run manually, it fails: $ make mrproper $ make defconfig && make silentoldconfig *** Default configuration is based on 'x86_64_defconfig' # # configuration written to .config # scripts/kconfig/conf -s arch/x86/Kconfig *** Error during update of the kernel configuration. ... Move the mkdir command to the silentoldconfig target to make it work. Signed-off-by: Michal Marek --- scripts/kconfig/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index 80599e3a7994..999e8a7d5bf7 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -27,6 +27,7 @@ oldconfig: $(obj)/conf $< -o $(Kconfig) silentoldconfig: $(obj)/conf + $(Q)mkdir -p include/generated $< -s $(Kconfig) localmodconfig: $(obj)/streamline_config.pl $(obj)/conf -- cgit v1.2.3 From eb8f844c0a41c4529a7d06b7801296eca9ae67aa Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 26 Nov 2009 13:34:12 +0100 Subject: kbuild: specify absolute paths for cscope Cscope doesn't hadle relative paths when cscope.out is not in $PWD. Use absolute paths when generating cscope.files, which seems to be the recommended way to generate cscope.out, anyway (at least according to cscope.sf.net). The speed and size differences are minimal, the only drawback is that the database needs to be regenerated if the source directory is moved. [mmarek: fixed for O= builds, modified changelog] Signed-off-by: Daniel Vetter Signed-off-by: Michal Marek --- scripts/tags.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/tags.sh b/scripts/tags.sh index d52f7a01557c..1a0c44d7c4a7 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -89,7 +89,13 @@ all_defconfigs() docscope() { - (echo \-k; echo \-q; all_sources) > cscope.files + # always use absolute paths for cscope, as recommended by cscope + # upstream + case "$tree" in + /*) ;; + *) tree=$PWD/$tree ;; + esac + (cd /; echo \-k; echo \-q; all_sources) > cscope.files cscope -b -f cscope.out } -- cgit v1.2.3 From d8379ab1dde371f13d7fdddf05346840a82c2b61 Mon Sep 17 00:00:00 2001 From: Tony Finch Date: Fri, 27 Nov 2009 15:50:30 +0000 Subject: unifdef: update to upstream revision 1.190 Fix handling of input files (e.g. with no newline at EOF) that could make unifdef get into an unexpected state and call abort(). The new -B option compresses blank lines around a deleted section so that blank lines around "paragraphs" of code don't get doubled. The evaluator can now handle macros with arguments, and unbracketed arguments to the "defined" operator. Add myself to MAINTAINERS for unifdef. Signed-off-by: Tony Finch Acked-by: Sam Ravnborg Signed-off-by: Michal Marek --- scripts/unifdef.c | 341 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 207 insertions(+), 134 deletions(-) (limited to 'scripts') diff --git a/scripts/unifdef.c b/scripts/unifdef.c index 30d459fb0709..44d39785e50d 100644 --- a/scripts/unifdef.c +++ b/scripts/unifdef.c @@ -1,13 +1,5 @@ /* - * Copyright (c) 2002 - 2005 Tony Finch . All rights reserved. - * - * This code is derived from software contributed to Berkeley by Dave Yost. - * It was rewritten to support ANSI C by Tony Finch. The original version of - * unifdef carried the following copyright notice. None of its code remains - * in this version (though some of the names remain). - * - * Copyright (c) 1985, 1993 - * The Regents of the University of California. All rights reserved. + * Copyright (c) 2002 - 2009 Tony Finch * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,23 +23,20 @@ * SUCH DAMAGE. */ -#include +/* + * This code was derived from software contributed to Berkeley by Dave Yost. + * It was rewritten to support ANSI C by Tony Finch. The original version + * of unifdef carried the 4-clause BSD copyright licence. None of its code + * remains in this version (though some of the names remain) so it now + * carries a more liberal licence. + * + * The latest version is available from http://dotat.at/prog/unifdef + */ -#ifndef lint -#if 0 -static const char copyright[] = -"@(#) Copyright (c) 1985, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif -#ifdef __IDSTRING -__IDSTRING(Berkeley, "@(#)unifdef.c 8.1 (Berkeley) 6/6/93"); -__IDSTRING(NetBSD, "$NetBSD: unifdef.c,v 1.8 2000/07/03 02:51:36 matt Exp $"); -__IDSTRING(dotat, "$dotat: things/unifdef.c,v 1.171 2005/03/08 12:38:48 fanf2 Exp $"); -#endif -#endif /* not lint */ -#ifdef __FBSDID -__FBSDID("$FreeBSD: /repoman/r/ncvs/src/usr.bin/unifdef/unifdef.c,v 1.20 2005/05/21 09:55:09 ru Exp $"); -#endif +static const char * const copyright[] = { + "@(#) Copyright (c) 2002 - 2009 Tony Finch \n", + "$dotat: unifdef/unifdef.c,v 1.190 2009/11/27 17:21:26 fanf2 Exp $", +}; /* * unifdef - remove ifdef'ed lines @@ -72,8 +61,6 @@ __FBSDID("$FreeBSD: /repoman/r/ncvs/src/usr.bin/unifdef/unifdef.c,v 1.20 2005/05 #include #include -size_t strlcpy(char *dst, const char *src, size_t siz); - /* types of input lines: */ typedef enum { LT_TRUEI, /* a true #if with ignore flag */ @@ -90,6 +77,7 @@ typedef enum { LT_DODGY_LAST = LT_DODGY + LT_ENDIF, LT_PLAIN, /* ordinary line */ LT_EOF, /* end of file */ + LT_ERROR, /* unevaluable #if */ LT_COUNT } Linetype; @@ -100,7 +88,7 @@ static char const * const linetype_name[] = { "DODGY IF", "DODGY TRUE", "DODGY FALSE", "DODGY ELIF", "DODGY ELTRUE", "DODGY ELFALSE", "DODGY ELSE", "DODGY ENDIF", - "PLAIN", "EOF" + "PLAIN", "EOF", "ERROR" }; /* state of #if processing */ @@ -168,11 +156,13 @@ static char const * const linestate_name[] = { * Globals. */ +static bool compblank; /* -B: compress blank lines */ +static bool lnblank; /* -b: blank deleted lines */ static bool complement; /* -c: do the complement */ static bool debugging; /* -d: debugging reports */ static bool iocccok; /* -e: fewer IOCCC errors */ +static bool strictlogic; /* -K: keep ambiguous #ifs */ static bool killconsts; /* -k: eval constant #ifs */ -static bool lnblank; /* -l: blank deleted lines */ static bool lnnum; /* -n: add #line directives */ static bool symlist; /* -s: output symbol list */ static bool text; /* -t: this is a text file */ @@ -196,7 +186,9 @@ static bool ignoring[MAXDEPTH]; /* ignore comments state */ static int stifline[MAXDEPTH]; /* start of current #if */ static int depth; /* current #if nesting */ static int delcount; /* count of deleted lines */ -static bool keepthis; /* don't delete constant #if */ +static unsigned blankcount; /* count of blank lines */ +static unsigned blankmax; /* maximum recent blankcount */ +static bool constexpr; /* constant #if expression */ static int exitstat; /* program exit status */ @@ -206,13 +198,14 @@ static void done(void); static void error(const char *); static int findsym(const char *); static void flushline(bool); -static Linetype get_line(void); +static Linetype parseline(void); static Linetype ifeval(const char **); static void ignoreoff(void); static void ignoreon(void); static void keywordedit(const char *); static void nest(void); static void process(void); +static const char *skipargs(const char *); static const char *skipcomment(const char *); static const char *skipsym(const char *); static void state(Ifstate); @@ -220,7 +213,7 @@ static int strlcmp(const char *, const char *, size_t); static void unnest(void); static void usage(void); -#define endsym(c) (!isalpha((unsigned char)c) && !isdigit((unsigned char)c) && c != '_') +#define endsym(c) (!isalnum((unsigned char)c) && c != '_') /* * The main program. @@ -230,7 +223,7 @@ main(int argc, char *argv[]) { int opt; - while ((opt = getopt(argc, argv, "i:D:U:I:cdeklnst")) != -1) + while ((opt = getopt(argc, argv, "i:D:U:I:BbcdeKklnst")) != -1) switch (opt) { case 'i': /* treat stuff controlled by these symbols as text */ /* @@ -255,6 +248,13 @@ main(int argc, char *argv[]) case 'I': /* no-op for compatibility with cpp */ break; + case 'B': /* compress blank lines around removed section */ + compblank = true; + break; + case 'b': /* blank deleted lines instead of omitting them */ + case 'l': /* backwards compatibility */ + lnblank = true; + break; case 'c': /* treat -D as -U and vice versa */ complement = true; break; @@ -264,12 +264,12 @@ main(int argc, char *argv[]) case 'e': /* fewer errors from dodgy lines */ iocccok = true; break; + case 'K': /* keep ambiguous #ifs */ + strictlogic = true; + break; case 'k': /* process constant #ifs */ killconsts = true; break; - case 'l': /* blank deleted lines instead of omitting them */ - lnblank = true; - break; case 'n': /* add #line directive after deleted lines */ lnnum = true; break; @@ -284,6 +284,8 @@ main(int argc, char *argv[]) } argc -= optind; argv += optind; + if (compblank && lnblank) + errx(2, "-B and -b are mutually exclusive"); if (argc > 1) { errx(2, "can only do one file"); } else if (argc == 1 && strcmp(*argv, "-") != 0) { @@ -302,7 +304,7 @@ main(int argc, char *argv[]) static void usage(void) { - fprintf(stderr, "usage: unifdef [-cdeklnst] [-Ipath]" + fprintf(stderr, "usage: unifdef [-BbcdeKknst] [-Ipath]" " [-Dsym[=val]] [-Usym] [-iDsym[=val]] [-iUsym] ... [file]\n"); exit(2); } @@ -383,46 +385,46 @@ static state_fn * const trans_table[IS_COUNT][LT_COUNT] = { /* IS_OUTSIDE */ { Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Eendif, Oiffy, Oiffy, Fpass, Oif, Oif, Eelif, Eelif, Eelif, Eelse, Eendif, - print, done }, + print, done, abort }, /* IS_FALSE_PREFIX */ { Idrop, Idrop, Fdrop, Fdrop, Fdrop, Mpass, Strue, Sfalse,Selse, Dendif, Idrop, Idrop, Fdrop, Fdrop, Fdrop, Mpass, Eioccc,Eioccc,Eioccc,Eioccc, - drop, Eeof }, + drop, Eeof, abort }, /* IS_TRUE_PREFIX */ { Itrue, Ifalse,Fpass, Ftrue, Ffalse,Dfalse,Dfalse,Dfalse,Delse, Dendif, Oiffy, Oiffy, Fpass, Oif, Oif, Eioccc,Eioccc,Eioccc,Eioccc,Eioccc, - print, Eeof }, + print, Eeof, abort }, /* IS_PASS_MIDDLE */ { Itrue, Ifalse,Fpass, Ftrue, Ffalse,Pelif, Mtrue, Delif, Pelse, Pendif, Oiffy, Oiffy, Fpass, Oif, Oif, Pelif, Oelif, Oelif, Pelse, Pendif, - print, Eeof }, + print, Eeof, abort }, /* IS_FALSE_MIDDLE */ { Idrop, Idrop, Fdrop, Fdrop, Fdrop, Pelif, Mtrue, Delif, Pelse, Pendif, Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eioccc,Eioccc,Eioccc,Eioccc,Eioccc, - drop, Eeof }, + drop, Eeof, abort }, /* IS_TRUE_MIDDLE */ { Itrue, Ifalse,Fpass, Ftrue, Ffalse,Melif, Melif, Melif, Melse, Pendif, Oiffy, Oiffy, Fpass, Oif, Oif, Eioccc,Eioccc,Eioccc,Eioccc,Pendif, - print, Eeof }, + print, Eeof, abort }, /* IS_PASS_ELSE */ { Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Pendif, Oiffy, Oiffy, Fpass, Oif, Oif, Eelif, Eelif, Eelif, Eelse, Pendif, - print, Eeof }, + print, Eeof, abort }, /* IS_FALSE_ELSE */ { Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eelif, Eelif, Eelif, Eelse, Dendif, Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eelif, Eelif, Eelif, Eelse, Eioccc, - drop, Eeof }, + drop, Eeof, abort }, /* IS_TRUE_ELSE */ { Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Dendif, Oiffy, Oiffy, Fpass, Oif, Oif, Eelif, Eelif, Eelif, Eelse, Eioccc, - print, Eeof }, + print, Eeof, abort }, /* IS_FALSE_TRAILER */ { Idrop, Idrop, Fdrop, Fdrop, Fdrop, Dfalse,Dfalse,Dfalse,Delse, Dendif, Idrop, Idrop, Fdrop, Fdrop, Fdrop, Dfalse,Dfalse,Dfalse,Delse, Eioccc, - drop, Eeof } + drop, Eeof, abort } /*TRUEI FALSEI IF TRUE FALSE ELIF ELTRUE ELFALSE ELSE ENDIF TRUEI FALSEI IF TRUE FALSE ELIF ELTRUE ELFALSE ELSE ENDIF (DODGY) - PLAIN EOF */ + PLAIN EOF ERROR */ }; /* @@ -463,9 +465,11 @@ keywordedit(const char *replacement) static void nest(void) { - depth += 1; - if (depth >= MAXDEPTH) + if (depth > MAXDEPTH-1) + abort(); /* bug */ + if (depth == MAXDEPTH-1) error("Too many levels of nesting"); + depth += 1; stifline[depth] = linenum; } static void @@ -490,15 +494,23 @@ flushline(bool keep) if (symlist) return; if (keep ^ complement) { - if (lnnum && delcount > 0) - printf("#line %d\n", linenum); - fputs(tline, stdout); - delcount = 0; + bool blankline = tline[strspn(tline, " \t\n")] == '\0'; + if (blankline && compblank && blankcount != blankmax) { + delcount += 1; + blankcount += 1; + } else { + if (lnnum && delcount > 0) + printf("#line %d\n", linenum); + fputs(tline, stdout); + delcount = 0; + blankmax = blankcount = blankline ? blankcount + 1 : 0; + } } else { if (lnblank) putc('\n', stdout); exitstat = 1; delcount += 1; + blankcount = 0; } } @@ -510,9 +522,12 @@ process(void) { Linetype lineval; + /* When compressing blank lines, act as if the file + is preceded by a large number of blank lines. */ + blankmax = blankcount = 1000; for (;;) { linenum++; - lineval = get_line(); + lineval = parseline(); trans_table[ifstate[depth]][lineval](); debug("process %s -> %s depth %d", linetype_name[lineval], @@ -526,7 +541,7 @@ process(void) * help from skipcomment(). */ static Linetype -get_line(void) +parseline(void) { const char *cp; int cursym; @@ -595,9 +610,21 @@ get_line(void) if (incomment) linestate = LS_DIRTY; } - /* skipcomment should have changed the state */ - if (linestate == LS_HASH) - abort(); /* bug */ + /* skipcomment normally changes the state, except + if the last line of the file lacks a newline, or + if there is too much whitespace in a directive */ + if (linestate == LS_HASH) { + size_t len = cp - tline; + if (fgets(tline + len, MAXLINE - len, input) == NULL) { + /* append the missing newline */ + tline[len+0] = '\n'; + tline[len+1] = '\0'; + cp++; + linestate = LS_START; + } else { + linestate = LS_DIRTY; + } + } } if (linestate == LS_DIRTY) { while (*cp != '\0') @@ -610,17 +637,40 @@ get_line(void) /* * These are the binary operators that are supported by the expression - * evaluator. Note that if support for division is added then we also - * need short-circuiting booleans because of divide-by-zero. + * evaluator. */ -static int op_lt(int a, int b) { return (a < b); } -static int op_gt(int a, int b) { return (a > b); } -static int op_le(int a, int b) { return (a <= b); } -static int op_ge(int a, int b) { return (a >= b); } -static int op_eq(int a, int b) { return (a == b); } -static int op_ne(int a, int b) { return (a != b); } -static int op_or(int a, int b) { return (a || b); } -static int op_and(int a, int b) { return (a && b); } +static Linetype op_strict(int *p, int v, Linetype at, Linetype bt) { + if(at == LT_IF || bt == LT_IF) return (LT_IF); + return (*p = v, v ? LT_TRUE : LT_FALSE); +} +static Linetype op_lt(int *p, Linetype at, int a, Linetype bt, int b) { + return op_strict(p, a < b, at, bt); +} +static Linetype op_gt(int *p, Linetype at, int a, Linetype bt, int b) { + return op_strict(p, a > b, at, bt); +} +static Linetype op_le(int *p, Linetype at, int a, Linetype bt, int b) { + return op_strict(p, a <= b, at, bt); +} +static Linetype op_ge(int *p, Linetype at, int a, Linetype bt, int b) { + return op_strict(p, a >= b, at, bt); +} +static Linetype op_eq(int *p, Linetype at, int a, Linetype bt, int b) { + return op_strict(p, a == b, at, bt); +} +static Linetype op_ne(int *p, Linetype at, int a, Linetype bt, int b) { + return op_strict(p, a != b, at, bt); +} +static Linetype op_or(int *p, Linetype at, int a, Linetype bt, int b) { + if (!strictlogic && (at == LT_TRUE || bt == LT_TRUE)) + return (*p = 1, LT_TRUE); + return op_strict(p, a || b, at, bt); +} +static Linetype op_and(int *p, Linetype at, int a, Linetype bt, int b) { + if (!strictlogic && (at == LT_FALSE || bt == LT_FALSE)) + return (*p = 0, LT_FALSE); + return op_strict(p, a && b, at, bt); +} /* * An evaluation function takes three arguments, as follows: (1) a pointer to @@ -629,8 +679,8 @@ static int op_and(int a, int b) { return (a && b); } * value of the expression; and (3) a pointer to a char* that points to the * expression to be evaluated and that is updated to the end of the expression * when evaluation is complete. The function returns LT_FALSE if the value of - * the expression is zero, LT_TRUE if it is non-zero, or LT_IF if the - * expression could not be evaluated. + * the expression is zero, LT_TRUE if it is non-zero, LT_IF if the expression + * depends on an unknown symbol, or LT_ERROR if there is a parse failure. */ struct ops; @@ -649,7 +699,7 @@ static const struct ops { eval_fn *inner; struct op { const char *str; - int (*fn)(int, int); + Linetype (*fn)(int *, Linetype, int, Linetype, int); } op[5]; } eval_ops[] = { { eval_table, { { "||", op_or } } }, @@ -664,8 +714,8 @@ static const struct ops { /* * Function for evaluating the innermost parts of expressions, - * viz. !expr (expr) defined(symbol) symbol number - * We reset the keepthis flag when we find a non-constant subexpression. + * viz. !expr (expr) number defined(symbol) symbol + * We reset the constexpr flag in the last two cases. */ static Linetype eval_unary(const struct ops *ops, int *valp, const char **cpp) @@ -673,68 +723,83 @@ eval_unary(const struct ops *ops, int *valp, const char **cpp) const char *cp; char *ep; int sym; + bool defparen; + Linetype lt; cp = skipcomment(*cpp); if (*cp == '!') { debug("eval%d !", ops - eval_ops); cp++; - if (eval_unary(ops, valp, &cp) == LT_IF) { - *cpp = cp; - return (LT_IF); + lt = eval_unary(ops, valp, &cp); + if (lt == LT_ERROR) + return (LT_ERROR); + if (lt != LT_IF) { + *valp = !*valp; + lt = *valp ? LT_TRUE : LT_FALSE; } - *valp = !*valp; } else if (*cp == '(') { cp++; debug("eval%d (", ops - eval_ops); - if (eval_table(eval_ops, valp, &cp) == LT_IF) - return (LT_IF); + lt = eval_table(eval_ops, valp, &cp); + if (lt == LT_ERROR) + return (LT_ERROR); cp = skipcomment(cp); if (*cp++ != ')') - return (LT_IF); + return (LT_ERROR); } else if (isdigit((unsigned char)*cp)) { debug("eval%d number", ops - eval_ops); *valp = strtol(cp, &ep, 0); + if (ep == cp) + return (LT_ERROR); + lt = *valp ? LT_TRUE : LT_FALSE; cp = skipsym(cp); } else if (strncmp(cp, "defined", 7) == 0 && endsym(cp[7])) { cp = skipcomment(cp+7); debug("eval%d defined", ops - eval_ops); - if (*cp++ != '(') - return (LT_IF); - cp = skipcomment(cp); + if (*cp == '(') { + cp = skipcomment(cp+1); + defparen = true; + } else { + defparen = false; + } sym = findsym(cp); - cp = skipsym(cp); - cp = skipcomment(cp); - if (*cp++ != ')') - return (LT_IF); - if (sym >= 0) + if (sym < 0) { + lt = LT_IF; + } else { *valp = (value[sym] != NULL); - else { - *cpp = cp; - return (LT_IF); + lt = *valp ? LT_TRUE : LT_FALSE; } - keepthis = false; + cp = skipsym(cp); + cp = skipcomment(cp); + if (defparen && *cp++ != ')') + return (LT_ERROR); + constexpr = false; } else if (!endsym(*cp)) { debug("eval%d symbol", ops - eval_ops); sym = findsym(cp); - if (sym < 0) - return (LT_IF); - if (value[sym] == NULL) + cp = skipsym(cp); + if (sym < 0) { + lt = LT_IF; + cp = skipargs(cp); + } else if (value[sym] == NULL) { *valp = 0; - else { + lt = LT_FALSE; + } else { *valp = strtol(value[sym], &ep, 0); if (*ep != '\0' || ep == value[sym]) - return (LT_IF); + return (LT_ERROR); + lt = *valp ? LT_TRUE : LT_FALSE; + cp = skipargs(cp); } - cp = skipsym(cp); - keepthis = false; + constexpr = false; } else { debug("eval%d bad expr", ops - eval_ops); - return (LT_IF); + return (LT_ERROR); } *cpp = cp; debug("eval%d = %d", ops - eval_ops, *valp); - return (*valp ? LT_TRUE : LT_FALSE); + return (lt); } /* @@ -746,11 +811,13 @@ eval_table(const struct ops *ops, int *valp, const char **cpp) const struct op *op; const char *cp; int val; - Linetype lhs, rhs; + Linetype lt, rt; debug("eval%d", ops - eval_ops); cp = *cpp; - lhs = ops->inner(ops+1, valp, &cp); + lt = ops->inner(ops+1, valp, &cp); + if (lt == LT_ERROR) + return (LT_ERROR); for (;;) { cp = skipcomment(cp); for (op = ops->op; op->str != NULL; op++) @@ -760,32 +827,16 @@ eval_table(const struct ops *ops, int *valp, const char **cpp) break; cp += strlen(op->str); debug("eval%d %s", ops - eval_ops, op->str); - rhs = ops->inner(ops+1, &val, &cp); - if (op->fn == op_and && (lhs == LT_FALSE || rhs == LT_FALSE)) { - debug("eval%d: and always false", ops - eval_ops); - if (lhs == LT_IF) - *valp = val; - lhs = LT_FALSE; - continue; - } - if (op->fn == op_or && (lhs == LT_TRUE || rhs == LT_TRUE)) { - debug("eval%d: or always true", ops - eval_ops); - if (lhs == LT_IF) - *valp = val; - lhs = LT_TRUE; - continue; - } - if (rhs == LT_IF) - lhs = LT_IF; - if (lhs != LT_IF) - *valp = op->fn(*valp, val); + rt = ops->inner(ops+1, &val, &cp); + if (rt == LT_ERROR) + return (LT_ERROR); + lt = op->fn(valp, lt, *valp, rt, val); } *cpp = cp; debug("eval%d = %d", ops - eval_ops, *valp); - if (lhs != LT_IF) - lhs = (*valp ? LT_TRUE : LT_FALSE); - return lhs; + debug("eval%d lt = %s", ops - eval_ops, linetype_name[lt]); + return (lt); } /* @@ -796,17 +847,14 @@ eval_table(const struct ops *ops, int *valp, const char **cpp) static Linetype ifeval(const char **cpp) { - const char *cp = *cpp; int ret; - int val; + int val = 0; debug("eval %s", *cpp); - keepthis = killconsts ? false : true; - ret = eval_table(eval_ops, &val, &cp); - if (ret != LT_IF) - *cpp = cp; + constexpr = killconsts ? false : true; + ret = eval_table(eval_ops, &val, cpp); debug("eval = %d", val); - return (keepthis ? LT_IF : ret); + return (constexpr ? LT_IF : ret == LT_ERROR ? LT_IF : ret); } /* @@ -917,6 +965,31 @@ skipcomment(const char *cp) return (cp); } +/* + * Skip macro arguments. + */ +static const char * +skipargs(const char *cp) +{ + const char *ocp = cp; + int level = 0; + cp = skipcomment(cp); + if (*cp != '(') + return (cp); + do { + if (*cp == '(') + level++; + if (*cp == ')') + level--; + cp = skipcomment(cp+1); + } while (level != 0 && *cp != '\0'); + if (level == 0) + return (cp); + else + /* Rewind and re-detect the syntax error later. */ + return (ocp); +} + /* * Skip over an identifier. */ @@ -929,7 +1002,7 @@ skipsym(const char *cp) } /* - * Look for the symbol in the symbol table. If is is found, we return + * Look for the symbol in the symbol table. If it is found, we return * the symbol table index, else we return -1. */ static int -- cgit v1.2.3 From 6299fee7b84ac7b4429b4e2787b99470a89cd5f5 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Sat, 5 Dec 2009 20:20:50 +0000 Subject: genksyms: properly consider EXPORT_UNUSED_SYMBOL{,_GPL}() Despite being unused these should also get a CRC calculated. Primarily I view this as a consistency thing. But I also think this is one of the reasons why __crc_* need to be weak (which I think should be avoided, and hence we should have the goal to eliminate this so that failure to calculate a proper CRC for a symbol causes the build to fail). Signed-off-by: Jan Beulich Cc: Anibal Monsalve Salazar Cc: Steven Rostedt Cc: Sam Ravnborg Signed-off-by: Andrew Morton Signed-off-by: Michal Marek --- scripts/genksyms/keywords.c_shipped | 191 ++++++++++++++++++------------------ scripts/genksyms/keywords.gperf | 2 + 2 files changed, 99 insertions(+), 94 deletions(-) (limited to 'scripts') diff --git a/scripts/genksyms/keywords.c_shipped b/scripts/genksyms/keywords.c_shipped index 287467a2e8c7..8060e06798b3 100644 --- a/scripts/genksyms/keywords.c_shipped +++ b/scripts/genksyms/keywords.c_shipped @@ -1,4 +1,4 @@ -/* ANSI-C code produced by gperf version 3.0.3 */ +/* ANSI-C code produced by gperf version 3.0.4 */ /* Command-line: gperf -L ANSI-C -a -C -E -g -H is_reserved_hash -k '1,3,$' -N is_reserved_word -p -t scripts/genksyms/keywords.gperf */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ @@ -34,7 +34,7 @@ struct resword; static const struct resword *is_reserved_word(register const char *str, register unsigned int len); #line 5 "scripts/genksyms/keywords.gperf" struct resword { const char *name; int token; }; -/* maximum key range = 62, duplicates = 0 */ +/* maximum key range = 64, duplicates = 0 */ #ifdef __GNUC__ __inline @@ -48,39 +48,39 @@ is_reserved_hash (register const char *str, register unsigned int len) { static const unsigned char asso_values[] = { - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 5, - 65, 65, 65, 65, 65, 65, 35, 65, 65, 65, - 0, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 0, 65, 0, 65, 5, - 20, 15, 10, 30, 65, 15, 65, 65, 20, 0, - 10, 35, 20, 65, 10, 5, 0, 10, 5, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65 + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 0, + 67, 67, 67, 67, 67, 67, 15, 67, 67, 67, + 0, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 0, 67, 0, 67, 5, + 25, 20, 15, 30, 67, 15, 67, 67, 10, 0, + 10, 40, 20, 67, 10, 5, 0, 10, 15, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67 }; return len + asso_values[(unsigned char)str[2]] + asso_values[(unsigned char)str[0]] + asso_values[(unsigned char)str[len - 1]]; } #ifdef __GNUC__ __inline -#ifdef __GNUC_STDC_INLINE__ +#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ __attribute__ ((__gnu_inline__)) #endif #endif @@ -89,116 +89,119 @@ is_reserved_word (register const char *str, register unsigned int len) { enum { - TOTAL_KEYWORDS = 43, + TOTAL_KEYWORDS = 45, MIN_WORD_LENGTH = 3, MAX_WORD_LENGTH = 24, MIN_HASH_VALUE = 3, - MAX_HASH_VALUE = 64 + MAX_HASH_VALUE = 66 }; static const struct resword wordlist[] = { {""}, {""}, {""}, -#line 28 "scripts/genksyms/keywords.gperf" +#line 30 "scripts/genksyms/keywords.gperf" {"asm", ASM_KEYW}, {""}, -#line 10 "scripts/genksyms/keywords.gperf" +#line 12 "scripts/genksyms/keywords.gperf" {"__asm", ASM_KEYW}, {""}, -#line 11 "scripts/genksyms/keywords.gperf" +#line 13 "scripts/genksyms/keywords.gperf" {"__asm__", ASM_KEYW}, {""}, {""}, -#line 54 "scripts/genksyms/keywords.gperf" +#line 56 "scripts/genksyms/keywords.gperf" {"__typeof__", TYPEOF_KEYW}, {""}, -#line 14 "scripts/genksyms/keywords.gperf" +#line 16 "scripts/genksyms/keywords.gperf" {"__const", CONST_KEYW}, -#line 13 "scripts/genksyms/keywords.gperf" - {"__attribute__", ATTRIBUTE_KEYW}, #line 15 "scripts/genksyms/keywords.gperf" + {"__attribute__", ATTRIBUTE_KEYW}, +#line 17 "scripts/genksyms/keywords.gperf" {"__const__", CONST_KEYW}, -#line 20 "scripts/genksyms/keywords.gperf" +#line 22 "scripts/genksyms/keywords.gperf" {"__signed__", SIGNED_KEYW}, -#line 46 "scripts/genksyms/keywords.gperf" +#line 48 "scripts/genksyms/keywords.gperf" {"static", STATIC_KEYW}, -#line 22 "scripts/genksyms/keywords.gperf" - {"__volatile__", VOLATILE_KEYW}, -#line 41 "scripts/genksyms/keywords.gperf" + {""}, +#line 43 "scripts/genksyms/keywords.gperf" {"int", INT_KEYW}, -#line 34 "scripts/genksyms/keywords.gperf" +#line 36 "scripts/genksyms/keywords.gperf" {"char", CHAR_KEYW}, -#line 35 "scripts/genksyms/keywords.gperf" +#line 37 "scripts/genksyms/keywords.gperf" {"const", CONST_KEYW}, -#line 47 "scripts/genksyms/keywords.gperf" +#line 49 "scripts/genksyms/keywords.gperf" {"struct", STRUCT_KEYW}, -#line 26 "scripts/genksyms/keywords.gperf" +#line 28 "scripts/genksyms/keywords.gperf" {"__restrict__", RESTRICT_KEYW}, -#line 27 "scripts/genksyms/keywords.gperf" +#line 29 "scripts/genksyms/keywords.gperf" {"restrict", RESTRICT_KEYW}, -#line 25 "scripts/genksyms/keywords.gperf" - {"_restrict", RESTRICT_KEYW}, -#line 18 "scripts/genksyms/keywords.gperf" +#line 9 "scripts/genksyms/keywords.gperf" + {"EXPORT_SYMBOL_GPL_FUTURE", EXPORT_SYMBOL_KEYW}, +#line 20 "scripts/genksyms/keywords.gperf" {"__inline__", INLINE_KEYW}, -#line 12 "scripts/genksyms/keywords.gperf" - {"__attribute", ATTRIBUTE_KEYW}, {""}, -#line 16 "scripts/genksyms/keywords.gperf" +#line 24 "scripts/genksyms/keywords.gperf" + {"__volatile__", VOLATILE_KEYW}, +#line 7 "scripts/genksyms/keywords.gperf" + {"EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW}, +#line 27 "scripts/genksyms/keywords.gperf" + {"_restrict", RESTRICT_KEYW}, + {""}, +#line 14 "scripts/genksyms/keywords.gperf" + {"__attribute", ATTRIBUTE_KEYW}, +#line 8 "scripts/genksyms/keywords.gperf" + {"EXPORT_SYMBOL_GPL", EXPORT_SYMBOL_KEYW}, +#line 18 "scripts/genksyms/keywords.gperf" {"__extension__", EXTENSION_KEYW}, -#line 37 "scripts/genksyms/keywords.gperf" +#line 39 "scripts/genksyms/keywords.gperf" {"enum", ENUM_KEYW}, -#line 21 "scripts/genksyms/keywords.gperf" - {"__volatile", VOLATILE_KEYW}, -#line 38 "scripts/genksyms/keywords.gperf" +#line 10 "scripts/genksyms/keywords.gperf" + {"EXPORT_UNUSED_SYMBOL", EXPORT_SYMBOL_KEYW}, +#line 40 "scripts/genksyms/keywords.gperf" {"extern", EXTERN_KEYW}, {""}, -#line 19 "scripts/genksyms/keywords.gperf" +#line 21 "scripts/genksyms/keywords.gperf" {"__signed", SIGNED_KEYW}, -#line 9 "scripts/genksyms/keywords.gperf" - {"EXPORT_SYMBOL_GPL_FUTURE", EXPORT_SYMBOL_KEYW}, - {""}, -#line 53 "scripts/genksyms/keywords.gperf" +#line 11 "scripts/genksyms/keywords.gperf" + {"EXPORT_UNUSED_SYMBOL_GPL", EXPORT_SYMBOL_KEYW}, +#line 51 "scripts/genksyms/keywords.gperf" + {"union", UNION_KEYW}, +#line 55 "scripts/genksyms/keywords.gperf" {"typeof", TYPEOF_KEYW}, -#line 48 "scripts/genksyms/keywords.gperf" +#line 50 "scripts/genksyms/keywords.gperf" {"typedef", TYPEDEF_KEYW}, -#line 17 "scripts/genksyms/keywords.gperf" +#line 19 "scripts/genksyms/keywords.gperf" {"__inline", INLINE_KEYW}, -#line 33 "scripts/genksyms/keywords.gperf" +#line 35 "scripts/genksyms/keywords.gperf" {"auto", AUTO_KEYW}, -#line 49 "scripts/genksyms/keywords.gperf" - {"union", UNION_KEYW}, - {""}, {""}, -#line 50 "scripts/genksyms/keywords.gperf" - {"unsigned", UNSIGNED_KEYW}, -#line 51 "scripts/genksyms/keywords.gperf" - {"void", VOID_KEYW}, -#line 44 "scripts/genksyms/keywords.gperf" - {"short", SHORT_KEYW}, +#line 23 "scripts/genksyms/keywords.gperf" + {"__volatile", VOLATILE_KEYW}, {""}, {""}, #line 52 "scripts/genksyms/keywords.gperf" - {"volatile", VOLATILE_KEYW}, - {""}, -#line 39 "scripts/genksyms/keywords.gperf" - {"float", FLOAT_KEYW}, -#line 36 "scripts/genksyms/keywords.gperf" - {"double", DOUBLE_KEYW}, + {"unsigned", UNSIGNED_KEYW}, {""}, -#line 7 "scripts/genksyms/keywords.gperf" - {"EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW}, - {""}, {""}, -#line 40 "scripts/genksyms/keywords.gperf" +#line 46 "scripts/genksyms/keywords.gperf" + {"short", SHORT_KEYW}, +#line 42 "scripts/genksyms/keywords.gperf" {"inline", INLINE_KEYW}, -#line 8 "scripts/genksyms/keywords.gperf" - {"EXPORT_SYMBOL_GPL", EXPORT_SYMBOL_KEYW}, -#line 43 "scripts/genksyms/keywords.gperf" - {"register", REGISTER_KEYW}, {""}, -#line 24 "scripts/genksyms/keywords.gperf" +#line 54 "scripts/genksyms/keywords.gperf" + {"volatile", VOLATILE_KEYW}, +#line 44 "scripts/genksyms/keywords.gperf" + {"long", LONG_KEYW}, +#line 26 "scripts/genksyms/keywords.gperf" {"_Bool", BOOL_KEYW}, -#line 45 "scripts/genksyms/keywords.gperf" - {"signed", SIGNED_KEYW}, {""}, {""}, -#line 42 "scripts/genksyms/keywords.gperf" - {"long", LONG_KEYW} +#line 45 "scripts/genksyms/keywords.gperf" + {"register", REGISTER_KEYW}, +#line 53 "scripts/genksyms/keywords.gperf" + {"void", VOID_KEYW}, +#line 41 "scripts/genksyms/keywords.gperf" + {"float", FLOAT_KEYW}, +#line 38 "scripts/genksyms/keywords.gperf" + {"double", DOUBLE_KEYW}, + {""}, {""}, {""}, {""}, +#line 47 "scripts/genksyms/keywords.gperf" + {"signed", SIGNED_KEYW} }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) diff --git a/scripts/genksyms/keywords.gperf b/scripts/genksyms/keywords.gperf index 8fe977a4d57b..e6349acb6f2f 100644 --- a/scripts/genksyms/keywords.gperf +++ b/scripts/genksyms/keywords.gperf @@ -7,6 +7,8 @@ struct resword { const char *name; int token; } EXPORT_SYMBOL, EXPORT_SYMBOL_KEYW EXPORT_SYMBOL_GPL, EXPORT_SYMBOL_KEYW EXPORT_SYMBOL_GPL_FUTURE, EXPORT_SYMBOL_KEYW +EXPORT_UNUSED_SYMBOL, EXPORT_SYMBOL_KEYW +EXPORT_UNUSED_SYMBOL_GPL, EXPORT_SYMBOL_KEYW __asm, ASM_KEYW __asm__, ASM_KEYW __attribute, ATTRIBUTE_KEYW -- cgit v1.2.3 From bc081dd6e9f622c73334dc465359168543ccaabf Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Mon, 7 Dec 2009 16:38:33 +0100 Subject: kbuild: generate modules.builtin To make it easier for module-init-tools and scripts like mkinitrd to distinguish builtin and missing modules, install a modules.builtin file listing all builtin modules. This is done by generating an additional config file (tristate.conf) with tristate options set to uppercase 'Y' or 'M'. If we source that config file, the builtin modules appear in obj-Y. Signed-off-by: Michal Marek --- scripts/Kbuild.include | 6 +++++ scripts/Makefile.modbuiltin | 55 +++++++++++++++++++++++++++++++++++++++++++++ scripts/kconfig/confdata.c | 22 +++++++++++++++++- 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 scripts/Makefile.modbuiltin (limited to 'scripts') diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index c67e73ecd5be..ed2773edfe71 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -149,6 +149,12 @@ ld-option = $(call try-run,\ # $(Q)$(MAKE) $(build)=dir build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj +### +# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.modbuiltin obj= +# Usage: +# $(Q)$(MAKE) $(modbuiltin)=dir +modbuiltin := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.modbuiltin obj + # Prefix -I with $(srctree) if it is not an absolute path. # skip if -I has no parameter addtree = $(if $(patsubst -I%,%,$(1)), \ diff --git a/scripts/Makefile.modbuiltin b/scripts/Makefile.modbuiltin new file mode 100644 index 000000000000..102a276f6eea --- /dev/null +++ b/scripts/Makefile.modbuiltin @@ -0,0 +1,55 @@ +# ========================================================================== +# Generating modules.builtin +# ========================================================================== + +src := $(obj) + +PHONY := __modbuiltin +__modbuiltin: + +-include include/config/auto.conf +# tristate.conf sets tristate variables to uppercase 'Y' or 'M' +# That way, we get the list of built-in modules in obj-Y +-include include/config/tristate.conf + +include scripts/Kbuild.include + +# The filename Kbuild has precedence over Makefile +kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) +kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile) +include $(kbuild-file) + +include scripts/Makefile.lib +__subdir-Y := $(patsubst %/,%,$(filter %/, $(obj-Y))) +subdir-Y += $(__subdir-Y) +subdir-ym := $(sort $(subdir-y) $(subdir-Y) $(subdir-m)) +subdir-ym := $(addprefix $(obj)/,$(subdir-ym)) +obj-Y := $(addprefix $(obj)/,$(obj-Y)) + +modbuiltin-subdirs := $(patsubst %,%/modules.builtin, $(subdir-ym)) +modbuiltin-mods := $(filter %.ko, $(obj-Y:.o=.ko)) +modbuiltin-target := $(obj)/modules.builtin + +__modbuiltin: $(modbuiltin-target) $(subdir-ym) + @: + +$(modbuiltin-target): $(subdir-ym) FORCE + $(Q)(for m in $(modbuiltin-mods); do echo kernel/$$m; done; \ + cat /dev/null $(modbuiltin-subdirs)) > $@ + +PHONY += FORCE + +FORCE: + +# Descending +# --------------------------------------------------------------------------- + +PHONY += $(subdir-ym) +$(subdir-ym): + $(Q)$(MAKE) $(modbuiltin)=$@ + + +# Declare the contents of the .PHONY variable as phony. We keep that +# information in a variable se we can use it in if_changed and friends. + +.PHONY: $(PHONY) diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 797a7410f690..c4dec80cfd8e 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -677,7 +677,7 @@ int conf_write_autoconf(void) struct symbol *sym; const char *str; const char *name; - FILE *out, *out_h; + FILE *out, *tristate, *out_h; time_t now; int i, l; @@ -692,9 +692,16 @@ int conf_write_autoconf(void) if (!out) return 1; + tristate = fopen(".tmpconfig_tristate", "w"); + if (!tristate) { + fclose(out); + return 1; + } + out_h = fopen(".tmpconfig.h", "w"); if (!out_h) { fclose(out); + fclose(tristate); return 1; } @@ -707,6 +714,9 @@ int conf_write_autoconf(void) "# %s" "#\n", sym_get_string_value(sym), ctime(&now)); + fprintf(tristate, "#\n" + "# Automatically generated - do not edit\n" + "\n"); fprintf(out_h, "/*\n" " * Automatically generated C config: don't edit\n" " * Linux kernel version: %s\n" @@ -727,10 +737,14 @@ int conf_write_autoconf(void) break; case mod: fprintf(out, "CONFIG_%s=m\n", sym->name); + fprintf(tristate, "CONFIG_%s=M\n", sym->name); fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name); break; case yes: fprintf(out, "CONFIG_%s=y\n", sym->name); + if (sym->type == S_TRISTATE) + fprintf(tristate, "CONFIG_%s=Y\n", + sym->name); fprintf(out_h, "#define CONFIG_%s 1\n", sym->name); break; } @@ -772,6 +786,7 @@ int conf_write_autoconf(void) } } fclose(out); + fclose(tristate); fclose(out_h); name = getenv("KCONFIG_AUTOHEADER"); @@ -779,6 +794,11 @@ int conf_write_autoconf(void) name = "include/generated/autoconf.h"; if (rename(".tmpconfig.h", name)) return 1; + name = getenv("KCONFIG_TRISTATE"); + if (!name) + name = "include/config/tristate.conf"; + if (rename(".tmpconfig_tristate", name)) + return 1; name = conf_get_autoconfig_name(); /* * This must be the last step, kbuild has a dependency on auto.conf -- cgit v1.2.3 From 7d241ff0567b9503d79ee775c40927d09b509f83 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 10 Dec 2009 14:15:44 +0100 Subject: microblaze: ftrace: Add dynamic trace support With dynamic function tracer, by default, _mcount is defined as an "empty" function, it returns directly without any more action. When enabling it in user-space, it will jump to a real tracing function(ftrace_caller), and do the real job for us. Differ from the static function tracer, dynamic function tracer provides two functions ftrace_make_call()/ftrace_make_nop() to enable/disable the tracing of some indicated kernel functions(set_ftrace_filter). In the kernel version, there is only one "_mcount" string for every kernel function, so, we just need to match this one in mcount_regex of scripts/recordmcount.pl. For more information please look at code and Documentation/trace folder. Steven ACK that scripts/recordmcount.pl part. Acked-by: Steven Rostedt Signed-off-by: Michal Simek --- scripts/recordmcount.pl | 3 +++ 1 file changed, 3 insertions(+) (limited to 'scripts') diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl index f0d14452632b..9cf0a6fad6ba 100755 --- a/scripts/recordmcount.pl +++ b/scripts/recordmcount.pl @@ -295,6 +295,9 @@ if ($arch eq "x86_64") { $ld .= " -m elf64_sparc"; $cc .= " -m64"; $objcopy .= " -O elf64-sparc"; +} elsif ($arch eq "microblaze") { + # Microblaze calls '_mcount' instead of plain 'mcount'. + $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$"; } else { die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD"; } -- cgit v1.2.3 From 9e1b9b80721661bd63b3662453767b22cd614fe7 Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Sat, 7 Nov 2009 21:03:54 +0000 Subject: module: make MODULE_SYMBOL_PREFIX into a CONFIG option The next commit will require the use of MODULE_SYMBOL_PREFIX in .tmp_exports-asm.S. Currently it is mixed in with C structure definitions in "asm/module.h". Move the definition of this arch option into Kconfig, so it can be easily accessed by any code. This also lets modpost.c use the same definition. Previously modpost relied on a hardcoded list of architectures in mk_elfconfig.c. A build test for blackfin, one of the two MODULE_SYMBOL_PREFIX archs, showed the generated code was unchanged. vmlinux was identical save for build ids, and an apparently randomized suffix on a single "__key" symbol in the kallsyms data). Signed-off-by: Alan Jenkins Acked-by: Mike Frysinger (blackfin) CC: Sam Ravnborg Signed-off-by: Rusty Russell --- scripts/Makefile.lib | 5 +++++ scripts/mod/Makefile | 2 +- scripts/mod/mk_elfconfig.c | 9 --------- scripts/mod/modpost.c | 9 +++++++++ 4 files changed, 15 insertions(+), 10 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index ffdafb26f539..224d85e72ef1 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -127,6 +127,11 @@ _c_flags += $(if $(patsubst n%,, \ $(CFLAGS_GCOV)) endif +ifdef CONFIG_SYMBOL_PREFIX +_cpp_flags += -DSYMBOL_PREFIX=$(patsubst "%",%,$(CONFIG_SYMBOL_PREFIX)) +endif + + # If building the kernel in a separate objtree expand all occurrences # of -Idir to -I$(srctree)/dir except for absolute paths (starting with '/'). diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile index 11d69c35e5b4..ff954f8168c1 100644 --- a/scripts/mod/Makefile +++ b/scripts/mod/Makefile @@ -8,7 +8,7 @@ modpost-objs := modpost.o file2alias.o sumversion.o $(obj)/modpost.o $(obj)/file2alias.o $(obj)/sumversion.o: $(obj)/elfconfig.h quiet_cmd_elfconfig = MKELF $@ - cmd_elfconfig = $(obj)/mk_elfconfig $(ARCH) < $< > $@ + cmd_elfconfig = $(obj)/mk_elfconfig < $< > $@ $(obj)/elfconfig.h: $(obj)/empty.o $(obj)/mk_elfconfig FORCE $(call if_changed,elfconfig) diff --git a/scripts/mod/mk_elfconfig.c b/scripts/mod/mk_elfconfig.c index 6a96d47bd1e6..639bca7ba559 100644 --- a/scripts/mod/mk_elfconfig.c +++ b/scripts/mod/mk_elfconfig.c @@ -9,9 +9,6 @@ main(int argc, char **argv) unsigned char ei[EI_NIDENT]; union { short s; char c[2]; } endian_test; - if (argc != 2) { - fprintf(stderr, "Error: no arch\n"); - } if (fread(ei, 1, EI_NIDENT, stdin) != EI_NIDENT) { fprintf(stderr, "Error: input truncated\n"); return 1; @@ -55,12 +52,6 @@ main(int argc, char **argv) else exit(1); - if ((strcmp(argv[1], "h8300") == 0) - || (strcmp(argv[1], "blackfin") == 0)) - printf("#define MODULE_SYMBOL_PREFIX \"_\"\n"); - else - printf("#define MODULE_SYMBOL_PREFIX \"\"\n"); - return 0; } diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 801a16a17545..fb0f9b711af3 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -15,8 +15,17 @@ #include #include #include "modpost.h" +#include "../../include/linux/autoconf.h" #include "../../include/linux/license.h" +/* Some toolchains use a `_' prefix for all user symbols. */ +#ifdef CONFIG_SYMBOL_PREFIX +#define MODULE_SYMBOL_PREFIX CONFIG_SYMBOL_PREFIX +#else +#define MODULE_SYMBOL_PREFIX "" +#endif + + /* Are we using CONFIG_MODVERSIONS? */ int modversions = 0; /* Warn about undefined symbols? (do so if we have vmlinux) */ -- cgit v1.2.3 From a8773769d1a1e08d0ca15f890515401ab3860637 Mon Sep 17 00:00:00 2001 From: Wenji Huang Date: Mon, 16 Nov 2009 13:49:55 +0800 Subject: Kbuild: clear marker out of modpost Remove the unnecessary functions and variables. Signed-off-by: Wenji Huang Signed-off-by: Michal Marek Signed-off-by: Rusty Russell --- scripts/mod/modpost.c | 164 -------------------------------------------------- scripts/mod/modpost.h | 3 - 2 files changed, 167 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index fb0f9b711af3..c16c0a0e2464 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -460,8 +460,6 @@ static int parse_elf(struct elf_info *info, const char *filename) info->export_unused_gpl_sec = i; else if (strcmp(secname, "__ksymtab_gpl_future") == 0) info->export_gpl_future_sec = i; - else if (strcmp(secname, "__markers_strings") == 0) - info->markers_strings_sec = i; if (sechdrs[i].sh_type != SHT_SYMTAB) continue; @@ -1518,62 +1516,6 @@ static void check_sec_ref(struct module *mod, const char *modname, } } -static void get_markers(struct elf_info *info, struct module *mod) -{ - const Elf_Shdr *sh = &info->sechdrs[info->markers_strings_sec]; - const char *strings = (const char *) info->hdr + sh->sh_offset; - const Elf_Sym *sym, *first_sym, *last_sym; - size_t n; - - if (!info->markers_strings_sec) - return; - - /* - * First count the strings. We look for all the symbols defined - * in the __markers_strings section named __mstrtab_*. For - * these local names, the compiler puts a random .NNN suffix on, - * so the names don't correspond exactly. - */ - first_sym = last_sym = NULL; - n = 0; - for (sym = info->symtab_start; sym < info->symtab_stop; sym++) - if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT && - sym->st_shndx == info->markers_strings_sec && - !strncmp(info->strtab + sym->st_name, - "__mstrtab_", sizeof "__mstrtab_" - 1)) { - if (first_sym == NULL) - first_sym = sym; - last_sym = sym; - ++n; - } - - if (n == 0) - return; - - /* - * Now collect each name and format into a line for the output. - * Lines look like: - * marker_name vmlinux marker %s format %d - * The format string after the second \t can use whitespace. - */ - mod->markers = NOFAIL(malloc(sizeof mod->markers[0] * n)); - mod->nmarkers = n; - - n = 0; - for (sym = first_sym; sym <= last_sym; sym++) - if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT && - sym->st_shndx == info->markers_strings_sec && - !strncmp(info->strtab + sym->st_name, - "__mstrtab_", sizeof "__mstrtab_" - 1)) { - const char *name = strings + sym->st_value; - const char *fmt = strchr(name, '\0') + 1; - char *line = NULL; - asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt); - NOFAIL(line); - mod->markers[n++] = line; - } -} - static void read_symbols(char *modname) { const char *symname; @@ -1629,8 +1571,6 @@ static void read_symbols(char *modname) get_src_version(modname, mod->srcversion, sizeof(mod->srcversion)-1); - get_markers(&info, mod); - parse_elf_finish(&info); /* Our trick to get versioning for module struct etc. - it's @@ -1985,96 +1925,6 @@ static void write_dump(const char *fname) write_if_changed(&buf, fname); } -static void add_marker(struct module *mod, const char *name, const char *fmt) -{ - char *line = NULL; - asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt); - NOFAIL(line); - - mod->markers = NOFAIL(realloc(mod->markers, ((mod->nmarkers + 1) * - sizeof mod->markers[0]))); - mod->markers[mod->nmarkers++] = line; -} - -static void read_markers(const char *fname) -{ - unsigned long size, pos = 0; - void *file = grab_file(fname, &size); - char *line; - - if (!file) /* No old markers, silently ignore */ - return; - - while ((line = get_next_line(&pos, file, size))) { - char *marker, *modname, *fmt; - struct module *mod; - - marker = line; - modname = strchr(marker, '\t'); - if (!modname) - goto fail; - *modname++ = '\0'; - fmt = strchr(modname, '\t'); - if (!fmt) - goto fail; - *fmt++ = '\0'; - if (*marker == '\0' || *modname == '\0') - goto fail; - - mod = find_module(modname); - if (!mod) { - mod = new_module(modname); - mod->skip = 1; - } - if (is_vmlinux(modname)) { - have_vmlinux = 1; - mod->skip = 0; - } - - if (!mod->skip) - add_marker(mod, marker, fmt); - } - release_file(file, size); - return; -fail: - fatal("parse error in markers list file\n"); -} - -static int compare_strings(const void *a, const void *b) -{ - return strcmp(*(const char **) a, *(const char **) b); -} - -static void write_markers(const char *fname) -{ - struct buffer buf = { }; - struct module *mod; - size_t i; - - for (mod = modules; mod; mod = mod->next) - if ((!external_module || !mod->skip) && mod->markers != NULL) { - /* - * Sort the strings so we can skip duplicates when - * we write them out. - */ - qsort(mod->markers, mod->nmarkers, - sizeof mod->markers[0], &compare_strings); - for (i = 0; i < mod->nmarkers; ++i) { - char *line = mod->markers[i]; - buf_write(&buf, line, strlen(line)); - while (i + 1 < mod->nmarkers && - !strcmp(mod->markers[i], - mod->markers[i + 1])) - free(mod->markers[i++]); - free(mod->markers[i]); - } - free(mod->markers); - mod->markers = NULL; - } - - write_if_changed(&buf, fname); -} - struct ext_sym_list { struct ext_sym_list *next; const char *file; @@ -2086,8 +1936,6 @@ int main(int argc, char **argv) struct buffer buf = { }; char *kernel_read = NULL, *module_read = NULL; char *dump_write = NULL; - char *markers_read = NULL; - char *markers_write = NULL; int opt; int err; struct ext_sym_list *extsym_iter; @@ -2131,12 +1979,6 @@ int main(int argc, char **argv) case 'w': warn_unresolved = 1; break; - case 'M': - markers_write = optarg; - break; - case 'K': - markers_read = optarg; - break; default: exit(1); } @@ -2191,11 +2033,5 @@ int main(int argc, char **argv) "'make CONFIG_DEBUG_SECTION_MISMATCH=y'\n", sec_mismatch_count); - if (markers_read) - read_markers(markers_read); - - if (markers_write) - write_markers(markers_write); - return err; } diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 09f58e33d227..be987a44f250 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -112,8 +112,6 @@ struct module { int has_init; int has_cleanup; struct buffer dev_table_buf; - char **markers; - size_t nmarkers; char srcversion[25]; }; @@ -128,7 +126,6 @@ struct elf_info { Elf_Section export_gpl_sec; Elf_Section export_unused_gpl_sec; Elf_Section export_gpl_future_sec; - Elf_Section markers_strings_sec; const char *strtab; char *modinfo; unsigned int modinfo_len; -- cgit v1.2.3 From 8d99513c1b76cfd0b2dcf061c5136cb1061e6b37 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Sat, 12 Dec 2009 12:02:24 +0100 Subject: modpost: fix segfault with short symbol names memcmp() is wrong here, the symbol name can be shorter than KSYMTAB_PFX or CRC_PFX. Signed-off-by: Michal Marek Signed-off-by: Rusty Russell --- scripts/mod/modpost.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index c16c0a0e2464..6c4ffc767b91 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -522,7 +522,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info, break; case SHN_ABS: /* CRC'd symbol */ - if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { + if (strncmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { crc = (unsigned int) sym->st_value; sym_update_crc(symname + strlen(CRC_PFX), mod, crc, export); @@ -566,7 +566,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info, break; default: /* All exported symbols */ - if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) { + if (strncmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) { sym_add_exported(symname + strlen(KSYMTAB_PFX), mod, export); } -- cgit v1.2.3 From 3c7385b81f721f0e7648d5134afb2088b28f8c69 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 14 Dec 2009 18:00:46 -0800 Subject: scripts/get_maintainer.pl: add --roles and --rolestats --roles shows the role of each email address, i.e. why it was selected. --rolestats selects --roles and adds git log/blame signers #'s and % Multiple roles are possible (supporter, maintainer, git-signer...) --roles or --rolestats is meant to help identify appropriate maintainers to notify and should not be used with "git send-email --cc-cmd" Example output: Existing: $ ./scripts/get_maintainer.pl -f arch/x86/kernel/acpi/boot.c Corentin Chary Karol Kozimor Len Brown Pavel Machek Rafael J. Wysocki Thomas Gleixner Ingo Molnar H. Peter Anvin x86@kernel.org Yinghai Lu Jeremy Fitzhardinge acpi4asus-user@lists.sourceforge.net linux-pm@lists.linux-foundation.org linux-kernel@vger.kernel.org With --roles $ ./scripts/get_maintainer.pl --roles -f arch/x86/kernel/acpi/boot.c Corentin Chary (maintainer:ASUS ACPI EXTRAS...) Karol Kozimor (maintainer:ASUS ACPI EXTRAS...) Len Brown (supporter:SUSPEND TO RAM,git-signer) Pavel Machek (supporter:SUSPEND TO RAM) Rafael J. Wysocki (supporter:SUSPEND TO RAM) Thomas Gleixner (maintainer:X86 ARCHITECTURE...) Ingo Molnar (maintainer:X86 ARCHITECTURE...,git-signer) H. Peter Anvin (maintainer:X86 ARCHITECTURE...) x86@kernel.org (maintainer:X86 ARCHITECTURE...) Yinghai Lu (git-signer) Jeremy Fitzhardinge (git-signer) acpi4asus-user@lists.sourceforge.net (open list:ASUS ACPI EXTRAS...) linux-pm@lists.linux-foundation.org (open list:SUSPEND TO RAM) linux-kernel@vger.kernel.org (open list) With --rolestats $ ./scripts/get_maintainer.pl --rolestats -f arch/x86/kernel/acpi/boot.c Corentin Chary (maintainer:ASUS ACPI EXTRAS...) Karol Kozimor (maintainer:ASUS ACPI EXTRAS...) Len Brown (supporter:SUSPEND TO RAM,git-signer:16/79=20%) Pavel Machek (supporter:SUSPEND TO RAM) Rafael J. Wysocki (supporter:SUSPEND TO RAM) Thomas Gleixner (maintainer:X86 ARCHITECTURE...) Ingo Molnar (maintainer:X86 ARCHITECTURE...,git-signer:29/79=37%) H. Peter Anvin (maintainer:X86 ARCHITECTURE...) x86@kernel.org (maintainer:X86 ARCHITECTURE...) Yinghai Lu (git-signer:12/79=15%) Jeremy Fitzhardinge (git-signer:6/79=8%) acpi4asus-user@lists.sourceforge.net (open list:ASUS ACPI EXTRAS...) linux-pm@lists.linux-foundation.org (open list:SUSPEND TO RAM) linux-kernel@vger.kernel.org (open list) With --rolestats and --git-blame $ ./scripts/get_maintainer.pl --rolestats --git-blame -f arch/x86/kernel/acpi/boot.c Corentin Chary (maintainer:ASUS ACPI EXTRAS...) Karol Kozimor (maintainer:ASUS ACPI EXTRAS...) Len Brown (supporter:SUSPEND TO RAM,git-signer:16/79=20%,commits:22/154=14%) Pavel Machek (supporter:SUSPEND TO RAM) Rafael J. Wysocki (supporter:SUSPEND TO RAM) Thomas Gleixner (maintainer:X86 ARCHITECTURE...) Ingo Molnar (maintainer:X86 ARCHITECTURE...,git-signer:29/79=37%,commits:36/154=23%) H. Peter Anvin (maintainer:X86 ARCHITECTURE...) x86@kernel.org (maintainer:X86 ARCHITECTURE...) Yinghai Lu (git-signer:12/79=15%,commits:9/154=6%) Jeremy Fitzhardinge (git-signer:6/79=8%) Andi Kleen (commits:11/154=7%) Andrew Morton (commits:10/154=6%) acpi4asus-user@lists.sourceforge.net (open list:ASUS ACPI EXTRAS...) linux-pm@lists.linux-foundation.org (open list:SUSPEND TO RAM) linux-kernel@vger.kernel.org (open list) Other changes: Format git-signers email addresses a bit to reduce bad signatures Command line bad arguments emitted a verbose usage(), just show --help Version number bumped to .22 Ben Hutchings had the idea and created a good deal of this implementation. Signed-off-by: Joe Perches Signed-off-by: Ben Hutchings Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/get_maintainer.pl | 194 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 176 insertions(+), 18 deletions(-) (limited to 'scripts') diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index 81a67a458e78..4e11c271e613 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl @@ -13,7 +13,7 @@ use strict; my $P = $0; -my $V = '0.21'; +my $V = '0.22'; use Getopt::Long qw(:config no_auto_abbrev); @@ -33,6 +33,8 @@ my $email_git_blame = 0; my $email_remove_duplicates = 1; my $output_multiline = 1; my $output_separator = ", "; +my $output_roles = 0; +my $output_rolestats = 0; my $scm = 0; my $web = 0; my $subsystem = 0; @@ -79,6 +81,8 @@ if (!GetOptions( 'l!' => \$email_list, 's!' => \$email_subscriber_list, 'multiline!' => \$output_multiline, + 'roles!' => \$output_roles, + 'rolestats!' => \$output_rolestats, 'separator=s' => \$output_separator, 'subsystem!' => \$subsystem, 'status!' => \$status, @@ -90,8 +94,7 @@ if (!GetOptions( 'v|version' => \$version, 'h|help' => \$help, )) { - usage(); - die "$P: invalid argument\n"; + die "$P: invalid argument - use --help if necessary\n"; } if ($help != 0) { @@ -113,6 +116,10 @@ if ($output_separator ne ", ") { $output_multiline = 0; } +if ($output_rolestats) { + $output_roles = 1; +} + my $selections = $email + $scm + $status + $subsystem + $web; if ($selections == 0) { usage(); @@ -326,9 +333,9 @@ if ($email) { $email_address = format_email($1, $2); if ($email_git_penguin_chiefs) { - push(@email_to, $email_address); + push(@email_to, [$email_address, 'chief penguin']); } else { - @email_to = grep(!/${email_address}/, @email_to); + @email_to = grep($_->[0] !~ /${email_address}/, @email_to); } } } @@ -342,7 +349,7 @@ if ($email || $email_list) { if ($email_list) { @to = (@to, @list_to); } - output(uniq(@to)); + output(merge_email(@to)); } if ($scm) { @@ -405,6 +412,8 @@ MAINTAINER field selection options: --l => include list(s) if any --s => include subscriber only list(s) if any --remove-duplicates => minimize duplicate email names/addresses + --roles => show roles (status:subsystem, git-signer, list, etc...) + --rolestats => show roles and statistics (commits/total_commits, %) --scm => print SCM tree(s) if any --status => print status if any --subsystem => print subsystem name if any @@ -435,6 +444,13 @@ Notes: Used with "--git-blame", does not iterate all files in directory Using "--git-blame" is slow and may add old committers and authors that are no longer active maintainers to the output. + Using "--roles" or "--rolestats" with git send-email --cc-cmd or any + other automated tools that expect only ["name"] + may not work because of additional output after . + Using "--rolestats" and "--git-blame" shows the #/total=% commits, + not the percentage of the entire file authored. # of commits is + not a good measure of amount of code authored. 1 major commit may + contain a thousand lines, 5 trivial commits may modify a single line. EOT } @@ -547,6 +563,71 @@ sub find_ending_index { return $index; } +sub get_maintainer_role { + my ($index) = @_; + + my $i; + my $start = find_starting_index($index); + my $end = find_ending_index($index); + + my $role; + my $subsystem = $typevalue[$start]; + if (length($subsystem) > 20) { + $subsystem = substr($subsystem, 0, 17); + $subsystem =~ s/\s*$//; + $subsystem = $subsystem . "..."; + } + + for ($i = $start + 1; $i < $end; $i++) { + my $tv = $typevalue[$i]; + if ($tv =~ m/^(\C):\s*(.*)/) { + my $ptype = $1; + my $pvalue = $2; + if ($ptype eq "S") { + $role = $pvalue; + } + } + } + + $role = lc($role); + if ($role eq "supported") { + $role = "supporter"; + } elsif ($role eq "maintained") { + $role = "maintainer"; + } elsif ($role eq "odd fixes") { + $role = "odd fixer"; + } elsif ($role eq "orphan") { + $role = "orphan minder"; + } elsif ($role eq "obsolete") { + $role = "obsolete minder"; + } elsif ($role eq "buried alive in reporters") { + $role = "chief penguin"; + } + + return $role . ":" . $subsystem; +} + +sub get_list_role { + my ($index) = @_; + + my $i; + my $start = find_starting_index($index); + my $end = find_ending_index($index); + + my $subsystem = $typevalue[$start]; + if (length($subsystem) > 20) { + $subsystem = substr($subsystem, 0, 17); + $subsystem =~ s/\s*$//; + $subsystem = $subsystem . "..."; + } + + if ($subsystem eq "THE REST") { + $subsystem = ""; + } + + return $subsystem; +} + sub add_categories { my ($index) = @_; @@ -564,17 +645,22 @@ sub add_categories { if ($ptype eq "L") { my $list_address = $pvalue; my $list_additional = ""; + my $list_role = get_list_role($i); + + if ($list_role ne "") { + $list_role = ":" . $list_role; + } if ($list_address =~ m/([^\s]+)\s+(.*)$/) { $list_address = $1; $list_additional = $2; } if ($list_additional =~ m/subscribers-only/) { if ($email_subscriber_list) { - push(@list_to, $list_address); + push(@list_to, [$list_address, "subscriber list${list_role}"]); } } else { if ($email_list) { - push(@list_to, $list_address); + push(@list_to, [$list_address, "open list${list_role}"]); } } } elsif ($ptype eq "M") { @@ -591,7 +677,8 @@ sub add_categories { } } if ($email_maintainer) { - push_email_addresses($pvalue); + my $role = get_maintainer_role($i); + push_email_addresses($pvalue, $role); } } elsif ($ptype eq "T") { push(@scm, $pvalue); @@ -618,7 +705,7 @@ sub email_inuse { } sub push_email_address { - my ($line) = @_; + my ($line, $role) = @_; my ($name, $address) = parse_email($line); @@ -627,9 +714,9 @@ sub push_email_address { } if (!$email_remove_duplicates) { - push(@email_to, format_email($name, $address)); + push(@email_to, [format_email($name, $address), $role]); } elsif (!email_inuse($name, $address)) { - push(@email_to, format_email($name, $address)); + push(@email_to, [format_email($name, $address), $role]); $email_hash_name{$name}++; $email_hash_address{$address}++; } @@ -638,24 +725,52 @@ sub push_email_address { } sub push_email_addresses { - my ($address) = @_; + my ($address, $role) = @_; my @address_list = (); if (rfc822_valid($address)) { - push_email_address($address); + push_email_address($address, $role); } elsif (@address_list = rfc822_validlist($address)) { my $array_count = shift(@address_list); while (my $entry = shift(@address_list)) { - push_email_address($entry); + push_email_address($entry, $role); } } else { - if (!push_email_address($address)) { + if (!push_email_address($address, $role)) { warn("Invalid MAINTAINERS address: '" . $address . "'\n"); } } } +sub add_role { + my ($line, $role) = @_; + + my ($name, $address) = parse_email($line); + my $email = format_email($name, $address); + + foreach my $entry (@email_to) { + if ($email_remove_duplicates) { + my ($entry_name, $entry_address) = parse_email($entry->[0]); + if ($name eq $entry_name || $address eq $entry_address) { + if ($entry->[1] eq "") { + $entry->[1] = "$role"; + } else { + $entry->[1] = "$entry->[1],$role"; + } + } + } else { + if ($email eq $entry->[0]) { + if ($entry->[1] eq "") { + $entry->[1] = "$role"; + } else { + $entry->[1] = "$entry->[1],$role"; + } + } + } + } +} + sub which { my ($bin) = @_; @@ -730,6 +845,10 @@ sub recent_git_signoffs { s/.*:\s*(.+)\s*/$1/ for (@lines); $total_sign_offs = @lines; + foreach my $line (@lines) { + my ($name, $address) = parse_email($line); + $line = format_email($name, $address); + } if ($email_remove_duplicates) { @lines = mailmap(@lines); @@ -743,11 +862,19 @@ sub recent_git_signoffs { # sort -rn foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) { my $sign_offs = $hash{$line}; + my $role; + $count++; last if ($sign_offs < $email_git_min_signatures || $count > $email_git_max_maintainers || $sign_offs * 100 / $total_sign_offs < $email_git_min_percent); - push_email_address($line); + push_email_address($line, ''); + $role = "git-signer"; + if ($output_rolestats) { + my $percent = sprintf("%.0f", $sign_offs * 100 / $total_sign_offs); + $role = "$role:$sign_offs/$total_sign_offs=$percent%"; + } + add_role($line, $role); } } @@ -824,11 +951,23 @@ sub git_assign_blame { $count = 0; foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) { my $sign_offs = $hash{$line}; + my $role; + $count++; last if ($sign_offs < $email_git_min_signatures || $count > $email_git_max_maintainers || $sign_offs * 100 / $total_sign_offs < $email_git_min_percent); - push_email_address($line); + push_email_address($line, ''); + if ($from_filename) { + $role = "commits"; + } else { + $role = "modified commits"; + } + if ($output_rolestats) { + my $percent = sprintf("%.0f", $sign_offs * 100 / $total_sign_offs); + $role = "$role:$sign_offs/$total_sign_offs=$percent%"; + } + add_role($line, $role); } } @@ -849,6 +988,25 @@ sub sort_and_uniq { return @parms; } +sub merge_email { + my @lines; + my %saw; + + for (@_) { + my ($address, $role) = @$_; + if (!$saw{$address}) { + if ($output_roles) { + push @lines, "$address ($role)"; + } else { + push @lines, $address; + } + $saw{$address} = 1; + } + } + + return @lines; +} + sub output { my @parms = @_; -- cgit v1.2.3 From a8af2430f3fb997951eff3d0d51cb166b399782b Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 14 Dec 2009 18:00:49 -0800 Subject: scripts/get_maintainer.pl: fix --non with --git-blame and cleanups Fix email matching without name --n and --git-blame Using --non and --git-blame caused maintainer signature matching to fail. Fixed that by adding 3rd argument to sub format_email to control show/hide name portion of address Slurp -f file instead of reading line-by-line for K: pattern matching. Suggested by Wolfram Sang as more efficient Refactor git command execution Break into 2 functions, execute/analyze Share code between --git and --git-blame Don't warn multiple times when git isn't installed Improve stats reporting --git-min-percent and -- rolestats now count the total number of commits for either the period of --git-since or if using --git-blame the commits used by the current file and calculate commit % as # of commits signed / total commits * 100 Code style cleaning Use consistent sub foo { my (args...) = @_; Signed-off-by: Joe Perches Cc: Ben Hutchings Cc: Greg KH Cc: Pavel Machek Cc: Wolfram Sang Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/get_maintainer.pl | 198 ++++++++++++++++++++++++---------------------- 1 file changed, 104 insertions(+), 94 deletions(-) (limited to 'scripts') diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index 4e11c271e613..fe91a984247b 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl @@ -182,7 +182,7 @@ if ($email_remove_duplicates) { next if ($line =~ m/^\s*$/); my ($name, $address) = parse_email($line); - $line = format_email($name, $address); + $line = format_email($name, $address, $email_usename); next if ($line =~ m/^\s*$/); @@ -214,12 +214,10 @@ foreach my $file (@ARGV) { push(@files, $file); if (-f $file && $keywords) { open(FILE, "<$file") or die "$P: Can't open ${file}\n"; - while () { - my $patch_line = $_; - foreach my $line (keys %keyword_hash) { - if ($patch_line =~ m/^.*$keyword_hash{$line}/x) { - push(@keyword_tvi, $line); - } + my $text = do { local($/) ; }; + foreach my $line (keys %keyword_hash) { + if ($text =~ m/$keyword_hash{$line}/x) { + push(@keyword_tvi, $line); } } close(FILE); @@ -311,7 +309,7 @@ foreach my $file (@files) { } if ($email && $email_git) { - recent_git_signoffs($file); + git_file_signoffs($file); } if ($email && $email_git_blame) { @@ -331,7 +329,7 @@ if ($email) { if ($chief =~ m/^(.*):(.*)/) { my $email_address; - $email_address = format_email($1, $2); + $email_address = format_email($1, $2, $email_usename); if ($email_git_penguin_chiefs) { push(@email_to, [$email_address, 'chief penguin']); } else { @@ -509,7 +507,7 @@ sub parse_email { } sub format_email { - my ($name, $address) = @_; + my ($name, $address, $usename) = @_; my $formatted_email; @@ -522,11 +520,11 @@ sub format_email { $name = "\"$name\""; } - if ($email_usename) { + if ($usename) { if ("$name" eq "") { $formatted_email = "$address"; } else { - $formatted_email = "$name <${address}>"; + $formatted_email = "$name <$address>"; } } else { $formatted_email = $address; @@ -671,7 +669,7 @@ sub add_categories { if ($tv =~ m/^(\C):\s*(.*)/) { if ($1 eq "P") { $name = $2; - $pvalue = format_email($name, $address); + $pvalue = format_email($name, $address, $email_usename); } } } @@ -714,9 +712,9 @@ sub push_email_address { } if (!$email_remove_duplicates) { - push(@email_to, [format_email($name, $address), $role]); + push(@email_to, [format_email($name, $address, $email_usename), $role]); } elsif (!email_inuse($name, $address)) { - push(@email_to, [format_email($name, $address), $role]); + push(@email_to, [format_email($name, $address, $email_usename), $role]); $email_hash_name{$name}++; $email_hash_address{$address}++; } @@ -747,7 +745,7 @@ sub add_role { my ($line, $role) = @_; my ($name, $address) = parse_email($line); - my $email = format_email($name, $address); + my $email = format_email($name, $address, $email_usename); foreach my $entry (@email_to) { if ($email_remove_duplicates) { @@ -784,7 +782,7 @@ sub which { } sub mailmap { - my @lines = @_; + my (@lines) = @_; my %hash; foreach my $line (@lines) { @@ -793,14 +791,14 @@ sub mailmap { $hash{$name} = $address; } elsif ($address ne $hash{$name}) { $address = $hash{$name}; - $line = format_email($name, $address); + $line = format_email($name, $address, $email_usename); } if (exists($mailmap{$name})) { my $obj = $mailmap{$name}; foreach my $map_address (@$obj) { if (($map_address eq $address) && ($map_address ne $hash{$name})) { - $line = format_email($name, $hash{$name}); + $line = format_email($name, $hash{$name}, $email_usename); } } } @@ -809,33 +807,44 @@ sub mailmap { return @lines; } -sub recent_git_signoffs { - my ($file) = @_; - - my $sign_offs = ""; - my $cmd = ""; - my $output = ""; - my $count = 0; - my @lines = (); - my %hash; - my $total_sign_offs; - +my $printed_nogit = 0; +my $printed_nogitdir = 0; +sub has_git { if (which("git") eq "") { - warn("$P: git not found. Add --nogit to options?\n"); - return; + if (!$printed_nogit) { + warn("$P: git not found. Add --nogit to options?\n"); + $printed_nogit = 1; + } + return 0; } if (!(-d ".git")) { - warn("$P: .git directory not found. Use a git repository for better results.\n"); - warn("$P: perhaps 'git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git'\n"); - return; + if (!$printed_nogitdir) { + warn(".git directory not found. " + . "Using a git repository produces better results.\n"); + warn("Try Linus Torvalds' latest git repository using:\n"); + warn("git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n"); + $printed_nogitdir = 1; + } + return 0; } - $cmd = "git log --since=${email_git_since} -- ${file}"; + return 1; +} + +sub git_find_signers { + my ($cmd) = @_; + + my $output; + my @lines = (); + my $commits; + + return (0, @lines) if (!has_git()); $output = `${cmd}`; $output =~ s/^\s*//gm; @lines = split("\n", $output); + $commits = grep(/^commit [0-9a-f]{40,40}/, @lines); # of commits @lines = grep(/^[-_ a-z]+by:.*\@.*$/i, @lines); if (!$email_git_penguin_chiefs) { @@ -844,10 +853,28 @@ sub recent_git_signoffs { # cut -f2- -d":" s/.*:\s*(.+)\s*/$1/ for (@lines); - $total_sign_offs = @lines; +## Reformat email addresses (with names) to avoid badly written signatures + foreach my $line (@lines) { my ($name, $address) = parse_email($line); - $line = format_email($name, $address); + $line = format_email($name, $address, 1); + } + + return ($commits, @lines); +} + +sub git_assign_signers { + my ($role, $divisor, @lines) = @_; + + my %hash; + my $count = 0; + + return if (!has_git()); + return if (@lines <= 0); + + if ($divisor <= 0) { + warn("Bad divisor in git_assign_signers: $divisor\n"); + $divisor = 1; } if ($email_remove_duplicates) { @@ -862,27 +889,43 @@ sub recent_git_signoffs { # sort -rn foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) { my $sign_offs = $hash{$line}; - my $role; + my $percent = $sign_offs * 100 / $divisor; + $percent = 100 if ($percent > 100); $count++; last if ($sign_offs < $email_git_min_signatures || $count > $email_git_max_maintainers || - $sign_offs * 100 / $total_sign_offs < $email_git_min_percent); + $percent < $email_git_min_percent); push_email_address($line, ''); - $role = "git-signer"; if ($output_rolestats) { - my $percent = sprintf("%.0f", $sign_offs * 100 / $total_sign_offs); - $role = "$role:$sign_offs/$total_sign_offs=$percent%"; + my $fmt_percent = sprintf("%.0f", $percent); + add_role($line, "$role:$sign_offs/$divisor=$fmt_percent%"); + } else { + add_role($line, $role); } - add_role($line, $role); } } +sub git_file_signoffs { + my ($file) = @_; + + my @signers = (); + my $total_signers; + + return if (!has_git()); + + ($total_signers, @signers) = + git_find_signers("git log --since=$email_git_since -- $file"); + git_assign_signers("git_signer", $total_signers, @signers); +} + sub save_commits { my ($cmd, @commits) = @_; my $output; my @lines = (); + return (@lines) if (!has_git()); + $output = `${cmd}`; @lines = split("\n", $output); @@ -897,13 +940,10 @@ sub save_commits { sub git_assign_blame { my ($file) = @_; - my @lines = (); - my @commits = (); my $cmd; - my $output; - my %hash; - my $total_sign_offs; - my $count; + my @commits = (); + my @signers = (); + my $total_commits; if (@range) { foreach my $file_range_diff (@range) { @@ -922,57 +962,27 @@ sub git_assign_blame { } } - $total_sign_offs = 0; @commits = uniq(@commits); - foreach my $commit (@commits) { - $cmd = "git log -1 ${commit}"; - - $output = `${cmd}`; - $output =~ s/^\s*//gm; - @lines = split("\n", $output); - - @lines = grep(/^[-_ a-z]+by:.*\@.*$/i, @lines); - if (!$email_git_penguin_chiefs) { - @lines = grep(!/${penguin_chiefs}/i, @lines); - } - - # cut -f2- -d":" - s/.*:\s*(.+)\s*/$1/ for (@lines); - - $total_sign_offs += @lines; + $total_commits = @commits; - if ($email_remove_duplicates) { - @lines = mailmap(@lines); - } + foreach my $commit (@commits) { + my $commit_count; + my @commit_signers = (); - $hash{$_}++ for @lines; + ($commit_count, @commit_signers) = + git_find_signers("git log -1 $commit"); + @signers = (@signers, @commit_signers); } - $count = 0; - foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) { - my $sign_offs = $hash{$line}; - my $role; - - $count++; - last if ($sign_offs < $email_git_min_signatures || - $count > $email_git_max_maintainers || - $sign_offs * 100 / $total_sign_offs < $email_git_min_percent); - push_email_address($line, ''); - if ($from_filename) { - $role = "commits"; - } else { - $role = "modified commits"; - } - if ($output_rolestats) { - my $percent = sprintf("%.0f", $sign_offs * 100 / $total_sign_offs); - $role = "$role:$sign_offs/$total_sign_offs=$percent%"; - } - add_role($line, $role); + if ($from_filename) { + git_assign_signers("commits", $total_commits, @signers); + } else { + git_assign_signers("modified commits", $total_commits, @signers); } } sub uniq { - my @parms = @_; + my (@parms) = @_; my %saw; @parms = grep(!$saw{$_}++, @parms); @@ -980,7 +990,7 @@ sub uniq { } sub sort_and_uniq { - my @parms = @_; + my (@parms) = @_; my %saw; @parms = sort @parms; @@ -1008,7 +1018,7 @@ sub merge_email { } sub output { - my @parms = @_; + my (@parms) = @_; if ($output_multiline) { foreach my $line (@parms) { -- cgit v1.2.3 From 60db31ac11e2fa35b1c343e7182fb59452c4e52e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 14 Dec 2009 18:00:50 -0800 Subject: scripts/get_maintainer.pl: support multiple VCSs - add mercurial Restructure a bit for multiple version control systems support. Use a hash for each supported VCS that contains the commands and patterns used to find commits, logs, and signers. --git command line options are still used for hg except for --git-since. Use --hg-since instead. The number of commits can differ for git and hg, so --rolestats might be different. Style changes: Use common push style push(@foo...), simplify a return Bumped version to 0.23. Signed-off-by: Joe Perches Cc: Marti Raudsepp Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/get_maintainer.pl | 261 +++++++++++++++++++++++++++++----------------- 1 file changed, 168 insertions(+), 93 deletions(-) (limited to 'scripts') diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index fe91a984247b..445e8845f0a4 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl @@ -13,7 +13,7 @@ use strict; my $P = $0; -my $V = '0.22'; +my $V = '0.23'; use Getopt::Long qw(:config no_auto_abbrev); @@ -23,13 +23,14 @@ my $email_usename = 1; my $email_maintainer = 1; my $email_list = 1; my $email_subscriber_list = 0; -my $email_git = 1; my $email_git_penguin_chiefs = 0; +my $email_git = 1; +my $email_git_blame = 0; my $email_git_min_signatures = 1; my $email_git_max_maintainers = 5; my $email_git_min_percent = 5; my $email_git_since = "1-year-ago"; -my $email_git_blame = 0; +my $email_hg_since = "-365"; my $email_remove_duplicates = 1; my $output_multiline = 1; my $output_separator = ", "; @@ -66,15 +67,44 @@ my $penguin_chiefs = "\(" . join("|",@penguin_chief_names) . "\)"; my $rfc822_lwsp = "(?:(?:\\r\\n)?[ \\t])"; my $rfc822_char = '[\\000-\\377]'; +# VCS command support: class-like functions and strings + +my %VCS_cmds; + +my %VCS_cmds_git = ( + "execute_cmd" => \&git_execute_cmd, + "available" => '(which("git") ne "") && (-d ".git")', + "find_signers_cmd" => "git log --since=\$email_git_since -- \$file", + "find_commit_signers_cmd" => "git log -1 \$commit", + "blame_range_cmd" => "git blame -l -L \$diff_start,+\$diff_length \$file", + "blame_file_cmd" => "git blame -l \$file", + "commit_pattern" => "^commit [0-9a-f]{40,40}", + "blame_commit_pattern" => "^([0-9a-f]+) " +); + +my %VCS_cmds_hg = ( + "execute_cmd" => \&hg_execute_cmd, + "available" => '(which("hg") ne "") && (-d ".hg")', + "find_signers_cmd" => + "hg log --date=\$email_hg_since" . + " --template='commit {node}\\n{desc}\\n' -- \$file", + "find_commit_signers_cmd" => "hg log --template='{desc}\\n' -r \$commit", + "blame_range_cmd" => "", # not supported + "blame_file_cmd" => "hg blame -c \$file", + "commit_pattern" => "^commit [0-9a-f]{40,40}", + "blame_commit_pattern" => "^([0-9a-f]+):" +); + if (!GetOptions( 'email!' => \$email, 'git!' => \$email_git, + 'git-blame!' => \$email_git_blame, 'git-chief-penguins!' => \$email_git_penguin_chiefs, 'git-min-signatures=i' => \$email_git_min_signatures, 'git-max-maintainers=i' => \$email_git_max_maintainers, 'git-min-percent=i' => \$email_git_min_percent, 'git-since=s' => \$email_git_since, - 'git-blame!' => \$email_git_blame, + 'hg-since=s' => \$email_hg_since, 'remove-duplicates!' => \$email_remove_duplicates, 'm!' => \$email_maintainer, 'n!' => \$email_usename, @@ -309,11 +339,11 @@ foreach my $file (@files) { } if ($email && $email_git) { - git_file_signoffs($file); + vcs_file_signoffs($file); } if ($email && $email_git_blame) { - git_assign_blame($file); + vcs_file_blame($file); } } @@ -403,8 +433,9 @@ MAINTAINER field selection options: --git-min-signatures => number of signatures required (default: 1) --git-max-maintainers => maximum maintainers to add (default: 5) --git-min-percent => minimum percentage of commits required (default: 5) - --git-since => git history to use (default: 1-year-ago) --git-blame => use git blame to find modified commits for patch or file + --git-since => git history to use (default: 1-year-ago) + --hg-since => hg history to use (default: -365) --m => include maintainer(s) if any --n => include name 'Full Name ' --l => include list(s) if any @@ -437,8 +468,8 @@ Notes: directory are examined as git recurses directories. Any specified X: (exclude) pattern matches are _not_ ignored. Used with "--nogit", directory is used as a pattern match, - no individual file within the directory or subdirectory - is matched. + no individual file within the directory or subdirectory + is matched. Used with "--git-blame", does not iterate all files in directory Using "--git-blame" is slow and may add old committers and authors that are no longer active maintainers to the output. @@ -449,6 +480,12 @@ Notes: not the percentage of the entire file authored. # of commits is not a good measure of amount of code authored. 1 major commit may contain a thousand lines, 5 trivial commits may modify a single line. + If git is not installed, but mercurial (hg) is installed and an .hg + repository exists, the following options apply to mercurial: + --git, + --git-min-signatures, --git-max-maintainers, --git-min-percent, and + --git-blame + Use --hg-since not --git-since to control date selection EOT } @@ -807,44 +844,37 @@ sub mailmap { return @lines; } -my $printed_nogit = 0; -my $printed_nogitdir = 0; -sub has_git { - if (which("git") eq "") { - if (!$printed_nogit) { - warn("$P: git not found. Add --nogit to options?\n"); - $printed_nogit = 1; - } - return 0; - } - if (!(-d ".git")) { - if (!$printed_nogitdir) { - warn(".git directory not found. " - . "Using a git repository produces better results.\n"); - warn("Try Linus Torvalds' latest git repository using:\n"); - warn("git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n"); - $printed_nogitdir = 1; - } - return 0; - } +sub git_execute_cmd { + my ($cmd) = @_; + my @lines = (); - return 1; + my $output = `$cmd`; + $output =~ s/^\s*//gm; + @lines = split("\n", $output); + + return @lines; } -sub git_find_signers { +sub hg_execute_cmd { my ($cmd) = @_; + my @lines = (); + + my $output = `$cmd`; + @lines = split("\n", $output); - my $output; + return @lines; +} + +sub vcs_find_signers { + my ($cmd) = @_; my @lines = (); my $commits; - return (0, @lines) if (!has_git()); + @lines = &{$VCS_cmds{"execute_cmd"}}($cmd); - $output = `${cmd}`; - $output =~ s/^\s*//gm; + my $pattern = $VCS_cmds{"commit_pattern"}; - @lines = split("\n", $output); - $commits = grep(/^commit [0-9a-f]{40,40}/, @lines); # of commits + $commits = grep(/$pattern/, @lines); # of commits @lines = grep(/^[-_ a-z]+by:.*\@.*$/i, @lines); if (!$email_git_penguin_chiefs) { @@ -863,17 +893,93 @@ sub git_find_signers { return ($commits, @lines); } -sub git_assign_signers { +sub vcs_save_commits { + my ($cmd) = @_; + my @lines = (); + my @commits = (); + + @lines = &{$VCS_cmds{"execute_cmd"}}($cmd); + + foreach my $line (@lines) { + if ($line =~ m/$VCS_cmds{"blame_commit_pattern"}/) { + push(@commits, $1); + } + } + + return @commits; +} + +sub vcs_blame { + my ($file) = @_; + my $cmd; + my @commits = (); + + return @commits if (!(-f $file)); + + if (@range && $VCS_cmds{"blame_range_cmd"} eq "") { + my @all_commits = (); + + $cmd = $VCS_cmds{"blame_file_cmd"}; + $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd + @all_commits = vcs_save_commits($cmd); + + foreach my $file_range_diff (@range) { + next if (!($file_range_diff =~ m/(.+):(.+):(.+)/)); + my $diff_file = $1; + my $diff_start = $2; + my $diff_length = $3; + next if ("$file" ne "$diff_file"); + for (my $i = $diff_start; $i < $diff_start + $diff_length; $i++) { + push(@commits, $all_commits[$i]); + } + } + } elsif (@range) { + foreach my $file_range_diff (@range) { + next if (!($file_range_diff =~ m/(.+):(.+):(.+)/)); + my $diff_file = $1; + my $diff_start = $2; + my $diff_length = $3; + next if ("$file" ne "$diff_file"); + $cmd = $VCS_cmds{"blame_range_cmd"}; + $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd + push(@commits, vcs_save_commits($cmd)); + } + } else { + $cmd = $VCS_cmds{"blame_file_cmd"}; + $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd + @commits = vcs_save_commits($cmd); + } + + return @commits; +} + +my $printed_novcs = 0; +sub vcs_exists { + %VCS_cmds = %VCS_cmds_git; + return 1 if eval $VCS_cmds{"available"}; + %VCS_cmds = %VCS_cmds_hg; + return 1 if eval $VCS_cmds{"available"}; + %VCS_cmds = (); + if (!$printed_novcs) { + warn("$P: No supported VCS found. Add --nogit to options?\n"); + warn("Using a git repository produces better results.\n"); + warn("Try Linus Torvalds' latest git repository using:\n"); + warn("git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n"); + $printed_novcs = 1; + } + return 0; +} + +sub vcs_assign { my ($role, $divisor, @lines) = @_; my %hash; my $count = 0; - return if (!has_git()); return if (@lines <= 0); if ($divisor <= 0) { - warn("Bad divisor in git_assign_signers: $divisor\n"); + warn("Bad divisor in " . (caller(0))[3] . ": $divisor\n"); $divisor = 1; } @@ -906,62 +1012,31 @@ sub git_assign_signers { } } -sub git_file_signoffs { +sub vcs_file_signoffs { my ($file) = @_; my @signers = (); - my $total_signers; - - return if (!has_git()); - - ($total_signers, @signers) = - git_find_signers("git log --since=$email_git_since -- $file"); - git_assign_signers("git_signer", $total_signers, @signers); -} - -sub save_commits { - my ($cmd, @commits) = @_; - my $output; - my @lines = (); + my $commits; - return (@lines) if (!has_git()); + return if (!vcs_exists()); - $output = `${cmd}`; + my $cmd = $VCS_cmds{"find_signers_cmd"}; + $cmd =~ s/(\$\w+)/$1/eeg; # interpolate $cmd - @lines = split("\n", $output); - foreach my $line (@lines) { - if ($line =~ m/^(\w+) /) { - push (@commits, $1); - } - } - return @commits; + ($commits, @signers) = vcs_find_signers($cmd); + vcs_assign("commit_signer", $commits, @signers); } -sub git_assign_blame { +sub vcs_file_blame { my ($file) = @_; - my $cmd; - my @commits = (); my @signers = (); + my @commits = (); my $total_commits; - if (@range) { - foreach my $file_range_diff (@range) { - next if (!($file_range_diff =~ m/(.+):(.+):(.+)/)); - my $diff_file = $1; - my $diff_start = $2; - my $diff_length = $3; - next if (!("$file" eq "$diff_file")); - $cmd = "git blame -l -L $diff_start,+$diff_length $file"; - @commits = save_commits($cmd, @commits); - } - } else { - if (-f $file) { - $cmd = "git blame -l $file"; - @commits = save_commits($cmd, @commits); - } - } + return if (!vcs_exists()); + @commits = vcs_blame($file); @commits = uniq(@commits); $total_commits = @commits; @@ -969,15 +1044,17 @@ sub git_assign_blame { my $commit_count; my @commit_signers = (); - ($commit_count, @commit_signers) = - git_find_signers("git log -1 $commit"); - @signers = (@signers, @commit_signers); + my $cmd = $VCS_cmds{"find_commit_signers_cmd"}; + $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd + + ($commit_count, @commit_signers) = vcs_find_signers($cmd); + push(@signers, @commit_signers); } if ($from_filename) { - git_assign_signers("commits", $total_commits, @signers); + vcs_assign("commits", $total_commits, @signers); } else { - git_assign_signers("modified commits", $total_commits, @signers); + vcs_assign("modified commits", $total_commits, @signers); } } @@ -1006,9 +1083,9 @@ sub merge_email { my ($address, $role) = @$_; if (!$saw{$address}) { if ($output_roles) { - push @lines, "$address ($role)"; + push(@lines, "$address ($role)"); } else { - push @lines, $address; + push(@lines, $address); } $saw{$address} = 1; } @@ -1115,11 +1192,9 @@ sub rfc822_validlist ($) { if ($s =~ m/^(?:$rfc822re)?(?:,(?:$rfc822re)?)*$/so && $s =~ m/^$rfc822_char*$/) { while ($s =~ m/(?:^|,$rfc822_lwsp*)($rfc822re)/gos) { - push @r, $1; + push(@r, $1); } return wantarray ? (scalar(@r), @r) : 1; } - else { - return wantarray ? () : 0; - } + return wantarray ? () : 0; } -- cgit v1.2.3 From e6299d2677e600f6a0bf93bbb89f20d3de5252de Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Fri, 20 Nov 2009 20:34:31 +0800 Subject: MIPS: Tracing: Add an endian argument to scripts/recordmcount.pl MIPS and some other architectures need this argument to handle big/little endian respectively. Signed-off-by: Wu Zhangjin Cc: Nicholas Mc Guire Cc: zhangfx@lemote.com Cc: Wu Zhangjin Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Frederic Weisbecker Cc: linux-kernel@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/674/ Acked-by: Steven Rostedt Signed-off-by: Ralf Baechle --- scripts/Makefile.build | 1 + scripts/recordmcount.pl | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 341b58902ffc..0b94d2fa3a88 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -207,6 +207,7 @@ endif ifdef CONFIG_FTRACE_MCOUNT_RECORD cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \ + "$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \ "$(if $(CONFIG_64BIT),64,32)" \ "$(OBJDUMP)" "$(OBJCOPY)" "$(CC)" "$(LD)" "$(NM)" "$(RM)" "$(MV)" \ "$(if $(part-of-module),1,0)" "$(@)"; diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl index 9cf0a6fad6ba..ab368e8a007d 100755 --- a/scripts/recordmcount.pl +++ b/scripts/recordmcount.pl @@ -113,13 +113,13 @@ $P =~ s@.*/@@g; my $V = '0.1'; -if ($#ARGV != 10) { - print "usage: $P arch bits objdump objcopy cc ld nm rm mv is_module inputfile\n"; +if ($#ARGV != 11) { + print "usage: $P arch endian bits objdump objcopy cc ld nm rm mv is_module inputfile\n"; print "version: $V\n"; exit(1); } -my ($arch, $bits, $objdump, $objcopy, $cc, +my ($arch, $endian, $bits, $objdump, $objcopy, $cc, $ld, $nm, $rm, $mv, $is_module, $inputfile) = @ARGV; # This file refers to mcount and shouldn't be ftraced, so lets' ignore it -- cgit v1.2.3 From 538f19526e40ce7a5a296fad6a3121409c890adc Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Fri, 20 Nov 2009 20:34:32 +0800 Subject: MIPS: Tracing: Add dynamic function tracer support With dynamic function tracer, by default, _mcount is defined as an "empty" function, it returns directly without any more action . When enabling it in user-space, it will jump to a real tracing function(ftrace_caller), and do the real job for us. Differ from the static function tracer, dynamic function tracer provides two functions ftrace_make_call()/ftrace_make_nop() to enable/disable the tracing of some indicated kernel functions(set_ftrace_filter). In the -v4 version, the implementation of this support is basically the same as X86 version does: _mcount is implemented as an empty function and ftrace_caller is implemented as a real tracing function respectively. But in this version, to support module tracing with the help of -mlong-calls in arch/mips/Makefile: MODFLAGS += -mlong-calls. The stuff becomes a little more complex. We need to cope with two different type of calling to _mcount. For the kernel part, the calling to _mcount(result of "objdump -hdr vmlinux"). is like this: 108: 03e0082d move at,ra 10c: 0c000000 jal 0 10c: R_MIPS_26 _mcount 10c: R_MIPS_NONE *ABS* 10c: R_MIPS_NONE *ABS* 110: 00020021 nop For the module with -mlong-calls, it looks like this: c: 3c030000 lui v1,0x0 c: R_MIPS_HI16 _mcount c: R_MIPS_NONE *ABS* c: R_MIPS_NONE *ABS* 10: 64630000 daddiu v1,v1,0 10: R_MIPS_LO16 _mcount 10: R_MIPS_NONE *ABS* 10: R_MIPS_NONE *ABS* 14: 03e0082d move at,ra 18: 0060f809 jalr v1 In the kernel version, there is only one "_mcount" string for every kernel function, so, we just need to match this one in mcount_regex of scripts/recordmcount.pl, but in the module version, we need to choose one of the two to match. Herein, I choose the first one with "R_MIPS_HI16 _mcount". and In the kernel verion, without module tracing support, we just need to replace "jal _mcount" by "jal ftrace_caller" to do real tracing, and filter the tracing of some kernel functions via replacing it by a nop instruction. but as we have described before, the instruction "jal ftrace_caller" only left 32bit length for the address of ftrace_caller, it will fail when calling from the module space. so, herein, we must replace something else. the basic idea is loading the address of ftrace_caller to v1 via changing these two instructions: lui v1,0x0 addiu v1,v1,0 If we want to enable the tracing, we need to replace the above instructions to: lui v1, HI_16BIT_ftrace_caller addiu v1, v1, LOW_16BIT_ftrace_caller If we want to stop the tracing of the indicated kernel functions, we just need to replace the "jalr v1" to a nop instruction. but we need to replace two instructions and encode the above two instructions oursevles. Is there a simpler solution? Yes! Here it is, in this version, we put _mcount and ftrace_caller together, which means the address of _mcount and ftrace_caller is the same: _mcount: ftrace_caller: j ftrace_stub nop ...(do real tracing here)... ftrace_stub: jr ra move ra, at By default, the kernel functions call _mcount, and then jump to ftrace_stub and return. and when we want to do real tracing, we just need to remove that "j ftrace_stub", and it will run through the two "nop" instructions and then do the real tracing job. what about filtering job? we just need to do this: lui v1, hi_16bit_of_mcount <--> b 1f (0x10000004) addiu v1, v1, low_16bit_of_mcount move at, ra jalr v1 nop 1f: (rec->ip + 12) In linux-mips64, there will be some local symbols, whose name are prefixed by $L, which need to be filtered. thanks goes to Steven for writing the mips64-specific function_regex. In a conclusion, with RISC, things becomes easier with such a "stupid" trick, RISC is something like K.I.S.S, and also, there are lots of "simple" tricks in the whole ftrace support, thanks goes to Steven and the other folks for providing such a wonderful tracing framework! Signed-off-by: Wu Zhangjin Cc: Nicholas Mc Guire Cc: zhangfx@lemote.com Cc: Wu Zhangjin Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Frederic Weisbecker Cc: linux-kernel@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/675/ Acked-by: Steven Rostedt Signed-off-by: Ralf Baechle --- scripts/recordmcount.pl | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'scripts') diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl index ab368e8a007d..92f09fe9639e 100755 --- a/scripts/recordmcount.pl +++ b/scripts/recordmcount.pl @@ -295,6 +295,58 @@ if ($arch eq "x86_64") { $ld .= " -m elf64_sparc"; $cc .= " -m64"; $objcopy .= " -O elf64-sparc"; +} elsif ($arch eq "mips") { + # To enable module support, we need to enable the -mlong-calls option + # of gcc for module, after using this option, we can not get the real + # offset of the calling to _mcount, but the offset of the lui + # instruction or the addiu one. herein, we record the address of the + # first one, and then we can replace this instruction by a branch + # instruction to jump over the profiling function to filter the + # indicated functions, or swith back to the lui instruction to trace + # them, which means dynamic tracing. + # + # c: 3c030000 lui v1,0x0 + # c: R_MIPS_HI16 _mcount + # c: R_MIPS_NONE *ABS* + # c: R_MIPS_NONE *ABS* + # 10: 64630000 daddiu v1,v1,0 + # 10: R_MIPS_LO16 _mcount + # 10: R_MIPS_NONE *ABS* + # 10: R_MIPS_NONE *ABS* + # 14: 03e0082d move at,ra + # 18: 0060f809 jalr v1 + # + # for the kernel: + # + # 10: 03e0082d move at,ra + # 14: 0c000000 jal 0 + # 14: R_MIPS_26 _mcount + # 14: R_MIPS_NONE *ABS* + # 14: R_MIPS_NONE *ABS* + # 18: 00020021 nop + if ($is_module eq "0") { + $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$"; + } else { + $mcount_regex = "^\\s*([0-9a-fA-F]+): R_MIPS_HI16\\s+_mcount\$"; + } + $objdump .= " -Melf-trad".$endian."mips "; + + if ($endian eq "big") { + $endian = " -EB "; + $ld .= " -melf".$bits."btsmip"; + } else { + $endian = " -EL "; + $ld .= " -melf".$bits."ltsmip"; + } + + $cc .= " -mno-abicalls -fno-pic -mabi=" . $bits . $endian; + $ld .= $endian; + + if ($bits == 64) { + $function_regex = + "^([0-9a-fA-F]+)\\s+<(.|[^\$]L.*?|\$[^L].*?|[^\$][^L].*?)>:"; + $type = ".dword"; + } } elsif ($arch eq "microblaze") { # Microblaze calls '_mcount' instead of plain 'mcount'. $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$"; -- cgit v1.2.3