dc hitting a compiler bug, or undefined behavior

2014-03-30 Thread Lauri Kasanen
Hi,

I'm seeing busybox dc acting funny when compiled with some versions of
gcc. This is on busybox git. The x86 binary busybox_unstripped and
config are attached.

gcc 4.2.2 - ok
gcc 4.7.2:
nc 10 1 add p
2.738e+93

So either bb is hitting a compiler bug, or undefined behavior somewhere
with new gcc's more aggressive optimizations.

- Lauri

-- 
http://www.fastmail.fm - Email service worth paying for. Try it for free



busybox_unstripped.gz
Description: GNU Zip compressed data


bb-config.gz
Description: GNU Zip compressed data
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

Re: dc hitting a compiler bug, or undefined behavior

2014-03-30 Thread Ralf Friedl

Lauri Kasanen wrote:

I'm seeing busybox dc acting funny when compiled with some versions of
gcc. This is on busybox git. The x86 binary busybox_unstripped and
config are attached.

gcc 4.2.2 - ok
gcc 4.7.2:
nc 10 1 add p
2.738e+93

So either bb is hitting a compiler bug, or undefined behavior somewhere
with new gcc's more aggressive optimizations.
I have 4.7.2 on x86 and I get 11 as output. You could add debug output 
to push and pop to see what happens.


Whether the output 11 is to be expected is another question:
$ dc --version
dc (GNU bc 1.06.95) 1.3.95
$ dc --help
Usage: dc [OPTION] [file ...]
  -e, --expression=EXPRevaluate expression
  -f, --file=FILE  evaluate contents of file
  -h, --help   display this help and exit
  -V, --versionoutput version information and exit
$ dc 10 1 add p
dc: Could not open file 10
dc: Could not open file 1
dc: Could not open file add
dc: Could not open file p
$ dc -e '10 1 add p'

$ dc -e '10 1 + p'
11

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: dc hitting a compiler bug, or undefined behavior

2014-03-30 Thread Lauri Kasanen
On Sun, Mar 30, 2014, at 15:05, Ralf Friedl wrote:
  I'm seeing busybox dc acting funny when compiled with some versions of
  gcc. This is on busybox git. The x86 binary busybox_unstripped and
  config are attached.
 
  gcc 4.2.2 - ok
  gcc 4.7.2:
  nc 10 1 add p
  2.738e+93
 
  So either bb is hitting a compiler bug, or undefined behavior somewhere
  with new gcc's more aggressive optimizations.

 I have 4.7.2 on x86 and I get 11 as output. You could add debug output 
 to push and pop to see what happens.

I think it's related to 
http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
which hit the radeon driver as well
http://lists.freedesktop.org/archives/dri-devel/2013-August/044122.html

but changing the stack[1] to stack[0], stack[], or even stack[10] did
not fix the issue.

What's even worse is that adding any output to push(), even a puts(hi)
that does not print the argument or any of the stack vars, fixes it. So
something magic is going on inside the GCC optimization, I'm afraid this
is above my pay grade.

FWIW printf calls in pop() or any other functions did not affect the
calculation. push() is being given the correct argument after strtod.

- Lauri

-- 
http://www.fastmail.fm - The way an email service should be

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: dc hitting a compiler bug, or undefined behavior

2014-03-30 Thread Ralf Friedl

Lauri Kasanen schrieb:

On Sun, Mar 30, 2014, at 15:05, Ralf Friedl wrote:

I'm seeing busybox dc acting funny when compiled with some versions of
gcc. This is on busybox git. The x86 binary busybox_unstripped and
config are attached.

gcc 4.2.2 - ok
gcc 4.7.2:
nc 10 1 add p
2.738e+93

So either bb is hitting a compiler bug, or undefined behavior somewhere
with new gcc's more aggressive optimizations.

I have 4.7.2 on x86 and I get 11 as output. You could add debug output
to push and pop to see what happens.

I think it's related to
http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
which hit the radeon driver as well
http://lists.freedesktop.org/archives/dri-devel/2013-August/044122.html

but changing the stack[1] to stack[0], stack[], or even stack[10] did
not fix the issue.

If the change didn't fix it, then maybe it's not related to that.


What's even worse is that adding any output to push(), even a puts(hi)
that does not print the argument or any of the stack vars, fixes it. So
something magic is going on inside the GCC optimization, I'm afraid this
is above my pay grade.
Could you send the file miscutils/dc.o that is created with and without 
this puts(hi) in push()?

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: dc hitting a compiler bug, or undefined behavior

2014-03-30 Thread Lauri Kasanen
On Sun, Mar 30, 2014, at 18:26, Ralf Friedl wrote:
  What's even worse is that adding any output to push(), even a puts(hi)
  that does not print the argument or any of the stack vars, fixes it. So
  something magic is going on inside the GCC optimization, I'm afraid this
  is above my pay grade.

 Could you send the file miscutils/dc.o that is created with and without 
 this puts(hi) in push()?

Attached.

- Lauri

-- 
http://www.fastmail.fm - Email service worth paying for. Try it for free



