help-guix
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: ABI mismatch on boot on arm32 system


From: Efraim Flashner
Subject: Re: ABI mismatch on boot on arm32 system
Date: Wed, 30 Oct 2024 09:09:10 +0200

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: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]