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 --]
next prev parent 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).