diff --git a/contrib/scripts/ast_coredumper b/contrib/scripts/ast_coredumper
index 2f685acb67..d0bad282de 100755
--- a/contrib/scripts/ast_coredumper
+++ b/contrib/scripts/ast_coredumper
@@ -1,59 +1,60 @@
-#!/usr/bin/env bash
+#!/bin/bash
+
 # Turn on extended globbing
 shopt -s extglob
 shopt -s nullglob
 # Bail on any error
 set -e
 
-prog=$(basename $0)
+prog=$(basename "$0")
 
 # NOTE: <(cmd) is a bash construct that returns a temporary file name
 # from which the command output can be read.  In this case, we're
 # extracting the block of text delimited by '#@@@FUNCSSTART@@@'
 # and '#@@@FUNCSEND@@@' from this file and 'source'ing it to
 # get some functions.
-source <(sed -n -r -e "/^#@@@FUNCSSTART@@@/,\${p;/^#@@@FUNCSEND@@@/q}" $0 | sed '1d;$d')
-
-# The "!(*.txt)" is a bash construct that excludes files ending with .txt
-# from the glob match.
-declare -a COREDUMPS=( /tmp/core!(*.txt) )
+# shellcheck disable=SC1090
+source <(sed -n "/^#@@@FUNCSSTART@@@/,/^#@@@FUNCSEND@@@/ p" "$0" | sed '1d;$d')
 
 # A line starting with ': ' is a POSIX construct that makes the shell
 # perform the operation but ignore the result.  This is an alternative to
 # having to do RUNNING=${RUNNING:=false} to set defaults.
 
-: ${ASTERISK_BIN:=$(which asterisk)}
-: ${DATEOPTS='-u +%FT%H-%M-%SZ'}
-: ${DELETE_COREDUMPS_AFTER:=false}
-: ${DELETE_RESULTS_AFTER:=false}
-: ${DRY_RUN:=false}
-: ${GDB:=$(which gdb)}
-: ${HELP:=false}
-: ${LATEST:=false}
-: ${OUTPUTDIR:=/tmp}
-: ${PROMPT:=true}
-: ${RUNNING:=false}
-: ${RENAME:=true}
-: ${TARBALL_CONFIG:=false}
-: ${TARBALL_COREDUMPS:=false}
-: ${TARBALL_RESULTS:=false}
+: "${DATEOPTS=-u +%FT%H-%M-%SZ}"
+: "${DELETE_COREDUMPS_AFTER:=false}"
+: "${DELETE_RESULTS_AFTER:=false}"
+: "${DRY_RUN:=false}"
+: "${GDB:=$(which gdb)}"
+: "${HELP:=false}"
+: "${LATEST:=false}"
+: "${OUTPUTDIR:=/tmp}"
+: "${PROMPT:=true}"
+: "${RUNNING:=false}"
+: "${RENAME:=true}"
+: "${TARBALL_CONFIG:=false}"
+: "${TARBALL_COREDUMPS:=false}"
+: "${TARBALL_RESULTS:=false}"
+: "${MODDIR:=}"
+: "${LIBDIR:=}"
+: "${ETCDIR:=}"
 
 COMMANDLINE_COREDUMPS=false
 
 # Read config files from most important to least important.
 # Variables set on the command line or environment always take precedence.
+# shellcheck disable=SC1091
 [ -f ./ast_debug_tools.conf ] && source ./ast_debug_tools.conf
+# shellcheck disable=SC1090
 [ -f ~/ast_debug_tools.conf ] && source ~/ast_debug_tools.conf
 [ -f /etc/asterisk/ast_debug_tools.conf ] && source /etc/asterisk/ast_debug_tools.conf
 
 if [ -n "${DATEFORMAT}" ] ; then
 	err <<-EOF
-	The DATEFORMAT variable in your ast_debug_tools.conf file has been
+	FYI... The DATEFORMAT variable in your ast_debug_tools.conf file has been
 	replaced with DATEOPTS which has a different format.  See the latest
 	ast_debug_tools.conf sample file for more information.
 	EOF
 fi
-	
 
 for a in "$@" ; do
 	if [[ $a == "--RUNNING" ]] ; then
