[Bug 211152] benchmarks/iozone: Build fails on typedef redefinition with different types ('long long' vs '__off64_t' (aka 'long'))

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Sun Jul 17 00:58:52 UTC 2016


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=211152

--- Comment #11 from Mark Millard <markmi at dsl-only.net> ---
(In reply to w.schwarzenfeld from comment #10)

I do not have a FreeBSD 10.x or earlier context to check. So I've not tested if
the "delete line" issue is 11.0+ specific or not. My guess is that it is not.
So the version test may be wrong.

The following would cause the Makefile to be very fragile relative to iozone.c
updates: nothing checks that the correct line is being deleted or reports when
things have likely changed. It is now commented for the issue but. . .

.if ${OPSYS} == FreeBSD && ${OSVERSION} >= 1100000
        @${REINPLACE_CMD} -e '363d' ${WRKSRC}/iozone.c
.endif

usually C source code checks its own context via macro tests. Why adjust the
Makefile instead of iozone.c itself?

Looking around shows iozone has no explicit support for 64-bit for freebsd:

/usr/ports/benchmarks/iozone/Makefile has:

MAKEFILE=       makefile
MAKE_ARGS=      ${MAKE_ENV}
ALL_TARGET=     freebsd

which uses:

. . ./iozone3_434/src/current/makefile

# grep -i freebsd
/usr/obj/portswork/usr/ports/benchmarks/iozone/work/iozone3_434/src/current/makefile
#               convex, FreeBSD, OpenBSD, OSFV3, OSFV4, OSFV5, SCO
        @echo "        ->   freebsd              (32bit)   <-"
# GNU C compiler FreeBSD build with no threads, no largefiles, no async I/O
freebsd:        iozone_freebsd.o libbif.o fileop_freebsd.o libasync.o
pit_server.o
        $(CC) $(LDFLAGS) iozone_freebsd.o libbif.o -lpthread libasync.o \
        $(CC)  -O fileop_freebsd.o -o fileop
fileop_freebsd.o:       fileop.c
        @echo "Building fileop for FreeBSD"
        $(CC) -c -O $(CFLAGS) fileop.c -o fileop_freebsd.o
iozone_freebsd.o:       iozone.c libbif.c libasync.c
        @echo "Build iozone for FreeBSD"
        $(CC) -c ${CFLAGS}  -DFreeBSD -Dunix -Dbsd4_4 -DHAVE_ANSIC_C -DASYNC_IO
\
                -DHAVE_PREAD -DNAME='"freebsd"' -DSHARED_MEM \
                $(CFLAGS) iozone.c -o iozone_freebsd.o
        $(CC) -c ${CFLAGS} -DFreeBSD -Dunix -Dbsd4_4 -DHAVE_ANSIC_C -DASYNC_IO
\
        $(CC) -c ${CFLAGS} -DFreeBSD -Dunix -Dbsd4_4 -DHAVE_ANSIC_C -DASYNC_IO
\

The the types that should be involved likely change for:

TARGET_ARCH=amd64 or powerpc64 or aarch64
vs.
TARGET_ARCH=i386 or powerpc or armv6

(not a comprehensive list).

So LP64 vs. ILP32, little endian vs. big endian, possibly alignment. FreeBSD
has a wide range. (I currently have access only to examples of amd64 and
armv6.)

Looking around NO_PRINT_LLD is not defined for freebsd:

# grep -i NO_PRINT_
/usr/obj/portswork/usr/ports/benchmarks/iozone/work/iozone3_434/src/current/makefile
                -DNAME='"OSFV3"' -DNO_PRINT_LLD -DOSF_64 $(CFLAGS) iozone.c \
                -DNO_PRINT_LLD  -DOSF_64 $(CFLAGS) libbif.c -o libbif.o
                -DNO_PRINT_LLD -DOSF_64 $(CFLAGS) libasync.c -o libasync.o
                -DNAME='"OSFV4"' -DNO_PRINT_LLD -DOSF_64 $(CFLAGS) iozone.c \
                -DNO_PRINT_LLD  -DOSF_64 $(CFLAGS) libbif.c -o libbif.o
                -DNO_PRINT_LLD -DOSF_64 $(CFLAGS) libasync.c -o libasync.o
                -DNAME='"OSFV5"' -DNO_PRINT_LLD -DOSF_64 $(CFLAGS) iozone.c \
                -DNO_PRINT_LLD  -DOSF_64 $(CFLAGS) libbif.c -o libbif.o
                -DNO_PRINT_LLD -DOSF_64 $(CFLAGS) libasync.c -o libasync.o
                -DNAME='"TRU64"' -DNO_PRINT_LLD -DOSF_64 -pthread $(CFLAGS)
iozone.c \
                -DNO_PRINT_LLD  -DOSF_64 $(CFLAGS) libbif.c -o libbif.o
                -DNO_PRINT_LLD -DOSF_64 $(CFLAGS) libasync.c -o libasync.o

So only OSF_64 variants involve NO_PRINT_LLD being defined. So it appears a
bunch of changes are irrelevant to FreeBSD but might be important for
non-FreeBSD. I've not tried anything under non-FreeBSD.

Ignoring that for the moment relative to FreeBSD, take the example:

 #ifdef NO_PRINT_LLD
-                       sscanf(optarg,"%ld",&kilobytes64);
+                       sscanf(optarg,"%ld",(long long *)&kilobytes64);

%ld is not a long long format. It is a long int format. For ILP32 contexts long
int and long long are not sized the same. There may not be examples yet but for
LP64 long long could be more than 64-bits instead of matching long int's size.

Changing the type of the pointer where the value is to be stored is generally
dangerous. The format must match the actual storage layout involved (including
size, alignment). Mismatched type sizes between the format and the storage can
get into endianness handling problems (format too small for the storage),
truncation problems (format too small for the storage), memory overwrite
problems (format too big for the storage). There could be alignment issues as
well.

For the variations of scan: Having "full/larger-than-needed width" in the
target type locally and then validating the values would fit in the desired
final storage and then converting if things are okay would be more generic to
variations like LP64 vs. IPL32 and such.

As for the printf variations:

+ #ifdef NO_PRINT_LLD
+-                      sprintf(splash[splash_line++],"\tUsing minimum file
size of %ld kilobytes.\n",minimum_file_size);
++                      sprintf(splash[splash_line++],"\tUsing minimum file
size of %ld (long long)kilobytes.\n",minimum_file_size);

This example added a "(long long)" to the string text. Why?

+ #ifdef NO_PRINT_LLD
+-                      sprintf(splash[splash_line++],"\tFile size set to %ld
kB\n",kilobytes64);
++                      sprintf(splash[splash_line++],"\tFile size set to %ld
kB\n",(long long )kilobytes64);

%ld is not a long long format. It is a long int format. For ILP32 contexts long
int and long long are not sized the same. There may not be examples yet but for
LP64 long long could be more than 64-bits instead of matching long int's size.

Incorrect value displays can happen when formats to not match storage layouts.
Endianness handling problems (format too small for the storage), truncation
problems (format too small for the storage), memory access problems (format too
big for the storage). There could be alignment issues as well.


It appears to me the the scan code with %lld (a long long format) might also
have some of these sorts of issues for various TARGET_ARCH's. The prints with
%lld and a matching (long long) cast for the value likely survive until long or
int happens to be be bigger than 64 bits.

(I've not looked for signed vs. unsigned issues.)

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the freebsd-ports-bugs mailing list