[committed] gprofng: fix display gmon option error handling

claudiu.zissulescu-ianculescu@oracle.com claudiu.zissulescu-ianculescu@oracle.com
Wed Mar 11 13:01:30 GMT 2026


From: Claudiu Zissulescu <claudiu.zissulescu-ianculescu@oracle.com>

Parse display gmon options only once so invalid arguments are not
reported twice and exit status is set to failure for invalid usage.

Also add tests in gp-gmon.exp to verify unknown options and missing
-o argument fail as expected and produce a single diagnostic.

gprofng/
	* src/gp-gmon.cc (usage_and_exit): New function.
	(check_mods): Change number of parameters.
	(checkflagterm): Fix error text, update to use new functions.
	* testsuite/gprofng.display/gp-gmon.exp: Add new test.
---
 gprofng/src/gp-gmon.cc                        | 32 +++++++++----------
 gprofng/testsuite/gprofng.display/gp-gmon.exp | 30 +++++++++++++++++
 2 files changed, 45 insertions(+), 17 deletions(-)

diff --git a/gprofng/src/gp-gmon.cc b/gprofng/src/gp-gmon.cc
index 6e018603c42..d3b4a67f51c 100644
--- a/gprofng/src/gp-gmon.cc
+++ b/gprofng/src/gp-gmon.cc
@@ -56,7 +56,8 @@ public:
 private:
   // override methods in base class
   void usage ();
-  int check_mods (int argc, char *argv[], bool check);
+  void usage_and_exit (int exit_code);
+  int check_mods (int argc, char *argv[]);
 
   bool overwrite = false;
   Coll_Ctrl *cc;
@@ -544,7 +545,7 @@ checkflagterm (const char *c)
 {
   if (c[2] != 0)
     {
-      dbe_write (2, GTXT ("collect: unrecognized argument `%s'\n"), c);
+      dbe_write (2, GTXT ("gmon: unrecognized argument `%s'\n"), c);
       return -1;
     }
   return 0;
@@ -598,14 +599,12 @@ er_gmon::start (int argc, char *argv[])
     {
       /* only one argument, -h */
       usage ();
-      exit (0);
     }
   else if (argc == 2 && (strcmp (argv[1], NTXT ("-help")) == 0 ||
 			 strcmp (argv[1], NTXT ("--help")) == 0))
     {
       /* only one argument, -help or --help */
       usage ();
-      exit (0);
     }
   else if ((argc == 2) &&
 	   (strcmp (argv[1], NTXT ("--version")) == 0))
@@ -617,12 +616,10 @@ er_gmon::start (int argc, char *argv[])
       exit (0);
     }
 
-  check_mods (argc, argv, true);
-  int adj = check_mods (argc, argv, false);
+  int adj = check_mods (argc, argv);
   if (adj < 0)
     {
-      usage ();
-      exit (0);
+      usage_and_exit (1);
     }
 
   char *ret = cc->create_exp_dir ();
@@ -651,8 +648,7 @@ er_gmon::start (int argc, char *argv[])
     }
   else if (argc != adj)
     {
-      usage ();
-      exit (0);
+      usage_and_exit (1);
     }
 
   /* Read the elf syms and the gmon file.  */
@@ -676,7 +672,7 @@ er_gmon::start (int argc, char *argv[])
 
 /* Get the args and search for modifiers.  */
 int
-er_gmon::check_mods (int argc, char *argv[], bool check)
+er_gmon::check_mods (int argc, char *argv[])
 {
   char *expName = NULL;
   int i = -1;
@@ -692,8 +688,6 @@ er_gmon::check_mods (int argc, char *argv[], bool check)
 	  overwrite = true;
 	  //FALLTHROU
 	case 'o':
-	  if (check)
-	    return i;
 	  if (checkflagterm (argv[i]) == -1)
 	    return -1;
 	  if (argv[i + 1] == NULL)
@@ -718,8 +712,6 @@ er_gmon::check_mods (int argc, char *argv[], bool check)
 	  return -1;
 	}
     }
-  if (check)
-    return i;
   if (expName)
     {
       char *ccret;
@@ -736,11 +728,17 @@ er_gmon::check_mods (int argc, char *argv[], bool check)
 	  return -1;
 	}
     }
-  return (check ? -1 : i);
+  return i;
 }
 
 void
 er_gmon::usage ()
+{
+  usage_and_exit (0);
+}
+
+void
+er_gmon::usage_and_exit (int exit_code)
 {
   printf ( GTXT (
     "Usage: gprofng display gmon [OPTION(S)] [TARGET-OBJECT [GMON-FILE]]\n"));
@@ -760,7 +758,7 @@ er_gmon::usage ()
     "                    existing experiment directory with the same name.\n"
     "\n"));
 
-    exit (0);
+    exit (exit_code);
 }
 
 er_gmon::~er_gmon ()
diff --git a/gprofng/testsuite/gprofng.display/gp-gmon.exp b/gprofng/testsuite/gprofng.display/gp-gmon.exp
index c7d261883d5..439270d83e7 100644
--- a/gprofng/testsuite/gprofng.display/gp-gmon.exp
+++ b/gprofng/testsuite/gprofng.display/gp-gmon.exp
@@ -50,6 +50,23 @@ proc check_gp_gmon { a_opt } {
   }
 }
 
+proc check_gp_gmon_fail { cmd err_pat } {
+  global tdir
+  set output [run_native_host_cmd "$cmd"]
+  set out [lindex $output 1]
+  if { [lindex $output 0] == 0 } then {
+    send_log "'$cmd' should fail, but exited with status 0\n"
+    fail $tdir
+    return -code break
+  }
+  if { ![regexp -- $err_pat $out] } then {
+    send_log "'$cmd' failed, but expected pattern '$err_pat' is missing\n"
+    fail $tdir
+    return -code break
+  }
+  return $output
+}
+
 run_native_host_cmd "mkdir -p $tdir"
 
 # Build test, create experiment:
@@ -67,4 +84,17 @@ if { [lindex $output 0] != 0 } then {
 
 check_gp_gmon gmontst
 
+# Unknown option should fail once with one diagnostic.
+set output [check_gp_gmon_fail "$gprofng display gmon -z" \
+  {gmon: unrecognized argument `-z'}]
+if { [regexp -all -- {gmon: unrecognized argument `-z'} [lindex $output 1]] != 1 } {
+  send_log "Unexpected duplicate diagnostics for unknown option\n"
+  fail $tdir
+  return
+}
+
+# Missing argument for -o should fail.
+check_gp_gmon_fail "$gprofng display gmon -o" \
+  {Argument -o must be followed by a file name}
+
 pass $tdir
-- 
2.53.0



More information about the Binutils mailing list