@@ -61,13 +62,13 @@ for a in "$@" ; do
 		PROMPT=false
 	elif [[ $a =~ --no-([^=]+)$ ]] ; then
 		var=${BASH_REMATCH[1]//-/_}
-		eval ${var^^}="false"
+		eval "${var^^}"="false"
 	elif [[ $a =~ --([^=]+)$ ]] ; then
 		var=${BASH_REMATCH[1]//-/_}
-		eval ${var^^}="true"
+		eval "${var^^}"="true"
 	elif [[ $a =~ --([^=]+)=(.+)$ ]] ; then
 		var=${BASH_REMATCH[1]//-/_}
-		eval ${var^^}=${BASH_REMATCH[2]}
+		eval "${var^^}"="${BASH_REMATCH[2]}"
 	else
 		if ! $COMMANDLINE_COREDUMPS ; then
 			COMMANDLINE_COREDUMPS=true
@@ -82,21 +83,14 @@ if $HELP ; then
 	exit 0
 fi
 
+# shellcheck disable=SC2218
 check_gdb
 
-if [ -z "${ASTERISK_BIN}" -o ! -x "${ASTERISK_BIN}" ] ; then
-	die -2 <<-EOF
-	The asterisk binary specified (${ASTERISK_BIN})
-	was not found or is not executable.  Use the '--asterisk-bin'
-	option to specify a valid binary.
-	EOF
-fi
-
 if [ $EUID -ne 0 ] ; then
 	die -13 "You must be root to use $prog."
 fi
 
-if [ -z "${OUTPUTDIR}" -o ! -d "${OUTPUTDIR}" ] ; then
+if [ -z "${OUTPUTDIR}" ] || [ ! -d "${OUTPUTDIR}" ] ; then
 	die -20 "OUTPUTDIR ${OUTPUTDIR} doesn't exists or is not a directory"
 fi
 
@@ -110,62 +104,127 @@ if $RUNNING ; then
 	msg "Found a single asterisk instance running as process $MAIN_PID"
 
 	if $PROMPT ; then
-		read -p "WARNING:  Taking a core dump of the running asterisk instance will suspend call processing while the dump is saved.  Do you wish to continue? (y/N) " answer
+		read -r -p "WARNING:  Taking a core dump of the running asterisk instance will suspend call processing while the dump is saved.  Do you wish to continue? (y/N) " answer
 	else
 		answer=Y
 	fi
 
 	if [[ "$answer" =~ ^[Yy] ]] ; then
+		# shellcheck disable=SC2086		
 		df=$(date ${DATEOPTS})
 		cf="${OUTPUTDIR}/core-asterisk-running-$df"
-		echo "$(S_COR ${DRY_RUN} 'Simulating dumping' 'Dumping') running asterisk process to $cf"
+		echo "$(S_COR "${DRY_RUN}" 'Simulating dumping' 'Dumping') running asterisk process to $cf"
 		if ${DRY_RUN} ; then
-			echo "Would run: ${GDB} ${ASTERISK_BIN} -p $MAIN_PID -q --batch --ex gcore $cf"
+			echo "Would run: ${GDB} -p $MAIN_PID -q --batch --ex gcore $cf"
 		else
-			${GDB} ${ASTERISK_BIN} -p $MAIN_PID -q --batch --ex "gcore $cf" >/dev/null 2>&1
+			${GDB} -p "$MAIN_PID" -q --batch --ex "gcore $cf" >/dev/null 2>&1
 		fi
-		echo "$(S_COR ${DRY_RUN} 'Simulated dump' 'Dump') is complete."
-		
+		echo "$(S_COR "${DRY_RUN}" 'Simulated dump' 'Dump') is complete."
+
 		COREDUMPS=( "$cf" )
+
+		exe=$(extract_binary_name "${cf}")
+		if [ -z "${exe}" ] ; then
+			die -125 "Coredump produced has no executable!"
+		fi
+
+		module_dir=$(extract_string_symbol "${exe}" "${cf}" ast_config_AST_MODULE_DIR)
+		if [ ! -d "$module_dir" ] ; then
+			die -125 "Couldn't get module directory from coredump!"
+		fi
 	else
 		die -125 "Aborting dump of running process"
 	fi
-	
+
 	$DRY_RUN && exit 0
 else
 
+	# If no coredumps were supplied on the command line or in
+	# the ast_debug_tools.conf file, we'll use the default search.
+	if [ ${#COREDUMPS[@]} -eq 0 ] ; then
+		# The "!(*.txt)" is a bash construct that excludes files ending
+		# with .txt from the glob match.  Needs extglob set.
+		mapfile -t COREDUMPS < <(readlink -f /tmp/core!(*.txt) | sort -u)
+	fi
+
 	# At this point, all glob entries that match files should be expanded.
 	# Any entries that don't exist are probably globs that didn't match anything
 	# and need to be pruned.  Any non coredumps are also pruned.
 
-	for i in ${!COREDUMPS[@]} ; do
+	for i in "${!COREDUMPS[@]}" ; do
 		if [ ! -f "${COREDUMPS[$i]}" ] ; then
 			unset "COREDUMPS[$i]"
 			continue
 		fi
-		# Some versions of 'file' don't allow only the first n bytes of the
-		# file to be processed so we use dd to grab just the first 32 bytes.
-		mimetype=$(dd if="${COREDUMPS[$i]}" bs=32 count=1 2>/dev/null | file -bi -)
-		if [[ ! "$mimetype" =~ coredump ]] ; then
+		cf="${COREDUMPS[$i]}"
+
+		msg "Examining ${cf}"
+
+		dump_note_strings "${cf}" | grep -q -E "app_dial|pbx_config"  || {
+			err "    Doesn't appear to be an asterisk coredump"
+			unset "COREDUMPS[$i]"
+			continue
+		}
+		msg "    Does appear to be an asterisk coredump"
+
+		# Let's get the executable from gdb "info proc".
+		# We could have skipped the previous test and just checked
+		# that the executable was "asterisk" but then, of course,
+		# someone will decide that they need to change the executable
+		# name to something else for some strange reason.
+		exe=$(extract_binary_name "${cf}")
+		if [ -z "${exe}" ] ; then
+			err "    Can't extract executable.  Skipping."
 			unset "COREDUMPS[$i]"
 			continue
 		fi
+		msg "    Coredump indicates executable '${exe}'"
+
+		# There's really only one reason --asterisk-bin might have
+		# been specified and that is because the version of the binary
+		# installed is newer than the one that caused the coredump in
+		# which case, --asterisk-bin might be used to point to a saved
+		# version of the correct binary.
+		if [ -n "${ASTERISK_BIN}" ] ; then
+			msg "    but --asterisk-bin was specified so using '${ASTERISK_BIN}'"
+			exe="${ASTERISK_BIN}"
+		fi
 
-		# Let's make sure it's an asterisk coredump by dumping the notes
-		# section of the file and grepping for "asterisk".
-		readelf -n "${COREDUMPS[$i]}" | grep -q "asterisk" || {
+		msg "    Searching for asterisk module directory"
+		# Now let's get the modules directory.
+		module_dir=$(extract_string_symbol "${exe}" "${cf}" \
+				ast_config_AST_MODULE_DIR)
+		# If ast_config_AST_MODULE_DIR couldn't be found, either the
+		# coredump has no symbols or the coredump and exe don't match.
+		# Either way, it's of no use to us.
+		if [ ! -d "$module_dir" ] ; then
+			err <<-EOF
+			    Can't extract asterisk module directory.
+			    Either the executable '${exe}' has no symbols
+			    or it's changed since the coredump was generated.
+			    Either way we can't use it.  If you still have the
+			    binary that created this coredump, or can recreate
+			    the binary from the exact same code base and exact same
+			    options that were used to to create the binary that generated
+			    this coredump, specify its location with the
+			    --asterisk-bin option.
+			EOF
 			unset "COREDUMPS[$i]"
 			continue
-		}
+		fi
+		msg "    Found asterisk module directory '${module_dir}'"
+		if [ -n "${MODDIR}" ] ; then
+			msg "    but --moddir was specified so using '${MODDIR}'"
+		fi
 
 	done
 
 	if [ ${#COREDUMPS[@]} -eq 0 ] ; then
-		die -2 "No coredumps found"
+		die -2 "No valid coredumps found"
 	fi
 
-	# Sort and weed out any dups
-	COREDUMPS=( $(ls -t "${COREDUMPS[@]}" 2>/dev/null | uniq ) )
+	# Make sure files actually exist then sort and weed out any dups
+	mapfile -t COREDUMPS < <(readlink -e "${COREDUMPS[@]}" | sort -u)
 
 	if [ ${#COREDUMPS[@]} -eq 0 ] ; then
 		die -2 "No coredumps found"
@@ -176,7 +235,6 @@ else
 	fi
 fi
 
-
 if [ ${#COREDUMPS[@]} -eq 0 ] ; then
 	die -2 "No coredumps found"
 fi
@@ -184,41 +242,60 @@ fi
 # Extract the gdb scripts from the end of this script
 # and save them to /tmp/.gdbinit, then add a trap to
 # clean it up.
+
 gdbinit=${OUTPUTDIR}/.ast_coredumper.gdbinit
-trap "rm $gdbinit" EXIT
-ss=`egrep -n "^#@@@SCRIPTSTART@@@" $0 |cut -f1 -d:`
-tail -n +${ss} $0 >$gdbinit
+trap 'rm $gdbinit' EXIT
+sed '1,/^#@@@SCRIPTSTART@@@/ d' "$0" >"$gdbinit"
 
 # Now iterate over the coredumps and dump the debugging info
 for i in "${!COREDUMPS[@]}" ; do
-	cf=$(realpath -e ${COREDUMPS[$i]} || : )
+	cf=$(realpath -e "${COREDUMPS[$i]}" || : )
 	if [ -z "$cf" ] ; then
 		continue
 	fi
 	echo "Processing $cf"
-
+	astbin="${ASTERISK_BIN}"
+	[ -z "${astbin}" ] && astbin=$(extract_binary_name "${cf}")
+	moddir="${MODDIR}"
+	[ -z "${moddir}" ] && moddir=$(extract_string_symbol "${exe}" "${cf}" ast_config_AST_MODULE_DIR)
+	etcdir="${ETCDIR}"
+	[ -z "${etcdir}" ] && etcdir=$(extract_string_symbol "${exe}" "${cf}" ast_config_AST_CONFIG_DIR)
+	libdir="${LIBDIR}"
+	[ -z "${libdir}" ] && {
+		libfile=$(dump_note_strings "${cf}" | grep -m 1 -E "libasteriskssl|libasteriskpj")
+		libdir=$(dirname "${libfile}")
+	}
+
+	msg "    ASTBIN: $astbin"
+	msg "    MODDIR: $moddir"
+	msg "    ETCDIR: $etcdir"
+	msg "    LIBDIR: $libdir"
+
+	astbin_base=$(basename "${astbin}")
 	if ! $RUNNING && ! [[ "$cf" =~ "running" ]] && $RENAME ; then
-		df=$(date -r $cf ${DATEOPTS})
+		# shellcheck disable=SC2086		
+		df=$(date -r "$cf" ${DATEOPTS})
 		cfdir=$(dirname "$cf")
-		newcf="${cfdir}/core-asterisk-${df}"
+		newcf="${cfdir}/core-${astbin_base}-${df}"
 		if [ "${newcf}" != "${cf}" ] ; then
-			echo "Renaming $cf to $cfdir/core-asterisk-${df}"
-			mv "$cf" "${cfdir}/core-asterisk-${df}"
-			cf="${cfdir}/core-asterisk-${df}"
+			msg "    Renaming $cf to $cfdir/core-${astbin_base}-${df}"
+			rm "${cfdir}/core-${astbin_base}-${df}" >/dev/null 2>&1 || :
+			ln -s "$cf" "${cfdir}/core-${astbin_base}-${df}"
+			cf="${cfdir}/core-${astbin_base}-${df}"
 		fi
 	fi
 
-	cfname=`basename ${cf}`
+	cfname=$(basename "${cf}")
 
 	# Produce all the output files
-	${GDB} -n --batch -q --ex "source $gdbinit" "${ASTERISK_BIN}" "$cf" 2>/dev/null | (
+	${GDB} -n --batch -q --ex "source $gdbinit" "${astbin}" "$cf" 2>/dev/null | (
 		of=/dev/null
-		while IFS= read line ; do
+		while IFS= read -r line ; do
 			if [[ "$line" =~ !@!@!@!\ ([^\ ]+)\ !@!@!@! ]] ; then
 				of=${OUTPUTDIR}/${cfname}-${BASH_REMATCH[1]}
 				of=${of//:/-}
 				rm -f "$of"
-				echo "Creating $of"
+				msg "    Creating $of"
 			fi
 			echo -e $"$line" >> "$of"
 		done
@@ -227,85 +304,54 @@ for i in "${!COREDUMPS[@]}" ; do
 	if $TARBALL_COREDUMPS ; then
 		# We need to change occurrences of ':' to '-' because
 		# Jira won't let you attach a file with colons in the name.
-		cfname=${cfname//:/-}
-		tf=${OUTPUTDIR}/${cfname}.tar.gz
-		echo "Creating ${tf}"
-
-		dest=${OUTPUTDIR}/${cfname}.output
-		rm -rf ${dest} 2>/dev/null || :
-
-		libdir=""
-
-		if [ -n "${LIBDIR}" ] ; then
-			LIBDIR=$(realpath "${LIBDIR}")
-			if [ ! -d "${LIBDIR}/asterisk/modules" ] ; then
-				die -2 <<-EOF
-				${LIBDIR}/asterisk/modules does not exist.
-				The library specified by --libdir or LIBDIR ${LIBDIR})
-				either does not exist or does not contain an "asterisk/modules" directory.
-				EOF
-			fi
-			libdir=${LIBDIR}
-		else
-			abits=$(file -b ${ASTERISK_BIN} | sed -n -r -e "s/.*(32|64)-bit.*/\1/p")
-			declare -a searchorder
-			if [ $abits -eq 32 ] ; then
-				searchorder=( /lib /usr/lib /usr/lib32 /usr/local/lib )
-			else
-				searchorder=( /usr/lib64 /usr/local/lib64 /usr/lib /usr/local/lib /lib )
-			fi
-			for d in ${searchorder[@]} ; do
-				testmod="${d}/asterisk/modules/bridge_simple.so"
-				if [ -e "${testmod}" ] ; then
-					lbits=$(file -b ${ASTERISK_BIN} | sed -n -r -e "s/.*(32|64)-bit.*/\1/p")
-					if [ $lbits -eq $abits ] ; then
-						libdir=$d
-						break;
-					fi
-				fi
-			done
-
-			if [ -z "${libdir}" ] ; then
-				die -2 <<-EOF
-				No standard systemlibrary directory contained asterisk modules.
-				Please specify the correct system library directory
-				with the --libdir option or the LIBDIR variable.
-				${LIBDIR}/asterisk/modules must exist.
-				EOF
-			fi
-		fi
 
-		mkdir -p ${dest}/tmp ${dest}/${libdir}/asterisk ${dest}/etc ${dest}/usr/sbin
+		cfname="${cfname//:/-}"
+		tf="${OUTPUTDIR}/${cfname}.tar.gz"
+		echo "    Creating ${tf}"
 
-		ln -s ${cf} ${dest}/tmp/${cfname}
-		cp ${OUTPUTDIR}/${cfname}*.txt ${dest}/tmp/
-		[ -f /etc/os-release ] && cp /etc/os-release ${dest}/etc/
-		if $TARBALL_CONFIG ; then
-			cp -a /etc/asterisk ${dest}/etc/
-		fi
-		cp -a /${libdir}/libasterisk* ${dest}/${libdir}/
-		cp -a /${libdir}/asterisk/* ${dest}/${libdir}/asterisk/
-		cp -a /usr/sbin/asterisk ${dest}/usr/sbin
-		rm -rf ${tf}
-		tar -chzf ${tf} --transform="s/^[.]/${cfname}.output/" -C ${dest} .
+		dest="${OUTPUTDIR}/${cfname}.output"
+		rm -rf "${dest}" 2>/dev/null || :
+
+		astbindir=$(dirname "${astbin}")
+		mkdir -p "${dest}/tmp" "${dest}/${moddir}" "${dest}/etc" \
+		"${dest}/${etcdir}" "${dest}/${libdir}" "${dest}/${astbindir}"
+
+		ln -s "${cf}" "${dest}/tmp/${cfname}"
+		msg "    Copying results files"
+		cp "${OUTPUTDIR}/${cfname}"*.txt "${dest}/tmp/"
+		[ -f /etc/os-release ] && {
+			msg "    Copying /etc/os-release"
+			cp /etc/os-release "${dest}/etc/"
+		}
+
+		$TARBALL_CONFIG && {
+			msg "    Copying $etcdir"
+			cp -a "${etcdir}"/* "${dest}/${etcdir}/"
+		}
+
+		msg "    Copying ${libdir}/libasterisk*"
+		cp -a "${libdir}/libasterisk"* "${dest}/${libdir}/"
+		msg "    Copying ${moddir}"
+		cp -a "${moddir}"/* "${dest}/${moddir}/"
+		msg "    Copying ${astbin}"
+		cp -a "${astbin}" "${dest}/${astbin}"
+		rm -rf "${tf}"
+		msg "    Creating ${tf}"
+		tar -chzf "${tf}" --transform="s/^[.]/${cfname}.output/" -C "${dest}" .
 		sleep 3
-		rm -rf ${dest}
-		echo "Created $tf"
+		rm -rf "${dest}"
+		msg "    Created $tf"
 	elif $TARBALL_RESULTS ; then
-		cfname=${cfname//:/-}
-		tf=${OUTPUTDIR}/${cfname}.tar.gz
-		echo "Creating ${tf}"
-
-		dest=${OUTPUTDIR}/${cfname}.output
-		rm -rf ${dest} 2>/dev/null || :
-		mkdir -p ${dest}
-		cp ${OUTPUTDIR}/${cfname}*.txt ${dest}/
-		if $TARBALL_CONFIG ; then
-			mkdir -p ${dest}/etc
-			cp -a /etc/asterisk ${dest}/etc/
-		fi
-		tar -chzf ${tf} --transform="s/^[.]/${cfname}/" -C ${dest} .
-		rm -rf ${dest}
+		cfname="${cfname//:/-}"
+		tf="${OUTPUTDIR}/${cfname}.tar.gz"
+		msg "    Creating ${tf}"
+
+		dest="${OUTPUTDIR}/${cfname}.output"
+		rm -rf "${dest}" 2>/dev/null || :
+		mkdir -p "${dest}"
+		cp "${OUTPUTDIR}/${cfname}"*.txt "${dest}/"
+		tar -chzf "${tf}" --transform="s/^[.]/${cfname}/" -C "${dest}" .
+		rm -rf "${dest}"
 		echo "Created $tf"
 	fi
 
@@ -314,7 +360,7 @@ for i in "${!COREDUMPS[@]}" ; do
 	fi
 
 	if $DELETE_RESULTS_AFTER ; then
-		to_delete=$cf
+		to_delete="$cf"
 		if [ -n "$OUTPUTDIR" ] ; then
 			to_delete="$OUTPUTDIR/$cfname"
 		fi
@@ -326,11 +372,7 @@ exit
 # @formatter:off
 
 #@@@FUNCSSTART@@@
-print_help() {
-	sed -n -r -e "/^#@@@HELPSTART@@@/,\${p;/^#@@@HELPEND@@@/q}" $0 | sed '1d;$d'
-	exit 1
-}
-
+# shellcheck disable=SC2317
 err() {
 	if [ -z "$1" ] ; then
 		cat >&2
@@ -340,6 +382,7 @@ err() {
 	return 0
 }
 
+# shellcheck disable=SC2317
 msg() {
 	if [ -z "$1" ] ; then
 		cat
@@ -349,15 +392,17 @@ msg() {
 	return 0
 }
 
+# shellcheck disable=SC2317
 die() {
 	if [[ $1 =~ ^-([0-9]+) ]] ; then
 		RC=${BASH_REMATCH[1]}
 		shift
 	fi
 	err "$1"
-	exit ${RC:-1}
+	exit "${RC:-1}"
 }
 
+# shellcheck disable=SC2317
 S_COR() {
 	if $1 ; then
 		echo -n "$2"
@@ -366,6 +411,7 @@ S_COR() {
 	fi
 }
 
+# shellcheck disable=SC2317
 check_gdb() {
 	if [ -z "${GDB}" -o ! -x "${GDB}" ] ; then
 		die -2 <<-EOF
@@ -384,15 +430,18 @@ check_gdb() {
 	fi
 }
 
+# shellcheck disable=SC2317
 find_pid() {
 	if [ -n "$PID" ] ; then
 		# Make sure it's at least all numeric
 		[[ $PID =~ ^[0-9]+$ ]] || die -22 $"Pid $PID is invalid."
 		# Make sure it exists
-		cmd=$(ps -p $PID -o comm=) || die -22 "Pid $PID is not a valid process."
-		# Make sure the program (without path) is "asterisk"
-		[ "$cmd" == "asterisk" ] || die -22 "Pid $PID is '$cmd' not 'asterisk'."
-		echo $PID
+		cmd=$(ps -p "$PID" -o comm=) || die -22 "Pid $PID is not a valid process."
+		# Make sure the program is "asterisk" by looking for common modules
+		# in /proc/$PID/maps
+		grep -q -E "app_dial|pbx_config" "/proc/$PID/maps" || \
+			die -22 "Pid $PID '$cmd' not 'asterisk'."
+		echo "$PID"
 		return 0
 	fi
 
@@ -400,7 +449,7 @@ find_pid() {
 	# so we'll just get the pids that exactly match a program
 	# name of "asterisk".
 	pids=$( pgrep -d ',' -x "asterisk")
-	if [ -z ${pids} ] ; then
+	if [ -z "${pids}" ] ; then
 		die -3 <<-EOF
 		No running asterisk instances detected.
 		If you know the pid of the process you want to dump,
@@ -411,7 +460,7 @@ find_pid() {
 	# Now that we have the pids, let's get the command and
 	# its args. We'll add them to an array indexed by pid.
 	declare -a candidates
-	while read LINE ; do
+	while read -r LINE ; do
 		[[ $LINE =~ ([0-9]+)[\ ]+([^\ ]+)[\ ]+(.*) ]] || continue
 		pid=${BASH_REMATCH[1]}
 		prog=${BASH_REMATCH[2]}
@@ -422,7 +471,7 @@ find_pid() {
 		# filter to weed out remote consoles.
 		[[ "$prog" == "rasterisk" ]] && continue;
 		candidates[$pid]="${prog}^${args}"
-	done < <(ps -o pid= -o command= -p $pids)
+	done < <(ps -o pid= -o command= -p "$pids")
 
 	if [ ${#candidates[@]} -eq 0 ] ; then
 		die -3 <<-EOF
@@ -436,29 +485,77 @@ find_pid() {
 		die -22 <<-EOF
 		Detected more than one asterisk process running.
 		$(printf "%8s %s\n" "PID" "COMMAND")
-		$(for p in ${!candidates[@]} ; do printf "%8s %s\n" $p "${candidates[$p]//^/ }" ; done )
+		$(for p in "${!candidates[@]}" ; do printf "%8s %s\n" $p "${candidates[$p]//^/ }" ; done )
 		If you know the pid of the process you want to dump,
 		supply it on the command line with --pid=<pid>.
 		EOF
 	fi
 
-	echo ${!candidates[@]}
+	echo "${!candidates[@]}"
+	return 0
+}
+
+# extract_binary_name <coredump>
+# shellcheck disable=SC2317
+extract_binary_name() {
+	${GDB} -c "$1" -q --batch -ex "info proc exe" 2>/dev/null \
+		| sed -n -r -e "s/exe\s*=\s*'([^ ]+).*'/\1/gp"
+	return 0
+}
+
+# extract_string_symbol <binary> <coredump> <symbol>
+# shellcheck disable=SC2317
+extract_string_symbol() {
+	${GDB} "$1" "$2" -q --batch \
+		-ex "p $3" 2>/dev/null \
+		| sed -n -r -e 's/[$]1\s*=\s*[0-9a-fx]+\s+<[^>]+>\s+"([^"]+)"/\1/gp'
 	return 0
 }
-#@@@FUNCSEND@@@
 
-#@@@HELPSTART@@@
+# The note0 section of the coredump has the map of shared
+# libraries to address so we can find that section with
+# objdump, dump it with dd, extract the strings, and
+# search for common asterisk modules.  This is quicker
+# that just running strings against the entire coredump
+# which could be many gigabytes in length.
+
+# dump_note_strings <coredump> [ <min string length> ]
+# shellcheck disable=SC2317
+dump_note_strings() {
+	note0=$(objdump -h "$1" | grep note0)
+
+	# The header we're interested in will look like this...
+	# Idx Name  Size      VMA               LMA               File off  Algn
+	# 0   note0 00033364  0000000000000000  0000000000000000  0000de10  2**0
+	# We want size and offset
+
+	[[ "${note0}" =~ ^[\ \t]*[0-9]+[\ \t]+note0[\ \t]+([0-9a-f]+)[\ \t]+[0-9a-f]+[\ \t]+[0-9a-f]+[\ \t]+([0-9a-f]+) ]] || {
+		return 1
+	}
+	count=$((0x${BASH_REMATCH[1]}))
+	skip=$((0x${BASH_REMATCH[2]}))
+
+	dd if="$1" bs=1 count="$count" skip="$skip" 2>/dev/null | strings -n "${2:-8}"
+	return 0
+}
+
+# shellcheck disable=SC2317
+print_help() {
+cat <<EOF
 NAME
 	$prog - Dump and/or format asterisk coredump files
 
 SYNOPSIS
-	$prog [ --help ] [ --running | --RUNNING ] [ --pid="pid" ]
-		[ --latest ] [ --OUTPUTDIR="path" ]
-		[ --libdir="path" ] [ --asterisk-bin="path" ]
-		[ --gdb="path" ] [ --rename ] [ --dateformat="date options" ]
+	$prog [ --help ] [ --running | --RUNNING ] [ --pid=<pid> ]
+		[ --latest ] [ --outputdir=<path> ]
+		[ --asterisk-bin=<path to asterisk binary that created the coredump> ]
+		[ --moddir=<path to asterisk modules directory that created the coredump> ]
+		[ --libdir=<path to directory containing libasterisk* libraries> ]
+		[ --gdb=<path to gdb> ] [ --rename ] [ --dateformat=<date options> ]
 		[ --tarball-coredumps ] [ --delete-coredumps-after ]
 		[ --tarball-results ] [ --delete-results-after ]
 		[ --tarball-config ]
+		[ --etcdir=<path to directory containing asterisk config files> ]
 		[ <coredump> | <pattern> ... ]
 
 DESCRIPTION
@@ -507,16 +604,25 @@ DESCRIPTION
 		The directory into which output products will be saved.
 		Default: same directory as coredump
 
-	--libdir=<shared libs directory>
-		The directory where the libasterisk* shared libraries and
-		the asterisk/modules directory are located.  The common
-		directories like /usr/lib, /usr/lib64, etc are automatically
-		searches so only use this option when your asterisk install
-		is non-standard.
-
-	--asterisk-bin=<asterisk binary>
-		Path to the asterisk binary.
-		Default: look for asterisk in the PATH.
+	--asterisk-bin=<path to asterisk binary that created the coredump>
+		You should only need to use this if the asterisk binary on
+		the system has changed since the coredump was generated.
+		In this case, the symbols won't be valid and the coredump
+		will be useless.  If you can recreate the binary with
+		the exact same source code and compile options, or you have
+		a saved version, you can use this option to use that binary
+		instead.
+		Default: executable path extracted from coredump
+
+	--moddir=<path to asterisk modules directory>
+		You should only need to use this for the same reason you'd
+		need to use --asterisk-bin.
+		Default: "astmoddir" directory extracted from coredump
+
+	--libdir=<path to directory containing libasterisk* libraries>
+		You should only need to use this for the same reason you'd
+		need to use --asterisk-bin.
+		Default: libdir extracted from coredump
 
 	--gdb=<path_to_gdb>
 		gdb must have python support built-in.  Most do.
@@ -542,6 +648,19 @@ DESCRIPTION
 		WARNING:  This file could be quite large!
 		Mutually exclusive with --tarball-results
 
+	--tarball-config
+		Adds the contents of /etc/asterisk to the tarball created
+		with --tarball-coredumps.
+		WARNING: This may include confidential information like
+		secrets or keys.
+
+	--etcdir=<path to directory asterisk config files>
+		If you use --tarball-config and the config files that
+		match this coredump are in a location other than that which
+		was specified in "astetcdir" in asterisk.conf, you can use
+		this option to point to their current location.
+		Default: "astetcdir" extracted from coredump.
+
 	--delete-coredumps-after
 		Deletes all processed coredumps regardless of whether
 		a tarball was created.
@@ -558,15 +677,9 @@ DESCRIPTION
 		to use this option unless you have also specified
 		--tarball-results.
 
-	--tarball-config
-		Adds the contents of /etc/asterisk to the tarball created
-		with --tarball-coredumps or --tarball-results.
-
 	<coredump> | <pattern>
 		A list of coredumps or coredump search patterns.  These
-		will override the default and those specified in the config files.
-
-		The default pattern is "/tmp/core!(*.txt)"
+		will override the default of "/tmp/core!(*.txt)"
 
 		The "!(*.txt)" tells bash to ignore any files that match
 		the base pattern and end in ".txt".  It$'s not strictly
@@ -583,7 +696,6 @@ NOTES
 	Examples:
 		TARBALL_RESULTS=true
 		RENAME=false
-		ASTERISK_BIN=/usr/sbin/asterisk
 
 	The script relies on not only bash, but also recent GNU date and
 	gdb with python support.  *BSD operating systems may require
@@ -602,7 +714,10 @@ FILES
 	See the configs/samples/ast_debug_tools.conf file in the asterisk
 	source tree for more info.
 
-#@@@HELPEND@@@
+EOF
+}
+
+#@@@FUNCSEND@@@
 
 # Be careful editing the inline scripts.
 # They're space-indented.