fail-dc.o.gz
Description: GNU Zip compressed data


success-dc.o.gz
Description: GNU Zip compressed data
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

[PATCH v1] Size reduction, cleanup, fixes, improvements for swapon/swapoff

2014-03-30 Thread Tito
Hi to all,
this patch started as a personal fun and learning project on swapon/swapoff 
after
Matt Whitlock's patches. I was curios if there was a way to remove all the 
#ifdefs
from within the code as for my personal taste this unindented stuff in indented
code makes the code harder to read.
So I tried hard by using the preprocessor and compilers dead code elimination
and in the end I was able to achieve my goal: a ifdef free code.
During the process as side effects I spotted a few differences between
our swapon/swapoff inplementation and the one on my debian box
so I added this fixes/improvements to the code:

1)  real swapon/swapoff handles also devices on the commandline with -a;
2)  xstat(device)  in  swap_enable_disable aborts on error when cycling through
 fstab so some devices  are not handled;
3) duplicated code for ENABLE_FEATURE_SWAPON_DISCARD and
ENABLE_FEATURE_SWAPON_PRI was moved to functions.
4) silence some error messages with -a;
5) minor cleanups and code refactoring reduced the size as per bloat-check:

./scripts/bloat-o-meter busybox_unstripped.old busybox_unstripped
function old new   delta
set_discard_flag   - 106+106
set_priority_flag  -  75 +75
swap_enable_disable  149 219 +70
.rodata   141270  141260 -10
swap_on_off_main 638 325-313
--
(add/remove: 2/0 grow/shrink: 1/2 up/down: 251/-323)  Total: -72 bytes

6) I also added support for /proc/swaps handling to swapoff: 

When the -a flag is given, swapping is disabled on all known  swap  devices
 and  files  (as  found  in  /proc/swaps  or /etc/fstab).

So now swapoff first cycles through  /proc/swaps and then through fstab
to swapoff all devices. 
With this additional feature bloat-check is:

./scripts/bloat-o-meter busybox_unstripped.old busybox_unstripped
function old new   delta
set_discard_flag   - 106+106
set_priority_flag  -  75 +75
swap_enable_disable  149 219 +70
.rodata   141270  141272  +2
swap_on_off_main 638 416-222
--
(add/remove: 2/0 grow/shrink: 2/1 up/down: 253/-222)   Total: 31 bytes

so it comes at almost no extra size cost.
I've decided not to add an extra config option for that, but it could
be  easily added if needed.

7) Something I'm forgettin...;

Sadly I cannot provide a patch series for the different changes but
only a allinone patch, therefore I also attach a drop-in replacement
file for swaponoff.c for review and testing by the list members.
I've tested it a little on my box with a few test cases I could think of,
but more testing is needed as there is a lot of code changed and bugs
can creep in.
Hint, critics and improvements are welcome.

Ciao,
Tito

Swapon/swapoff fixes, enhacements and size reduction:

1)  real swapon/swapoff handles also devices on the commandline with -a;
2)  xstat(device)  in  swap_enable_disable aborts on error when cycling through
fstab so some devices  are not handled;
3)  duplicated code for ENABLE_FEATURE_SWAPON_DISCARD and
ENABLE_FEATURE_SWAPON_PRI was moved to functions.
4)  silence some error messages with -a;
5)  minor cleanups and code refactoring to reduce binary size.
6)  added support for /proc/swaps handling to swapoff.

Signed-off by Tito Ragusa farmat...@tiscali.it

--- util-linux/swaponoff.c.orig	2014-03-26 07:46:29.263718690 +0100
+++ util-linux/swaponoff.c	2014-03-30 21:49:11.642492640 +0200
@@ -63,90 +63,142 @@
 } FIX_ALIASING;
 #define G (*(struct globals*)bb_common_bufsiz1)
 #define g_flags (G.flags)
+#define save_g_flags()  int save_g_flags = g_flags
+#define restore_g_flags() g_flags = save_g_flags
 #else
 #define g_flags 0
+#define save_g_flags()((void)0)
+#define restore_g_flags() ((void)0)
 #endif
 #define INIT_G() do { } while (0)
 
+#define do_swapoff   (applet_name[5] == 'f')
+
+/* Command line options */
+enum {
+	OPTBIT_a,  /* -a all  */
+	IF_FEATURE_SWAPON_DISCARD( OPTBIT_d ,) /* -d discard  */
+	IF_FEATURE_SWAPON_PRI( OPTBIT_p ,) /* -p priority */
+	OPT_a = 1  OPTBIT_a,
+	OPT_d = IF_FEATURE_SWAPON_DISCARD((1  OPTBIT_d)) + 0,
+	OPT_p = IF_FEATURE_SWAPON_PRI((1  OPTBIT_p)) + 0,
+};
+
+#define OPT_ALL (option_mask32  OPT_a)
+#define OPT_DISCARD (option_mask32  OPT_d)
+#define OPT_PRIO(option_mask32  OPT_p)
+
 static int swap_enable_disable(char *device)
 

