George Koehler <kern...@gmail.com> writes:

> On Wed, 23 Feb 2022 00:08:34 +0100
> Omar Polo <o...@openbsd.org> wrote:
>
>> I think I've finally solved it.  The problem is that contrib/sb-capstone
>> hardcodes some values from capstone.h so lisp can call the C functions.
>> This "transcription" however is not accurate and worked until now by
>> pure chance on 64 bit arches due to how arguments are passed and struct
>> padding, pure luck!
>
> I tried to patch capstone.lisp but didn't fix my build.  Your patch
> looks better, but I haven't built it.  I have comments below.
>
> The build deletes every *.orig and breaks "make update-patches", so
> I started using "PATCHORIG= .orig.port".  Joshua Elsasser, as the
> maintainer, do you have an opinion about PATCHORIG?
>
> Go down for patch comments.
>
>> [...]
>> Index: patches/patch-contrib_sb-capstone_capstone_lisp
>> ===================================================================
>> RCS file: patches/patch-contrib_sb-capstone_capstone_lisp
>> diff -N patches/patch-contrib_sb-capstone_capstone_lisp
>> --- /dev/null        1 Jan 1970 00:00:00 -0000
>> +++ patches/patch-contrib_sb-capstone_capstone_lisp  22 Feb 2022 23:07:25 
>> -0000
>> @@ -0,0 +1,26 @@
>> +$OpenBSD$
>> +
>> +sync a couple of size mismatches with capstone.h; fixes the build on
>> +32bit arches (i386, powerpc.)
>> +
>> +Index: contrib/sb-capstone/capstone.lisp
>> +--- contrib/sb-capstone/capstone.lisp.orig
>> ++++ contrib/sb-capstone/capstone.lisp
>> +@@ -285,7 +285,7 @@
>> + (define-alien-type cs-insn
>> +     (struct nil
>> +             (insn-id int)
>> +-            (insn-addr unsigned)
>> ++            (insn-addr (integer 64))
>> +             (insn-size short)
>> +             (insn-bytes (array char 16))
>> +             (insn-mnemonic (array char 32))
>
> I guess that it should be (insn-addr (unsigned 64)), to match the
> capstone.h's struct cs_insn's uint64_t address.

agreed, sorry for the typo, i meant unsigned

> I have not called C from Lisp before now, so sb-alien confused me.
> I now believe that "integer" and "unsigned" have pointer size, but
> "int" and "unsigned-int" have 32 bits.  So "unsigned" had 64 bits
> on amd64, or 32 bits on i386|powerpc.

I've yet to find a list of types and their counterpart in C in the sbcl
documentation, I'm only finding stuff for sb-groveler which uses
sb-alien.  Anyway, I *think* that `integer' and `unsigned' should mirror
their C counterpart (int and unsigned int), so 32 bit on amd64, i386 and
powerpc.

http://www.lichteblau.com/sbcl/doc/manual/sbcl/Foreign-Type-Specifiers.html

My (unconfirmed) guess is that on amd64 the compiler aligns the short at
64 bit boundaries and so there are 32 bits of padding between ins-addr
and ins-size, which makes the difference between `unsigned' and (integer
64) not noticeable for small values -- at least on LE.  test.lisp uses
small chunks that output only a few bytes so the truncation due to the
wrong size went unseen.  Testing on a 64bit BE arch would have
discovered this issue too probably.

>> +@@ -310,7 +310,7 @@
>> + 
>> + ;; The handle returned by cs-open will be represented as being of type 
>> unsigned
>> + 
>> +-(define-alien-routine cs-open int (arch int) (mode (integer 64)) (handle 
>> unsigned :out))
>> ++(define-alien-routine cs-open int (arch int) (mode unsigned) (handle 
>> unsigned :out))
>> + 
>> + (define-alien-routine cs-version unsigned (major int :out) (minor int 
>> :out))
>> + 
>
> cs-open should have "(mode int)".  <capstone.h> has "cs_mode mode" and
> powerpc clang says that "(cs_mode)-1 > 0" is false, implying that
> cs_mode is a signed type.

(i forgot to explain this in the previous mail, sorry)

That was my first thought as well, but the third test fails if `mode' is
`int':

Test SB-CAPSTONE-TESTS::PPC-BIG-ENDIAN failed
Form: (SB-CAPSTONE-TESTS::CAPSTONE-CHECK '(124 8 2 166) '(:PPC64 :BIG-ENDIAN)
                                         '("MFLR R0"))
Expected value: T
Actual value: #<TYPE-ERROR expected-type: (SIGNED-BYTE 32) datum: 2147483656>.
The value
  2147483656
is not of type
  (SIGNED-BYTE 32)

my reading is that capstone.lisp:get-cs-mode tries to set the most
significant bit which is fine in C but sbcl begs to differ.  (2147483656
is actually -2147483640 in base 2 complement if I'm doing the math
right, or 0x80000008)

This probably explain why upstream went for (integer 64), sbcl doesn't
warn and the value is still correctly passed to and read by the library
on amd64 (don't know the details of the calling convention but I guess
32 and 64 bits integers are passed on registers.)

> I also think that cs-version should return "unsigned-int" (32 bits),
> not "unsigned" (64 bits on amd64), though I suspect that amd64
> tolerates the wrong size.

It's true that the wrong size is tolerated but I think that `unsigned'
mirrors C' `unsigned int', so it's already correct?

> --George

Updated diff below with the type fixed for insn-addr and PATCHORIG for
our sanity :)

(note that I haven't finished to build with the following patch, I just
started it, but I'm quite confident it'll work)

Thanks!


Index: Makefile
===================================================================
RCS file: /home/cvs/ports/lang/sbcl/Makefile,v
retrieving revision 1.47
diff -u -p -r1.47 Makefile
--- Makefile    31 Dec 2021 09:53:11 -0000      1.47
+++ Makefile    23 Feb 2022 09:03:58 -0000
@@ -1,35 +1,17 @@
 # $OpenBSD: Makefile,v 1.47 2021/12/31 09:53:11 solene Exp $
 
-BROKEN-i386 =          build fails in "Compiling file 
[...]/src/compiler/generic/genesis.lisp"
-# ;; Compiling file 
/pobj/sbcl-2.0.1/sbcl-2.0.1/src/compiler/generic/genesis.lisp ...
-# ;; Wrote file 
/pobj/sbcl-2.0.1/sbcl-2.0.1/obj/from-host/src/compiler/generic/genesis.fas-tmp
-# 0 errors, 0 warnings
-# ;;  Loading file obj/from-host/src/compiler/generic/genesis.fas ...
-# ;;  Loaded file obj/from-host/src/compiler/generic/genesis.fas
-# *** - OPEN: File
-#       #P"/pobj/sbcl-2.0.1/sbcl-2.0.1/obj/from-xc/tls-init.lisp-expr" does not
-#       exist
-# The following restarts are available:
-# SKIP           :R1      skip (GENESIS OBJECT-FILE-NAMES # ...)
-# RETRY          :R2      retry (GENESIS OBJECT-FILE-NAMES # ...)
-# STOP           :R3      stop loading file 
/pobj/sbcl-2.0.1/sbcl-2.0.1/make-genesis-2.lisp
-# ABORT-BUILD    :R4      Abort building SBCL.
-# ABORT          :R5      Abort main loop
-# //testing for consistency of first and second GENESIS passes
-# diff: output/genesis-2: No such file or directory   
-# error: header files do not match between first and second GENESIS
-
 # not yet ported to other arches
 ONLY_FOR_ARCHS =       amd64 i386 powerpc
 USE_WXNEEDED =         Yes
 
 COMMENT=               compiler and runtime system for ANSI Common Lisp
 
-V =                    2.1.11
+V =                    2.2.1
 DISTNAME=              sbcl-${V}-source
 PKGNAME=               sbcl-${V}
 WRKDIST=               ${WRKDIR}/sbcl-${V}
 EXTRACT_SUFX=          .tar.bz2
+PATCHORIG =            .orig.port
 
 CATEGORIES=            lang
 HOMEPAGE=              http://www.sbcl.org/
@@ -58,10 +40,17 @@ WANTLIB+=           pthread
 MAKE_PARAMS +=         --with-sb-core-compression \
                        --with-sb-xref-for-internals
 
+# contrib/sb-capstone/test.lisp uses it at build-time if present
+BUILD_DEPENDS =                devel/capstone/main
+
 .if ${FLAVOR:Mnative_bootstrap}
 BUILD_DEPENDS+=                lang/sbcl
 BOOTSTRAP_CMD=         ${LOCALBASE}/bin/sbcl \
                        --disable-debugger --no-sysinit --no-userinit
+.elif ${MACHINE_ARCH:Mi386}
+# ecl is slower but lang/clips fails to build sbcl on i386
+BUILD_DEPENDS +=       lang/ecl
+BOOTSTRAP_CMD =                ${LOCALBASE}/bin/ecl -q --norc
 .else
 BUILD_DEPENDS +=       lang/clisp
 BOOTSTRAP_CMD =                ${LOCALBASE}/bin/clisp -q -norc
Index: distinfo
===================================================================
RCS file: /home/cvs/ports/lang/sbcl/distinfo,v
retrieving revision 1.21
diff -u -p -r1.21 distinfo
--- distinfo    31 Dec 2021 09:53:11 -0000      1.21
+++ distinfo    22 Feb 2022 23:07:36 -0000
@@ -1,2 +1,2 @@
-SHA256 (sbcl-2.1.11-source.tar.bz2) = 
v8FIHef9vfru8qsPDo6E79NDQz3qjSHPvqiwFGy9/v0=
-SIZE (sbcl-2.1.11-source.tar.bz2) = 6687529
+SHA256 (sbcl-2.2.1-source.tar.bz2) = 
Xdbm4/CLfG7fJioOhEqfi15WLMoIFVA0wfLAFPyQh9o=
+SIZE (sbcl-2.2.1-source.tar.bz2) = 6701705
Index: patches/patch-contrib_sb-capstone_capstone_lisp
===================================================================
RCS file: patches/patch-contrib_sb-capstone_capstone_lisp
diff -N patches/patch-contrib_sb-capstone_capstone_lisp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-contrib_sb-capstone_capstone_lisp     23 Feb 2022 08:55:36 
-0000
@@ -0,0 +1,26 @@
+$OpenBSD$
+
+sync a couple of size mismatches with capstone.h; fixes the build on
+32bit arches (i386, powerpc.)
+
+Index: contrib/sb-capstone/capstone.lisp
+--- contrib/sb-capstone/capstone.lisp.orig
++++ contrib/sb-capstone/capstone.lisp
+@@ -285,7 +285,7 @@
+ (define-alien-type cs-insn
+     (struct nil
+             (insn-id int)
+-            (insn-addr unsigned)
++            (insn-addr (unsigned 64))
+             (insn-size short)
+             (insn-bytes (array char 16))
+             (insn-mnemonic (array char 32))
+@@ -310,7 +310,7 @@
+ 
+ ;; The handle returned by cs-open will be represented as being of type 
unsigned
+ 
+-(define-alien-routine cs-open int (arch int) (mode (integer 64)) (handle 
unsigned :out))
++(define-alien-routine cs-open int (arch int) (mode unsigned) (handle unsigned 
:out))
+ 
+ (define-alien-routine cs-version unsigned (major int :out) (minor int :out))
+ 

Reply via email to