diff --git a/Makefile b/Makefile
index 70092c7cb3418f552d685b555464635837b4c83a..88062fe83bda6de971e1117a3e10f595badde2f9 100644
--- a/Makefile
+++ b/Makefile
@@ -254,6 +254,7 @@ DISTRIB_FILES:=\
       share/analysis-scripts/cmd-dep.sh                                 \
       share/analysis-scripts/concat-csv.sh                              \
       $(wildcard share/analysis-scripts/examples/*)                     \
+      share/analysis-scripts/find_fun.py                                \
       share/analysis-scripts/flamegraph.pl                              \
       share/analysis-scripts/frama-c.mk                                 \
       share/analysis-scripts/list_files.py                              \
@@ -1804,6 +1805,7 @@ install:: install-lib
 	$(MKDIR) $(FRAMAC_DATADIR)/analysis-scripts
 	$(CP) share/analysis-scripts/cmd-dep.sh \
 	  share/analysis-scripts/concat-csv.sh \
+	  share/analysis-scripts/find_fun.py \
 	  share/analysis-scripts/flamegraph.pl \
 	  share/analysis-scripts/frama-c.mk \
 	  share/analysis-scripts/parse-coverage.sh \
diff --git a/bin/frama-c-script b/bin/frama-c-script
index 707e9fd932f3208791ecbc8d851f1d5ce1804ce9..6a2dc40105337ff48d3fa7c600c536370931eb19 100755
--- a/bin/frama-c-script
+++ b/bin/frama-c-script
@@ -49,6 +49,11 @@ if [ $# -lt 1 ]; then
    echo "      Generates flamegraph.svg and flamegraph.html in [dir]"
    echo "      (or in the FRAMAC_SESSION directory by default)."
    echo "      Also opens it in a browser, unless variable NOGUI is set."
+   echo ""
+   echo "  - find-fun <function-name> [dirs]"
+   echo "      Lists files in [dirs] declaring or defining <function-name>"
+   echo "      (defaults to PWD + /usr/include)."
+   echo "      Heuristics-based: neither correct nor complete."
    exit
 fi
 
@@ -188,6 +193,10 @@ case "$command" in
         shift;
         ${FRAMAC_SHARE}/analysis-scripts/list_files.py "$@";
         ;;
+    "find-fun")
+        shift;
+        ${FRAMAC_SHARE}/analysis-scripts/find_fun.py "$@";
+        ;;
     "flamegraph")
         shift;
         flamegraph "$@";
diff --git a/headers/header_spec.txt b/headers/header_spec.txt
index 509d0627ae8b5724d772b34288850461b48a0cf7..53fa80a1a72a5c701eb535f708636072c3040b56 100644
--- a/headers/header_spec.txt
+++ b/headers/header_spec.txt
@@ -122,6 +122,7 @@ share/analysis-scripts/examples/example.mk: .ignore
 share/analysis-scripts/examples/example-multi.mk: .ignore
 share/analysis-scripts/examples/example-slevel.mk: .ignore
 share/analysis-scripts/examples/Makefile: .ignore
+share/analysis-scripts/find_fun.py: .ignore
 share/analysis-scripts/flamegraph.pl: CDDL
 share/analysis-scripts/list_files.py: .ignore
 share/analysis-scripts/parse-coverage.sh: .ignore
diff --git a/share/analysis-scripts/find_fun.py b/share/analysis-scripts/find_fun.py
new file mode 100755
index 0000000000000000000000000000000000000000..3e89dccbe3ba30d3bf5be29075677521399d3da9
--- /dev/null
+++ b/share/analysis-scripts/find_fun.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python3
+#-*- coding: utf-8 -*-
+##########################################################################
+#                                                                        #
+#  This file is part of Frama-C.                                         #
+#                                                                        #
+#  Copyright (C) 2007-2018                                               #
+#    CEA (Commissariat à l'énergie atomique et aux énergies              #
+#         alternatives)                                                  #
+#                                                                        #
+#  you can redistribute it and/or modify it under the terms of the GNU   #
+#  Lesser General Public License as published by the Free Software       #
+#  Foundation, version 2.1.                                              #
+#                                                                        #
+#  It is distributed in the hope that it will be useful,                 #
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of        #
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
+#  GNU Lesser General Public License for more details.                   #
+#                                                                        #
+#  See the GNU Lesser General Public License version 2.1                 #
+#  for more details (enclosed in the file licenses/LGPLv2.1).            #
+#                                                                        #
+##########################################################################
+
+# This script finds files containing likely declarations and definitions
+# for a given function name, via heuristic syntactic matching.
+
+import sys
+import os
+import re
+import glob
+
+debug = False
+
+arg = ""
+if len(sys.argv) < 2:
+   print("usage: %s fname [dir1 dir2 ...]" % sys.argv[0])
+   print("       looks for likely declarations/definitions of function fname")
+   print("       in files with extensions '.c', '.h' and '.i';")
+   print("       if dir1, dir2, etc, are specified, looks inside them,")
+   print("       otherwise looks inside PWD and /usr/include.")
+   print("       Subdirectories are always considered recursively.")
+   sys.exit(1)
+else:
+   fname = sys.argv[1]
+
+dirs = set()
+if len(sys.argv) < 3:
+    pwd = os.getcwd()
+    dirs = [pwd, "/usr/include"]
+else:
+    dirs = set(sys.argv[2:])
+
+if debug:
+    print("Looking for files in dirs (and their subdirs): %s" % dirs)
+
+files = []
+for d in dirs:
+    files += glob.glob(d + "/**/*.[ich]", recursive=True)
+
+print("Looking for '%s' inside %d file(s)..." % (fname, len(files)))
+#print("\n".join(files))
+
+# To minimize the amount of false positives, we try to match the following:
+# - the line must begin with a C identifier (declarations and definitions in C
+#   rarely start with spaces in the line), or with the function name itself
+#   (supposing the return type is in the previous line)
+# - any number of identifiers are allowed (to allow for 'struct', 'volatile',
+#   'extern', etc)
+# - asterisks are allowed both before and after identifiers, except for the
+#   first one (to allow for 'char *', 'struct **ptr', etc)
+# - identifiers are allowed after the parentheses, to allow for some macros/
+#   modifiers
+
+possible_declarators = []
+possible_definers = []
+c_identifier = "[a-zA-Z_][a-zA-Z0-9_]*"
+c_id_maybe_pointer = c_identifier + "\**"
+type_prefix = c_id_maybe_pointer + "(?:\s+\**" + c_id_maybe_pointer + ")*\s+\**"
+parentheses_suffix = "\s*\([^)]*\)"
+re_fun = re.compile("^(?:" + type_prefix + ")?" + fname + parentheses_suffix + "\s*(?:" + c_identifier + ")?\s*(;|{)", flags=re.MULTILINE)
+for f in files:
+    with open(f, encoding="ascii", errors='ignore') as content_file:
+        content = content_file.read()
+        has_decl_or_def = re_fun.search(content)
+        if has_decl_or_def is not None:
+            is_decl = has_decl_or_def.group(1) == ";"
+            if is_decl:
+                possible_declarators.append(f)
+            else:
+                possible_definers.append(f)
+
+if possible_declarators == [] and possible_definers == []:
+    print("No declaration/definition found for function '%s'" % fname)
+else:
+    if possible_declarators != []:
+        print("Possible declarations for function '%s' in the following file(s):" % fname)
+        print("  " + "\n  ".join(possible_declarators))
+    if possible_definers != []:
+        print("Possible definitions for function '%s' in the following file(s):" % fname)
+        print("  " + "\n  ".join(possible_definers))
diff --git a/tests/fc_script/for-find-fun.c b/tests/fc_script/for-find-fun.c
new file mode 100644
index 0000000000000000000000000000000000000000..c8c3a67560fb5a5f321117bedacb256b8884decb
--- /dev/null
+++ b/tests/fc_script/for-find-fun.c
@@ -0,0 +1,17 @@
+/* run.config
+   DONTRUN: test run by main.c
+*/
+
+int
+main2
+(char *c, int i);
+
+struct s {
+  char c;
+};
+
+struct s **main3(
+                 struct s *p1, struct s s2
+                 ) {
+
+}
diff --git a/tests/fc_script/main.c b/tests/fc_script/main.c
index 34b9b7c79ac1e3cbca1c44cd4696cbee7d47618a..1acc886dfd3ef3306dfcdcdb875e6bd34df55a4f 100644
--- a/tests/fc_script/main.c
+++ b/tests/fc_script/main.c
@@ -3,6 +3,8 @@
    EXECNOW: LOG GNUmakefile LOG make_template.res LOG make_template.err bin/frama-c-script make-template @PTEST_DIR@/result < @PTEST_DIR@/make_template.input > @PTEST_DIR@/result/make_template.res 2> @PTEST_DIR@/result/make_template.err
    EXECNOW: LOG list_files.res LOG list_files.err bin/frama-c-script list-files @PTEST_DIR@/list_files.json > @PTEST_DIR@/result/list_files.res 2> @PTEST_DIR@/result/list_files.err
    EXECNOW: LOG flamegraph.html LOG flamegraph.res LOG flamegraph.err NOGUI=1 bin/frama-c-script flamegraph @PTEST_DIR@/flamegraph.txt @PTEST_DIR@/result > @PTEST_DIR@/result/flamegraph.res 2> @PTEST_DIR@/result/flamegraph.err && rm -f @PTEST_DIR@/result/flamegraph.svg
+   EXECNOW: LOG find_fun1.res LOG find_fun1.err bin/frama-c-script find-fun main2 @PTEST_DIR@ > @PTEST_DIR@/result/find_fun1.res 2> @PTEST_DIR@/result/find_fun1.err
+   EXECNOW: LOG find_fun2.res LOG find_fun2.err bin/frama-c-script find-fun main3 @PTEST_DIR@ > @PTEST_DIR@/result/find_fun2.res 2> @PTEST_DIR@/result/find_fun2.err
  */
 
 void main() {
diff --git a/tests/fc_script/oracle/find_fun1.err b/tests/fc_script/oracle/find_fun1.err
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tests/fc_script/oracle/find_fun1.res b/tests/fc_script/oracle/find_fun1.res
new file mode 100644
index 0000000000000000000000000000000000000000..330fcaca0a0bf618080a63aeda3f1f88fffcd022
--- /dev/null
+++ b/tests/fc_script/oracle/find_fun1.res
@@ -0,0 +1,5 @@
+Looking for 'main2' inside 4 file(s)...
+Possible declarations for function 'main2' in the following file(s):
+  tests/fc_script/for-find-fun.c
+Possible definitions for function 'main2' in the following file(s):
+  tests/fc_script/main2.c
diff --git a/tests/fc_script/oracle/find_fun2.err b/tests/fc_script/oracle/find_fun2.err
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tests/fc_script/oracle/find_fun2.res b/tests/fc_script/oracle/find_fun2.res
new file mode 100644
index 0000000000000000000000000000000000000000..35e3da577fac50d5c30169a95b0bdbd0e5220264
--- /dev/null
+++ b/tests/fc_script/oracle/find_fun2.res
@@ -0,0 +1,3 @@
+Looking for 'main3' inside 4 file(s)...
+Possible definitions for function 'main3' in the following file(s):
+  tests/fc_script/for-find-fun.c