Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 9 Sep 2016 15:27:02 +1000 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Justin Hibbits <jhibbits@freebsd.org>
Cc:        src-committers@freebsd.org, svn-src-all@freebsd.org,  svn-src-head@freebsd.org
Subject:   Re: svn commit: r305636 - head/sys/ddb
Message-ID:  <20160909142012.W864@besplex.bde.org>
In-Reply-To: <201609090416.u894GriK087316@repo.freebsd.org>
References:  <201609090416.u894GriK087316@repo.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, 9 Sep 2016, Justin Hibbits wrote:

> Log:
>  Correct the type of db_cmd_loop_done.
>
>  On big endian hardware that uses 1 byte bool a type mismatch of bool vs int will
>  cause the least signifcant byte of db_cmd_loop_done to be set, but the MSB to be
>  read, and read as 0.  This causes ddb to stay in an infinite loop.

Hrmph.  I objected to converting ddb to bool.

> Modified: head/sys/ddb/db_command.c
> ==============================================================================
> --- head/sys/ddb/db_command.c	Fri Sep  9 02:02:13 2016	(r305635)
> +++ head/sys/ddb/db_command.c	Fri Sep  9 04:16:53 2016	(r305636)
> @@ -59,7 +59,7 @@ __FBSDID("$FreeBSD$");
> /*
>  * Exported global variables
>  */
> -bool		db_cmd_loop_done;
> +int		db_cmd_loop_done;
> db_addr_t	db_dot;
> db_addr_t	db_last_addr;
> db_addr_t	db_prev;

It used to use boolean_t, but was misinitialized with 0 and 1 instead of
FALSE and TRUE.  Then it used bool, but was misinitialized with 0 and 1
instead of false and true.  Now it is initialized with matching types
for the literals, but its type regressed 2 steps.

But what was the problem?  (int)1 (or any nonzero value) is converted
to (bool)true on assigment.  The final value is always 1 if converted
back to an int, and probably also when viewed as bits in memory.  When
bool has 8 bits big endian, this means that it has bits 0b00000001
where you can't really know the bit order within a byte.

The bugs were actually that:
- this variable was not declared in a header file, first as boolean_t,
   then as bool
- it was misdeclared as 'extern int' in db_run.c.  This accidentally
   matched boolean_t, but not bool
- conversion to bool in 1 place gave a type mismatch.  This might have
   caused memory overruns on all systems, but the bug was more obvious
   on big-endian systems.

On i386, I get the variable addresses:

...
c0bc8288 B db_dot
c0bc828c B db_last_addr
c0bc8290 B db_prev
c0bc8294 B db_next
c0bc8298 B db_cmd_loop_done
c0bc829c b db_last_command
c0bc82a0 b escstate.4091
c0bc82a4 b db_lbuf_start
c0bc82a8 b db_lbuf_end
...

when compiled by gcc-4.2.1 (gcc-4.2.1 generates the same '.comm xxx,1,1'
directive as clang, as required by the ABI.

The variable is pessimized for both space and time (one reason I don't
like to use compiler bool).  The ABI specifies packing to 8 bits but
not to 1 bit and not expansion to 32 bits.  The linker expands it to 32
bits anyway, but the compiler doesn't know this so it has to use slightly
larger and slower instructions to use it.

Compilers do OK for bools in static functions, but for public functions
they don't even trust the ABI, and on x86 do 2 extra movzbl (register)
instructions and a few extra loads and stores to do null conversions
of bools in each of the caller and callee in code like 'extern bool
b(bool); bool q(bool r) { return (b(r)); }'.

These extra instructions fix some bool-int mismatches on little-endian
systems only.  Loading 32 bits from db_cmd_loop_done might give garbage
in the top bits if the top bits are actually for another variable, but
zero-extending the low bits fixes this (a 32-bit store would clobber
the other variable).  But in the big-endian case, it would be the
garbage top bits that are zero-extended.  It is impossible to determine
where the low bits are so as to adjust, starting from the incorrect type.
This is perhaps the main disadvantage of big-endian format.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20160909142012.W864>