abipkgdiff: Add support to compare packages with CTF debug format
Commit Message
This patch add support in `abipkgdiff' to compare binaries with CTF
debug data. It depends of:
* https://sourceware.org/pipermail/libabigail/2022q2/004340.html
* https://sourceware.org/pipermail/libabigail/2022q2/004343.html
* https://sourceware.org/pipermail/libabigail/2022q2/004344.html
* [PATCH] ctf-reader: add support to looking debug information in
external path
Please let me know your comments, I'll really appreciate them.
Kind regards,
Guillermo
This patch add support in `abipkgdiff' to compare binaries with CTF
debug information inside of packages, when `--ctf' option is provided.
* tools/abipkgdiff.cc: Include `abg-ctf-reader.h'.
(options::use_ctf): Add new data member.
(display_usage): Add `--ctf' usage.
(compare): Add condition to use ctf-reader to extract
(parse_command_line): Set `options::use_ctf' when --ctf
option is provided.
and build CTF corpora when `options::use_ctf' is set.
(compare_to_self): Likewise.
Signed-off-by: Guillermo E. Martinez <guillermo.e.martinez@oracle.com>
---
doc/manuals/abipkgdiff.rst | 4 ++
tools/abipkgdiff.cc | 116 ++++++++++++++++++++++++++++++-------
2 files changed, 100 insertions(+), 20 deletions(-)
base-commit: c96463e1ad974b7c4561886d7a3aa8a3c9a35607
prerequisite-patch-id: 781b026536589341e1e4378d9529fe258633bb53
prerequisite-patch-id: e6191c510bc90e225bd0858d333e2e01b6e52a62
prerequisite-patch-id: b87e0b761bf3f909eb84147b3b13e2a338de9509
prerequisite-patch-id: 6ddc271ce828e41f3d7c1f472ad01be8fb10b5d3
Comments
Hello Guillermo,
"Guillermo E. Martinez via Libabigail" <libabigail@sourceware.org> a
écrit:
I have applied the patch to master, thank you very much for it!
I have however made some little adjustments. Please read about them
below.
commit a433820d809bfa134210f5647ee2d1e303d591e7
Author: Guillermo E. Martinez <guillermo.e.martinez@oracle.com>
Date: Fri May 6 21:03:26 2022 -0500
[...]
> --- a/tools/abipkgdiff.cc
> +++ b/tools/abipkgdiff.cc
[...]
> +#ifdef WITH_CTF
> + if (opts.use_ctf)
> + {
> + ctxt_ctf = abigail::ctf_reader::create_read_context(elf1.path,
> + di_dirs1,
> + env.get());
abigail::ctf_reader::create_read_context only takes two parameters:
elf1.path and env.get(). So I removed the di_dirs1 one.
[...]
> +#ifdef WITH_CTF
> + if (opts.use_ctf)
> + {
> + ctxt_ctf = abigail::ctf_reader::create_read_context
> + (elf2.path, di_dirs2, env.get());
Likewise.
> +#ifdef WITH_CTF
> + if (opts.use_ctf)
> + {
> + ctxt_ctf = abigail::ctf_reader::create_read_context(elf.path,
> + di_dirs,
> + env.get());
Likewise.
[...]
> This patch add support in `abipkgdiff' to compare binaries with CTF
> debug information inside of packages, when `--ctf' option is provided.
>
> * tools/abipkgdiff.cc: Include `abg-ctf-reader.h'.
> (options::use_ctf): Add new data member.
> (display_usage): Add `--ctf' usage.
> (compare): Add condition to use ctf-reader to extract
> (parse_command_line): Set `options::use_ctf' when --ctf
> option is provided.
> and build CTF corpora when `options::use_ctf' is set.
> (compare_to_self): Likewise.
Do you plan on adding some regression tests for this patch? That
would be neat and useful.
>
> Signed-off-by: Guillermo E. Martinez <guillermo.e.martinez@oracle.com>
Applied the patch below to master, thanks!
From 28a629347f598e3b5a35152538c4a4638ca3995a Mon Sep 17 00:00:00 2001
From: "Guillermo E. Martinez" <guillermo.e.martinez@oracle.com>
Date: Fri, 6 May 2022 21:03:26 -0500
Subject: [PATCH] abipkgdiff: Add support to compare packages with CTF debug format
This patch add support in `abipkgdiff' to compare binaries with CTF
debug information inside of packages, when `--ctf' option is provided.
* tools/abipkgdiff.cc: Include `abg-ctf-reader.h'.
(options::use_ctf): Add new data member.
(display_usage): Add `--ctf' usage.
(compare): Add condition to use ctf-reader to extract
(parse_command_line): Set `options::use_ctf' when --ctf
option is provided.
and build CTF corpora when `options::use_ctf' is set.
(compare_to_self): Likewise.
Signed-off-by: Guillermo E. Martinez <guillermo.e.martinez@oracle.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
---
doc/manuals/abipkgdiff.rst | 4 ++
tools/abipkgdiff.cc | 114 ++++++++++++++++++++++++++++++-------
2 files changed, 98 insertions(+), 20 deletions(-)
diff --git a/doc/manuals/abipkgdiff.rst b/doc/manuals/abipkgdiff.rst
index c15dc51f..f297c9a8 100644
--- a/doc/manuals/abipkgdiff.rst
+++ b/doc/manuals/abipkgdiff.rst
@@ -468,6 +468,10 @@ Options
==== SELF CHECK SUCCEEDED for 'libGLU.so.1.3.1' ====
$
+ * ``--ctf``
+
+ This is used to compare packages with CTF debug information, if present.
+
.. _abipkgdiff_return_value_label:
Return value
diff --git a/tools/abipkgdiff.cc b/tools/abipkgdiff.cc
index ef9fabf2..eabd19ae 100644
--- a/tools/abipkgdiff.cc
+++ b/tools/abipkgdiff.cc
@@ -90,6 +90,9 @@
#include "abg-dwarf-reader.h"
#include "abg-reader.h"
#include "abg-writer.h"
+#ifdef WITH_CTF
+#include "abg-ctf-reader.h"
+#endif
using std::cout;
using std::cerr;
@@ -202,6 +205,10 @@ public:
bool fail_if_no_debug_info;
bool show_identical_binaries;
bool self_check;
+#ifdef WITH_CTF
+ bool use_ctf;
+#endif
+
vector<string> kabi_whitelist_packages;
vector<string> suppression_paths;
vector<string> kabi_whitelist_paths;
@@ -240,6 +247,10 @@ public:
fail_if_no_debug_info(),
show_identical_binaries(),
self_check()
+#ifdef WITH_CTF
+ ,
+ use_ctf()
+#endif
{
// set num_workers to the default number of threads of the
// underlying maching. This is the default value for the number
@@ -879,6 +890,9 @@ display_usage(const string& prog_name, ostream& out)
<< " --verbose emit verbose progress messages\n"
<< " --self-check perform a sanity check by comparing "
"binaries inside the input package against their ABIXML representation\n"
+#ifdef WITH_CTF
+ << " --ctf use CTF instead of DWARF in ELF files\n"
+#endif
<< " --help|-h display this help message\n"
<< " --version|-v display program version information"
" and exit\n";
@@ -1302,15 +1316,31 @@ compare(const elf_file& elf1,
<< " ...\n";
corpus_sptr corpus1;
+#ifdef WITH_CTF
+ abigail::ctf_reader::read_context_sptr ctxt_ctf;
+#endif
+ read_context_sptr ctxt_dwarf;
{
- read_context_sptr c =
- create_read_context(elf1.path, di_dirs1, env.get(),
- /*load_all_types=*/opts.show_all_types);
- add_read_context_suppressions(*c, priv_types_supprs1);
- if (!opts.kabi_suppressions.empty())
- add_read_context_suppressions(*c, opts.kabi_suppressions);
+#ifdef WITH_CTF
+ if (opts.use_ctf)
+ {
+ ctxt_ctf = abigail::ctf_reader::create_read_context(elf1.path,
+ env.get());
+ ABG_ASSERT(ctxt_ctf);
+ corpus1 = abigail::ctf_reader::read_corpus(ctxt_ctf.get(),
+ c1_status);
+ }
+ else
+#endif
+ {
+ ctxt_dwarf = create_read_context(elf1.path, di_dirs1, env.get(),
+ /*load_all_types=*/opts.show_all_types);
+ add_read_context_suppressions(*ctxt_dwarf, priv_types_supprs1);
+ if (!opts.kabi_suppressions.empty())
+ add_read_context_suppressions(*ctxt_dwarf, opts.kabi_suppressions);
- corpus1 = read_corpus_from_elf(*c, c1_status);
+ corpus1 = read_corpus_from_elf(*ctxt_dwarf, c1_status);
+ }
bool bail_out = false;
if (!(c1_status & abigail::elf_reader::STATUS_OK))
@@ -1356,7 +1386,13 @@ compare(const elf_file& elf1,
emit_prefix("abipkgdiff", cerr)
<< "Could not find alternate debug info file";
string alt_di_path;
- abigail::dwarf_reader::refers_to_alt_debug_info(*c, alt_di_path);
+#ifdef WITH_CTF
+ if (opts.use_ctf)
+ ;
+ else
+#endif
+ abigail::dwarf_reader::refers_to_alt_debug_info(*ctxt_dwarf,
+ alt_di_path);
if (!alt_di_path.empty())
cerr << ": " << alt_di_path << "\n";
else
@@ -1389,15 +1425,26 @@ compare(const elf_file& elf1,
corpus_sptr corpus2;
{
- read_context_sptr c =
- create_read_context(elf2.path, di_dirs2, env.get(),
- /*load_all_types=*/opts.show_all_types);
- add_read_context_suppressions(*c, priv_types_supprs2);
+#ifdef WITH_CTF
+ if (opts.use_ctf)
+ {
+ ctxt_ctf = abigail::ctf_reader::create_read_context(elf2.path,
+ env.get());
+ corpus2 = abigail::ctf_reader::read_corpus(ctxt_ctf.get(),
+ c2_status);
+ }
+ else
+#endif
+ {
+ ctxt_dwarf = create_read_context(elf2.path, di_dirs2, env.get(),
+ /*load_all_types=*/opts.show_all_types);
+ add_read_context_suppressions(*ctxt_dwarf, priv_types_supprs2);
- if (!opts.kabi_suppressions.empty())
- add_read_context_suppressions(*c, opts.kabi_suppressions);
+ if (!opts.kabi_suppressions.empty())
+ add_read_context_suppressions(*ctxt_dwarf, opts.kabi_suppressions);
- corpus2 = read_corpus_from_elf(*c, c2_status);
+ corpus2 = read_corpus_from_elf(*ctxt_dwarf, c2_status);
+ }
bool bail_out = false;
if (!(c2_status & abigail::elf_reader::STATUS_OK))
@@ -1443,7 +1490,13 @@ compare(const elf_file& elf1,
emit_prefix("abipkgdiff", cerr)
<< "Could not find alternate debug info file";
string alt_di_path;
- abigail::dwarf_reader::refers_to_alt_debug_info(*c, alt_di_path);
+#ifdef WITH_CTF
+ if (opts.use_ctf)
+ ;
+ else
+#endif
+ abigail::dwarf_reader::refers_to_alt_debug_info(*ctxt_dwarf,
+ alt_di_path);
if (!alt_di_path.empty())
cerr << ": " << alt_di_path << "\n";
else
@@ -1540,12 +1593,29 @@ compare_to_self(const elf_file& elf,
<< " ...\n";
corpus_sptr corp;
+#ifdef WITH_CTF
+ abigail::ctf_reader::read_context_sptr ctxt_ctf;
+#endif
+ read_context_sptr ctxt_dwarf;
{
- read_context_sptr c =
- create_read_context(elf.path, di_dirs, env.get(),
- /*read_all_types=*/opts.show_all_types);
+#ifdef WITH_CTF
+ if (opts.use_ctf)
+ {
+ ctxt_ctf = abigail::ctf_reader::create_read_context(elf.path,
+ env.get());
+ ABG_ASSERT(ctxt_ctf);
+ corp = abigail::ctf_reader::read_corpus(ctxt_ctf.get(),
+ c_status);
+ }
+ else
+#endif
+ {
+ ctxt_dwarf =
+ create_read_context(elf.path, di_dirs, env.get(),
+ /*read_all_types=*/opts.show_all_types);
- corp = read_corpus_from_elf(*c, c_status);
+ corp = read_corpus_from_elf(*ctxt_dwarf, c_status);
+ }
if (!(c_status & abigail::elf_reader::STATUS_OK))
{
@@ -3332,6 +3402,10 @@ parse_command_line(int argc, char* argv[], options& opts)
(make_path_absolute(argv[j]).get());
++i;
}
+#ifdef WITH_CTF
+ else if (!strcmp(argv[i], "--ctf"))
+ opts.use_ctf = true;
+#endif
else if (!strcmp(argv[i], "--help")
|| !strcmp(argv[i], "-h"))
{
On Monday, May 16, 2022 5:09:51 PM CDT Dodji Seketeli wrote:
> Hello Guillermo,
Hello Dodji,
> "Guillermo E. Martinez via Libabigail" <libabigail@sourceware.org> a
> écrit:
>
> I have applied the patch to master, thank you very much for it!
>
> I have however made some little adjustments. Please read about them
> below.
Ok, thanks!
> commit a433820d809bfa134210f5647ee2d1e303d591e7
> Author: Guillermo E. Martinez <guillermo.e.martinez@oracle.com>
> Date: Fri May 6 21:03:26 2022 -0500
>
> [...]
>
> > --- a/tools/abipkgdiff.cc
> > +++ b/tools/abipkgdiff.cc
>
> [...]
>
> > +#ifdef WITH_CTF
> > + if (opts.use_ctf)
> > + {
> > + ctxt_ctf = abigail::ctf_reader::create_read_context(elf1.path,
> > + di_dirs1,
> > + env.get());
>
> abigail::ctf_reader::create_read_context only takes two parameters:
> elf1.path and env.get(). So I removed the di_dirs1 one.
Oh, this is because there is a previous patch to use the `di_dirs1' parameters:
https://sourceware.org/pipermail/libabigail/2022q2/004361.html[1]
my fault, for get mentioned it.
> [...]
>
>
> > +#ifdef WITH_CTF
> > + if (opts.use_ctf)
> > + {
> > + ctxt_ctf = abigail::ctf_reader::create_read_context
> > + (elf2.path, di_dirs2, env.get());
>
> Likewise.
>
> > +#ifdef WITH_CTF
> > + if (opts.use_ctf)
> > + {
> > + ctxt_ctf = abigail::ctf_reader::create_read_context(elf.path,
> > + di_dirs,
> > + env.get());
>
> Likewise.
>
> [...]
>
>
> > This patch add support in `abipkgdiff' to compare binaries with CTF
> > debug information inside of packages, when `--ctf' option is provided.
> >
> > * tools/abipkgdiff.cc: Include `abg-ctf-reader.h'.
> > (options::use_ctf): Add new data member.
> > (display_usage): Add `--ctf' usage.
> > (compare): Add condition to use ctf-reader to extract
> > (parse_command_line): Set `options::use_ctf' when --ctf
> > option is provided.
> > and build CTF corpora when `options::use_ctf' is set.
> > (compare_to_self): Likewise.
>
> Do you plan on adding some regression tests for this patch? That
> would be neat and useful.
Yes, it will send soon :-)
> >
> > Signed-off-by: Guillermo E. Martinez <guillermo.e.martinez@oracle.com>
>
> Applied the patch below to master, thanks!
Thanks!
> From 28a629347f598e3b5a35152538c4a4638ca3995a Mon Sep 17 00:00:00 2001
> From: "Guillermo E. Martinez" <guillermo.e.martinez@oracle.com>
> Date: Fri, 6 May 2022 21:03:26 -0500
> Subject: [PATCH] abipkgdiff: Add support to compare packages with CTF debug format
>
> [...]
--------
[1] https://sourceware.org/pipermail/libabigail/2022q2/004361.html
Hello Guillermo,
"Guillermo E. Martinez" <guillermo.e.martinez@oracle.com> a écrit:
[...]
>> abigail::ctf_reader::create_read_context only takes two parameters:
>> elf1.path and env.get(). So I removed the di_dirs1 one.
> Oh, this is because there is a previous patch to use the `di_dirs1' parameters:
> https://sourceware.org/pipermail/libabigail/2022q2/004361.html[1]
> my fault, for get mentioned it.
No problem, I'll look at that one, apply it, and perform the necessary
modifications.
Maybe in the future, if you have patches that depends on each other like
that, it's better to post a complete patch-set, rather than posting them
one by one?
In any case, thank you for working on this, it's appreciated.
[...]
Cheers,
On Tuesday, May 17, 2022 2:11:28 AM CDT Dodji Seketeli wrote:
> Hello Guillermo,
Hello Dodji,
> "Guillermo E. Martinez" <guillermo.e.martinez@oracle.com> a écrit:
>
> [...]
>
> >> abigail::ctf_reader::create_read_context only takes two parameters:
> >> elf1.path and env.get(). So I removed the di_dirs1 one.
> > Oh, this is because there is a previous patch to use the `di_dirs1' parameters:
> > https://sourceware.org/pipermail/libabigail/2022q2/004361.html[1]
> > my fault, for get mentioned it.
>
> No problem, I'll look at that one, apply it, and perform the necessary
> modifications.
>
> Maybe in the future, if you have patches that depends on each other like
> that, it's better to post a complete patch-set, rather than posting them
> one by one?
ok, understood.
> In any case, thank you for working on this, it's appreciated.
>
> [...]
>
> Cheers,
Thanks!,
guillermo
@@ -468,6 +468,10 @@ Options
==== SELF CHECK SUCCEEDED for 'libGLU.so.1.3.1' ====
$
+ * ``--ctf``
+
+ This is used to compare packages with CTF debug information, if present.
+
.. _abipkgdiff_return_value_label:
Return value
@@ -90,6 +90,9 @@
#include "abg-dwarf-reader.h"
#include "abg-reader.h"
#include "abg-writer.h"
+#ifdef WITH_CTF
+#include "abg-ctf-reader.h"
+#endif
using std::cout;
using std::cerr;
@@ -202,6 +205,10 @@ public:
bool fail_if_no_debug_info;
bool show_identical_binaries;
bool self_check;
+#ifdef WITH_CTF
+ bool use_ctf;
+#endif
+
vector<string> kabi_whitelist_packages;
vector<string> suppression_paths;
vector<string> kabi_whitelist_paths;
@@ -240,6 +247,10 @@ public:
fail_if_no_debug_info(),
show_identical_binaries(),
self_check()
+#ifdef WITH_CTF
+ ,
+ use_ctf()
+#endif
{
// set num_workers to the default number of threads of the
// underlying maching. This is the default value for the number
@@ -879,6 +890,9 @@ display_usage(const string& prog_name, ostream& out)
<< " --verbose emit verbose progress messages\n"
<< " --self-check perform a sanity check by comparing "
"binaries inside the input package against their ABIXML representation\n"
+#ifdef WITH_CTF
+ << " --ctf use CTF instead of DWARF in ELF files\n"
+#endif
<< " --help|-h display this help message\n"
<< " --version|-v display program version information"
" and exit\n";
@@ -1302,15 +1316,32 @@ compare(const elf_file& elf1,
<< " ...\n";
corpus_sptr corpus1;
+#ifdef WITH_CTF
+ abigail::ctf_reader::read_context_sptr ctxt_ctf;
+#endif
+ read_context_sptr ctxt_dwarf;
{
- read_context_sptr c =
- create_read_context(elf1.path, di_dirs1, env.get(),
- /*load_all_types=*/opts.show_all_types);
- add_read_context_suppressions(*c, priv_types_supprs1);
- if (!opts.kabi_suppressions.empty())
- add_read_context_suppressions(*c, opts.kabi_suppressions);
+#ifdef WITH_CTF
+ if (opts.use_ctf)
+ {
+ ctxt_ctf = abigail::ctf_reader::create_read_context(elf1.path,
+ di_dirs1,
+ env.get());
+ ABG_ASSERT(ctxt_ctf);
+ corpus1 = abigail::ctf_reader::read_corpus(ctxt_ctf.get(),
+ c1_status);
+ }
+ else
+#endif
+ {
+ ctxt_dwarf = create_read_context(elf1.path, di_dirs1, env.get(),
+ /*load_all_types=*/opts.show_all_types);
+ add_read_context_suppressions(*ctxt_dwarf, priv_types_supprs1);
+ if (!opts.kabi_suppressions.empty())
+ add_read_context_suppressions(*ctxt_dwarf, opts.kabi_suppressions);
- corpus1 = read_corpus_from_elf(*c, c1_status);
+ corpus1 = read_corpus_from_elf(*ctxt_dwarf, c1_status);
+ }
bool bail_out = false;
if (!(c1_status & abigail::elf_reader::STATUS_OK))
@@ -1356,7 +1387,13 @@ compare(const elf_file& elf1,
emit_prefix("abipkgdiff", cerr)
<< "Could not find alternate debug info file";
string alt_di_path;
- abigail::dwarf_reader::refers_to_alt_debug_info(*c, alt_di_path);
+#ifdef WITH_CTF
+ if (opts.use_ctf)
+ ;
+ else
+#endif
+ abigail::dwarf_reader::refers_to_alt_debug_info(*ctxt_dwarf,
+ alt_di_path);
if (!alt_di_path.empty())
cerr << ": " << alt_di_path << "\n";
else
@@ -1389,15 +1426,26 @@ compare(const elf_file& elf1,
corpus_sptr corpus2;
{
- read_context_sptr c =
- create_read_context(elf2.path, di_dirs2, env.get(),
- /*load_all_types=*/opts.show_all_types);
- add_read_context_suppressions(*c, priv_types_supprs2);
+#ifdef WITH_CTF
+ if (opts.use_ctf)
+ {
+ ctxt_ctf = abigail::ctf_reader::create_read_context
+ (elf2.path, di_dirs2, env.get());
+ corpus2 = abigail::ctf_reader::read_corpus(ctxt_ctf.get(),
+ c2_status);
+ }
+ else
+#endif
+ {
+ ctxt_dwarf = create_read_context(elf2.path, di_dirs2, env.get(),
+ /*load_all_types=*/opts.show_all_types);
+ add_read_context_suppressions(*ctxt_dwarf, priv_types_supprs2);
- if (!opts.kabi_suppressions.empty())
- add_read_context_suppressions(*c, opts.kabi_suppressions);
+ if (!opts.kabi_suppressions.empty())
+ add_read_context_suppressions(*ctxt_dwarf, opts.kabi_suppressions);
- corpus2 = read_corpus_from_elf(*c, c2_status);
+ corpus2 = read_corpus_from_elf(*ctxt_dwarf, c2_status);
+ }
bool bail_out = false;
if (!(c2_status & abigail::elf_reader::STATUS_OK))
@@ -1443,7 +1491,13 @@ compare(const elf_file& elf1,
emit_prefix("abipkgdiff", cerr)
<< "Could not find alternate debug info file";
string alt_di_path;
- abigail::dwarf_reader::refers_to_alt_debug_info(*c, alt_di_path);
+#ifdef WITH_CTF
+ if (opts.use_ctf)
+ ;
+ else
+#endif
+ abigail::dwarf_reader::refers_to_alt_debug_info(*ctxt_dwarf,
+ alt_di_path);
if (!alt_di_path.empty())
cerr << ": " << alt_di_path << "\n";
else
@@ -1540,12 +1594,30 @@ compare_to_self(const elf_file& elf,
<< " ...\n";
corpus_sptr corp;
+#ifdef WITH_CTF
+ abigail::ctf_reader::read_context_sptr ctxt_ctf;
+#endif
+ read_context_sptr ctxt_dwarf;
{
- read_context_sptr c =
- create_read_context(elf.path, di_dirs, env.get(),
- /*read_all_types=*/opts.show_all_types);
+#ifdef WITH_CTF
+ if (opts.use_ctf)
+ {
+ ctxt_ctf = abigail::ctf_reader::create_read_context(elf.path,
+ di_dirs,
+ env.get());
+ ABG_ASSERT(ctxt_ctf);
+ corp = abigail::ctf_reader::read_corpus(ctxt_ctf.get(),
+ c_status);
+ }
+ else
+#endif
+ {
+ ctxt_dwarf =
+ create_read_context(elf.path, di_dirs, env.get(),
+ /*read_all_types=*/opts.show_all_types);
- corp = read_corpus_from_elf(*c, c_status);
+ corp = read_corpus_from_elf(*ctxt_dwarf, c_status);
+ }
if (!(c_status & abigail::elf_reader::STATUS_OK))
{
@@ -3332,6 +3404,10 @@ parse_command_line(int argc, char* argv[], options& opts)
(make_path_absolute(argv[j]).get());
++i;
}
+#ifdef WITH_CTF
+ else if (!strcmp(argv[i], "--ctf"))
+ opts.use_ctf = true;
+#endif
else if (!strcmp(argv[i], "--help")
|| !strcmp(argv[i], "-h"))
{