unofficial mirror of help-guix@gnu.org 
 help / color / mirror / Atom feed
From: Efraim Flashner <efraim@flashner.co.il>
To: Christoph Buck <dev@icepic.de>
Cc: Zack Weinberg <zack@owlfolio.org>, help-guix@gnu.org
Subject: Re: ABI mismatch on boot on arm32 system
Date: Wed, 30 Oct 2024 09:09:10 +0200	[thread overview]
Message-ID: <ZyHblkuxVPj2M45O@3900XT> (raw)
In-Reply-To: <87wmhqesw0.fsf@icepic.de>

[-- Attachment #1: Type: text/plain, Size: 6043 bytes --]

On Tue, Oct 29, 2024 at 06:11:27PM +0100, Christoph Buck wrote:
> Hi!
> 
> In case anybody is reading along here. I digged deeper and found
> something rather interessting :P

Thank you! From where I'm sitting it's much easier (for me) to suggest
things than to try and setup your environment.

> From my understanding by reading through the records.scm from guix (and
> please note that im a total scheme newbee), the abi check works by
> calculation a string-hash over the record field names and storing the
> hash as hidden field in the record. During runtime this string-hash is
> computed again and compared to the compiled hash. If they don't
> match, the abi is broken because a field was added or removed.
> 
> The hash is calculated in the `compute-abi-cookie` procedure in the
> records.scm.
> 
> I extended the procedure with the following debug outputs
> 
> --8<---------------cut here---------------start------------->8---
> (define (compute-abi-cookie field-specs)
>   ;; Compute an "ABI cookie" for the given FIELD-SPECS.  We use
>   ;; 'string-hash' because that's a better hash function that 'hash' on a
>   ;; list of symbols.
>   (let ((hash
>          (syntax-case field-specs ()
>            (((field get properties ...) ...)
>             (string-hash (object->string
>                           (syntax->datum #'((field properties ...) ...)))
>                          ;; (bla)
>                          (cond-expand
>                           (guile-3 (target-most-positive-fixnum))
>                           (else most-positive-fixnum))
>                          ))))
>         (fd (syntax-case field-specs ()
>               (((field get properties ...) ...)
>                (object->string
>                 (syntax->datum #'((field properties ...) ...)))))))
>     
>     (format #t "Compute-abi-cookie: ~a~%" hash)
>     (format #t "field-specs: ~a~%" field-specs)
>     (format #t "fd: ~a~%" fd)
>     (format #t "hashsize ~a~%: " (cond-expand
>                                   (guile-3 (target-most-positive-fixnum))
>                                   (else most-positive-fixnum)))
>     hash))
> --8<---------------cut here---------------end--------------->8---
> 
> Now, if i compile a simple test record
> 
> --8<---------------cut here---------------start------------->8---
> 
> (define-record-type* <test-system> test-system
>   make-test-system
>   test-system?
>   (device test-system-device) 
>   (mount-point test-system-mount-point))
> 
> (define test-abi (test-system
>                   (device "my-root")
>                   (mount-point "/")))
>                   
> --8<---------------cut here---------------end--------------->8---
> 
> on x64 using guile cross-compiling (in a `guix shell --container guix
> guile` environment) using the call
> 
> --8<---------------cut here---------------start------------->8---
> (with-target "arm-linux-gnueabihf" (lambda () (compile-file "test-abi.scm")))
> --8<---------------cut here---------------end--------------->8---
> 
> the following outputs are generated:
> 
> --8<---------------cut here---------------start------------->8---
> Compute-abi-cookie: 212719825
> field-specs: ((#<syntax device> #<syntax test-system-device>) (#<syntax mount-point> #<syntax test-system-mount-point>))
> fd: ((device) (mount-point))
> hashsize 536870911
> --8<---------------cut here---------------end--------------->8---
> 
> The abi cookie is computed by calculating the string hash over
> "((device) (mount-point))" while limiting the size of the hash by
> 536870911. One can manually check this by calling
> 
> --8<---------------cut here---------------start------------->8---
> scheme@(guile-user)> (string-hash "((device) (mount-point))" 536870911)
> $1 = 212719825
> --8<---------------cut here---------------end--------------->8---
> 
> in the repl. 
> 
> Now, if i do the same in a qemu arm32 environment (using `guix shell
> --container guix guile --system=armhf-linux`), a different hash is
> printed, even though the hash is calculated over the same string, see:
> 
> --8<---------------cut here---------------start------------->8---
> Compute-abi-cookie: 2434018
> field-specs: ((#<syntax device> #<syntax test-system-device>) (#<syntax mount-point> #<syntax test-system-mount-point>))
> fd: ((device) (mount-point))
> hashsize 536870911
> --8<---------------cut here---------------end--------------->8---
> 
> You can verify this in the repl as well:
> 
> --8<---------------cut here---------------start------------->8---
> scheme@(guile-user)> (string-hash "((device) (mount-point))" 536870911)
> $1 = 2434018
> --8<---------------cut here---------------end--------------->8---
> 
> My first intuition after seeing the source of `compute-abi-cookie` was,
> that maybe the `target-most-positive-fixnum` results in an wrong value
> when called in a cross-compile context. But as you can see, this is not
> the case. Instead, the `string-hash` calculates a different hash
> even thought the input values are the same.
> 
> Now, i am not even sure if one can expect that hash functions running on
> different architectures result in the same hash if the input is the
> same. If not, then the implementation in guix record.scm would be
> buggy. If one expects that the hash of `string-hash` for the same input
> must be the same regardless of the architecture, then this would hint to
> a bug in the `string-hash` function in guile for arm32.
> 
> Any inputs and thoughts regarding this issue would be appreciated.
> 

Can you run it again, but with i686 -> armhf, and x86_64 -> i686?

My curiosity includes i686 -> x86_64, but I suspect it won't tell us
anything we won't learn from the previous tests.

-- 
Efraim Flashner   <efraim@flashner.co.il>   רנשלפ םירפא
GPG key = A28B F40C 3E55 1372 662D  14F7 41AA E7DC CA3D 8351
Confidentiality cannot be guaranteed on emails sent or received unencrypted

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  reply	other threads:[~2024-10-30  7:09 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-16 10:11 ABI mismatch on boot on arm32 system Christoph Buck
2024-10-16 20:05 ` Richard Sent
2024-10-20 15:15   ` Christoph Buck
2024-10-18 20:58 ` Denis 'GNUtoo' Carikli
2024-10-20 15:23 ` Christoph Buck
2024-10-20 15:39   ` Zack Weinberg
2024-10-20 17:24     ` Christoph Buck
2024-10-21  9:55       ` Christoph Buck
2024-10-29 17:11         ` Christoph Buck
2024-10-30  7:09           ` Efraim Flashner [this message]
2024-10-30 13:24             ` Christoph Buck
2024-11-06 10:25               ` Christoph Buck
2024-11-11  7:47                 ` Christoph Buck
2024-12-04 11:50                 ` Maxim Cournoyer
2024-12-07 13:44                   ` Christoph Buck
2024-12-09  0:44                     ` Maxim Cournoyer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://guix.gnu.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ZyHblkuxVPj2M45O@3900XT \
    --to=efraim@flashner.co.il \
    --cc=dev@icepic.de \
    --cc=help-guix@gnu.org \
    --cc=zack@owlfolio.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).