[PATCH] Avoid double argument evaluation in MIN and MAX macros

2014-03-30 Thread Bartosz Golaszewski
Commit c3a27b0b fixes a double argument evaluation by modifying the
macro invocation. What about preventing it on macro definition level?

Signed-off-by: Bartosz Golaszewski bartekg...@gmail.com
---
 include/libbb.h| 22 +++---
 util-linux/swaponoff.c |  5 ++---
 2 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/include/libbb.h b/include/libbb.h
index 1cbe2c8..db75641 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -265,13 +265,21 @@ struct BUG_off_t_size_is_misdetected {
 #define SKIP   ((int) 2)
 
 /* Macros for min/max.  */
-#ifndef MIN
-#define MIN(a,b) (((a)(b))?(a):(b))
-#endif
-
-#ifndef MAX
-#define MAX(a,b) (((a)(b))?(a):(b))
-#endif
+#undef MIN
+#define MIN(a,b) \
+   ({ \
+   __typeof__(a) _a = (a); \
+   __typeof__(b) _b = (b); \
+   _a  _b ? _a : _b; \
+   })
+
+#undef MAX
+#define MAX(a,b) \
+   ({ \
+   __typeof__(a) _a = (a); \
+   __typeof__(b) _b = (b); \
+   _a  _b ? _a : _b; \
+   })
 
 /* buffer allocation schemes */
 #if ENABLE_FEATURE_BUFFERS_GO_ON_STACK
diff --git a/util-linux/swaponoff.c b/util-linux/swaponoff.c
index a7ad6db..b3d265f 100644
--- a/util-linux/swaponoff.c
+++ b/util-linux/swaponoff.c
@@ -137,11 +137,10 @@ static int do_em_all(void)
p = hasmntopt(m, pri);
if (p) {
/* Max allowed 32767 (== 
SWAP_FLAG_PRIO_MASK) */
-   unsigned prio = bb_strtou(p + 4, NULL, 
10);
+   unsigned prio = MIN(bb_strtou(p + 4, 
NULL, 10), SWAP_FLAG_PRIO_MASK);
/* We want to allow ,foo, thus 
errno == EINVAL is allowed too */
if (errno != ERANGE) {
-   g_flags = (g_flags  
~SWAP_FLAG_PRIO_MASK) | SWAP_FLAG_PREFER |
-   MIN(prio, 
SWAP_FLAG_PRIO_MASK);
+   g_flags = (g_flags  
~SWAP_FLAG_PRIO_MASK) | SWAP_FLAG_PREFER | prio;
}
}
 #endif
-- 
1.8.4.5

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: dc hitting a compiler bug, or undefined behavior

2014-03-30 Thread Ralf Friedl

Lauri Kasanen wrote:

On Sun, Mar 30, 2014, at 18:26, Ralf Friedl wrote:

What's even worse is that adding any output to push(), even a puts(hi)
that does not print the argument or any of the stack vars, fixes it. So
something magic is going on inside the GCC optimization, I'm afraid this
is above my pay grade.

Could you send the file miscutils/dc.o that is created with and without
this puts(hi) in push()?

Attached.
Are you using some special compiler options, especially regarding 
parameter passing in registers and stack alignment?


The relevant part of fail-dc.o is this:
 push:
   0:   dd 07   fldl   (%edi)
The function expects the value to push at the address pointed to by 
%edi. But the functions that call push pass the value at the top of the 
CPU stack (not to be confused with the stack dc implements).


The relevant part ofsuccess-dc.o is this:
 push:
   0:   57  push   %edi
   1:   8d 7c 24 08 lea0x8(%esp),%edi
   5:   83 e4 f0and$0xfff0,%esp
   8:   ff 77 fcpushl  -0x4(%edi)
   b:   55  push   %ebp
   c:   89 e5   mov%esp,%ebp
   e:   57  push   %edi
   f:   83 ec 14sub$0x14,%esp
  12:   dd 07   fldl   (%edi)
These lines set up an aligned stack.
0: save %edi
1: put address of top of stack at the time the function was called in 
%edi. This is the address of the parameter.

5: align stack to 0x10 boundary
8: push return address of the function
b, c: normal frame setup
e: save %edi for later use
f: make space for a double and align to 0x10
12: load parameter, %edi still points to the address of the parameter.

The instruction at 12 loads the double from address %edi after %edi has 
been set to point to the parameter area. The instruction at 0 in the 
failed case is exactly the same, except that %edi has not been setup 
before. So I would consider this a compiler bug.


I wrote that the instruction at f makes space for an aligned double. 
This is itself is strange because later on the double that is loaded 
from %edi is saved on the CPU stack and later loaded from the CPU stack 
and saved in the dc stack, which is unnecessary. Also the double is 
always loaded to the FPU stack and then removed if bb_error_msg_and_die 
is called, instead of loading it only after it is clear that it will be 
used. So there is also opportunity for further optimization of the compiler.


This stack alignment makes your code bigger, and the additional 
instructions also have to be executed, which also takes time. I'm not 
sure whether the aligned stack saves enough time to offset this.

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox