[v2,06/10] selftests/nolibc: make functions static if possible

Message ID 20230801-nolibc-warnings-v2-6-1ba5ca57bd9b@weissschuh.net
State New
Headers
Series tools/nolibc: enable compiler warnings |

Commit Message

Thomas Weißschuh Aug. 1, 2023, 5:30 a.m. UTC
  This allows the compiler to generate warnings if they go unused.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
 tools/testing/selftests/nolibc/nolibc-test.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)
  

Comments

Willy Tarreau Aug. 1, 2023, 6:52 a.m. UTC | #1
On Tue, Aug 01, 2023 at 07:30:13AM +0200, Thomas Weißschuh wrote:
> diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c
> index 1555759bb164..53a3773c7790 100644
> --- a/tools/testing/selftests/nolibc/nolibc-test.c
> +++ b/tools/testing/selftests/nolibc/nolibc-test.c
> @@ -80,7 +80,7 @@ char *itoa(int i)
>  /* returns the error name (e.g. "ENOENT") for common errors, "SUCCESS" for 0,
>   * or the decimal value for less common ones.
>   */
> -const char *errorname(int err)
> +static const char *errorname(int err)
>  {
>  	switch (err) {
>  	case 0: return "SUCCESS";

OK for this one, even desired for such a use case.

> @@ -593,7 +593,7 @@ int expect_strne(const char *expr, int llen, const char *cmp)
>  #define CASE_TEST(name) \
>  	case __LINE__: llen += printf("%d %s", test, #name);
>  
> -int run_startup(int min, int max)
> +static int run_startup(int min, int max)
>  {
>  	int test;
>  	int ret = 0;
> @@ -640,7 +640,7 @@ int run_startup(int min, int max)
>  
>  
>  /* used by some syscall tests below */
> -int test_getdents64(const char *dir)
> +static int test_getdents64(const char *dir)
>  {
>  	char buffer[4096];
>  	int fd, ret;
> @@ -734,7 +734,7 @@ static int test_stat_timestamps(void)
>  	return 0;
>  }
>  
> -int test_mmap_munmap(void)
> +static int test_mmap_munmap(void)
>  {
>  	int ret, fd, i;
>  	void *mem;
> @@ -796,7 +796,7 @@ int test_mmap_munmap(void)
>  /* Run syscall tests between IDs <min> and <max>.
>   * Return 0 on success, non-zero on failure.
>   */
> -int run_syscall(int min, int max)
> +static int run_syscall(int min, int max)
>  {
>  	struct timeval tv;
>  	struct timezone tz;
> @@ -907,7 +907,7 @@ int run_syscall(int min, int max)
>  	return ret;
>  }
>  
> -int run_stdlib(int min, int max)
> +static int run_stdlib(int min, int max)
>  {
>  	int test;
>  	int ret = 0;
> @@ -1141,7 +1141,7 @@ static int run_protection(int min, int max)
>  }
>  
>  /* prepare what needs to be prepared for pid 1 (stdio, /dev, /proc, etc) */
> -int prepare(void)
> +static int prepare(void)
>  {
>  	struct stat stat_buf;
>  
> @@ -1208,7 +1208,7 @@ static const struct test test_names[] = {
>  	{ 0 }
>  };
 
For these ones it will prevent gcc from putting breakpoints there, which
is counter-productive.

> -int is_setting_valid(char *test)
> +static int is_setting_valid(char *test)
>  {
>  	int idx, len, test_len, valid = 0;
>  	char delimiter;

OK for this one.

Willy
  
Thomas Weißschuh Aug. 1, 2023, 7:34 a.m. UTC | #2
On 2023-08-01 08:52:19+0200, Willy Tarreau wrote:
> On Tue, Aug 01, 2023 at 07:30:13AM +0200, Thomas Weißschuh wrote:
> > diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c
> > index 1555759bb164..53a3773c7790 100644
> > --- a/tools/testing/selftests/nolibc/nolibc-test.c
> > +++ b/tools/testing/selftests/nolibc/nolibc-test.c

> [..]

> >  /* prepare what needs to be prepared for pid 1 (stdio, /dev, /proc, etc) */
> > -int prepare(void)
> > +static int prepare(void)
> >  {
> >  	struct stat stat_buf;
> >  
> > @@ -1208,7 +1208,7 @@ static const struct test test_names[] = {
> >  	{ 0 }
> >  };
>  
> For these ones it will prevent gcc from putting breakpoints there, which
> is counter-productive.

Indeed.

An alternative would be to add -g to CFLAGS (and remove -s from LDFLAGS).
This way we get full debugability including breakpoints for everything.

I didn't find the reasoning for -s in LDFLAGS.

Thomas
  
Willy Tarreau Aug. 1, 2023, 8:13 a.m. UTC | #3
On Tue, Aug 01, 2023 at 09:34:18AM +0200, Thomas Weißschuh wrote:
> On 2023-08-01 08:52:19+0200, Willy Tarreau wrote:
> > On Tue, Aug 01, 2023 at 07:30:13AM +0200, Thomas Weißschuh wrote:
> > > diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c
> > > index 1555759bb164..53a3773c7790 100644
> > > --- a/tools/testing/selftests/nolibc/nolibc-test.c
> > > +++ b/tools/testing/selftests/nolibc/nolibc-test.c
> 
> > [..]
> 
> > >  /* prepare what needs to be prepared for pid 1 (stdio, /dev, /proc, etc) */
> > > -int prepare(void)
> > > +static int prepare(void)
> > >  {
> > >  	struct stat stat_buf;
> > >  
> > > @@ -1208,7 +1208,7 @@ static const struct test test_names[] = {
> > >  	{ 0 }
> > >  };
> >  
> > For these ones it will prevent gcc from putting breakpoints there, which
> > is counter-productive.
> 
> Indeed.
> 
> An alternative would be to add -g to CFLAGS (and remove -s from LDFLAGS).
> This way we get full debugability including breakpoints for everything.

It wouldn't change much because while it would allow the debugger to know
where the function was possibly inlined, it's still not very convenient:
you believe you're in a function but in fact you're in the caller. It
really depends what you're debugging but here I don't see all that as
providing a value, at least it brings more annoyance and little to no
gain IMHO.

> I didn't find the reasoning for -s in LDFLAGS.

It's historic, because normally when you want small binaries you strip
them, and the command line was reused as-is, but I agree that we could
get rid of it!

Willy
  
Thomas Weißschuh Aug. 1, 2023, 8:50 a.m. UTC | #4
On 2023-08-01 10:13:07+0200, Willy Tarreau wrote:
> On Tue, Aug 01, 2023 at 09:34:18AM +0200, Thomas Weißschuh wrote:
> > On 2023-08-01 08:52:19+0200, Willy Tarreau wrote:
> > > On Tue, Aug 01, 2023 at 07:30:13AM +0200, Thomas Weißschuh wrote:
> > > > diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c
> > > > index 1555759bb164..53a3773c7790 100644
> > > > --- a/tools/testing/selftests/nolibc/nolibc-test.c
> > > > +++ b/tools/testing/selftests/nolibc/nolibc-test.c
> > 
> > > [..]
> > 
> > > >  /* prepare what needs to be prepared for pid 1 (stdio, /dev, /proc, etc) */
> > > > -int prepare(void)
> > > > +static int prepare(void)
> > > >  {
> > > >  	struct stat stat_buf;
> > > >  
> > > > @@ -1208,7 +1208,7 @@ static const struct test test_names[] = {
> > > >  	{ 0 }
> > > >  };
> > >  
> > > For these ones it will prevent gcc from putting breakpoints there, which
> > > is counter-productive.
> > 
> > Indeed.
> > 
> > An alternative would be to add -g to CFLAGS (and remove -s from LDFLAGS).
> > This way we get full debugability including breakpoints for everything.
> 
> It wouldn't change much because while it would allow the debugger to know
> where the function was possibly inlined, it's still not very convenient:
> you believe you're in a function but in fact you're in the caller. It
> really depends what you're debugging but here I don't see all that as
> providing a value, at least it brings more annoyance and little to no
> gain IMHO.

Even if it doesn't work 100% properly it wouldn't it still be a superset
of the previous functionality?
And we don't have to manually keep track of which ones should be static
and which shouldn't (See this discussion).

Would it be better with -ggdb?

If you are still not conviced I'll drop the argument here :-)
(And the changes in the next revision)

> > I didn't find the reasoning for -s in LDFLAGS.
> 
> It's historic, because normally when you want small binaries you strip
> them, and the command line was reused as-is, but I agree that we could
> get rid of it!

I'll remove it. It was annoying to figure out why my "-g" CFLAG didn't
work at all.

Thomas
  
Willy Tarreau Aug. 1, 2023, 9:13 a.m. UTC | #5
On Tue, Aug 01, 2023 at 10:50:05AM +0200, Thomas Weißschuh wrote:
> > > An alternative would be to add -g to CFLAGS (and remove -s from LDFLAGS).
> > > This way we get full debugability including breakpoints for everything.
> > 
> > It wouldn't change much because while it would allow the debugger to know
> > where the function was possibly inlined, it's still not very convenient:
> > you believe you're in a function but in fact you're in the caller. It
> > really depends what you're debugging but here I don't see all that as
> > providing a value, at least it brings more annoyance and little to no
> > gain IMHO.
> 
> Even if it doesn't work 100% properly it wouldn't it still be a superset
> of the previous functionality?

No, we need to be able to disassemble this to understand what was done
to the code we believe is being tested. All of us have been dealing with
this already, and making that code less mappable from asm to C is quite
annoying.

> And we don't have to manually keep track of which ones should be static
> and which shouldn't (See this discussion).

We should not have to be concerned about this, because it's out of the
scope of what this "program" is used for. If we're wondering too much,
we're wasting our time on the wrong topic. So we have to find a reasonable
rule. One that sounds fine to me is to say:
  - all that's part of the framework to help with testing (i.e. the expect
    functions, errorname()  etc) could be static because we don't really
    care about them (at least we won't be placing breakpoints there). They
    may be marked inline or unused and we can be done with them.

  - user code and the calling stack from main should be easily traceable
    using gdb and objdump -dr so that when you start with a new arch and
    it breaks early (as happens by definition when syscalls or crt code
    don't all work well) then it's possible to accurately trace it without
    having to worry too much about what was transformed how.

> Would it be better with -ggdb?

It doesn't change. The thing is: by saying "static" you tell the
compiler "I promise it cannot be used anywhere else, do what you want
with it", and it can trivially decide to inline all or part of it, or
change its number of arguments or whatever as it sees fit because no
other code part relies on that function. And when you're trying to
disassemble your test_mmap_munmap() and can't find it and can only
infer its inlined presence in run_syscall() by seeing a value in a
register that vaguely reminds you about __NR_mmap, it's clearly much
less easy.

> If you are still not conviced I'll drop the argument here :-)
> (And the changes in the next revision)

No problem, it's fine to discuss the current situation. I've just
noticed a number of static on some test functions that would deserve
being removed precisely for the reasons above. But that justifies the
need for some doc about all this.

> > > I didn't find the reasoning for -s in LDFLAGS.
> > 
> > It's historic, because normally when you want small binaries you strip
> > them, and the command line was reused as-is, but I agree that we could
> > get rid of it!
> 
> I'll remove it. It was annoying to figure out why my "-g" CFLAG didn't
> work at all.

Yes I can definitely understand!

Thanks,
Willy
  

Patch

diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c
index 1555759bb164..53a3773c7790 100644
--- a/tools/testing/selftests/nolibc/nolibc-test.c
+++ b/tools/testing/selftests/nolibc/nolibc-test.c
@@ -80,7 +80,7 @@  char *itoa(int i)
 /* returns the error name (e.g. "ENOENT") for common errors, "SUCCESS" for 0,
  * or the decimal value for less common ones.
  */
-const char *errorname(int err)
+static const char *errorname(int err)
 {
 	switch (err) {
 	case 0: return "SUCCESS";
@@ -593,7 +593,7 @@  int expect_strne(const char *expr, int llen, const char *cmp)
 #define CASE_TEST(name) \
 	case __LINE__: llen += printf("%d %s", test, #name);
 
-int run_startup(int min, int max)
+static int run_startup(int min, int max)
 {
 	int test;
 	int ret = 0;
@@ -640,7 +640,7 @@  int run_startup(int min, int max)
 
 
 /* used by some syscall tests below */
-int test_getdents64(const char *dir)
+static int test_getdents64(const char *dir)
 {
 	char buffer[4096];
 	int fd, ret;
@@ -734,7 +734,7 @@  static int test_stat_timestamps(void)
 	return 0;
 }
 
-int test_mmap_munmap(void)
+static int test_mmap_munmap(void)
 {
 	int ret, fd, i;
 	void *mem;
@@ -796,7 +796,7 @@  int test_mmap_munmap(void)
 /* Run syscall tests between IDs <min> and <max>.
  * Return 0 on success, non-zero on failure.
  */
-int run_syscall(int min, int max)
+static int run_syscall(int min, int max)
 {
 	struct timeval tv;
 	struct timezone tz;
@@ -907,7 +907,7 @@  int run_syscall(int min, int max)
 	return ret;
 }
 
-int run_stdlib(int min, int max)
+static int run_stdlib(int min, int max)
 {
 	int test;
 	int ret = 0;
@@ -1141,7 +1141,7 @@  static int run_protection(int min, int max)
 }
 
 /* prepare what needs to be prepared for pid 1 (stdio, /dev, /proc, etc) */
-int prepare(void)
+static int prepare(void)
 {
 	struct stat stat_buf;
 
@@ -1208,7 +1208,7 @@  static const struct test test_names[] = {
 	{ 0 }
 };
 
-int is_setting_valid(char *test)
+static int is_setting_valid(char *test)
 {
 	int idx, len, test_len, valid = 0;
 	char delimiter;