-
Notifications
You must be signed in to change notification settings - Fork 136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
.data with relocations not linked in correctly #73
Comments
I'm wondering if this has something to do with position independent code... maybe |
I can't reproduce this with a plain C test case using The following code:
Built with this script:
always gives me a
@pqwy Do you have a reproducible test case that hits the problem? |
Regarding I remember investigating this some time ago and deciding to ignore the problem since I could see the same happening for |
See my comment in #74 -- I have working crypto ( |
Back when we had the "loader" in the virtio boot, the 64-bit ELF wasn't getting loaded properly and there was a weird hack to clear the BSS very late in the boot. I don't think it still exists after you cleaned up the virtio boot, but I thought I'd mention it if it gives any ideas. |
@djwillia The multiboot specification explicitly states that the boot loader will zero BSS if those fields are filled in in the multiboot header (which they are). Out of paranoia, I added in some code to do it ourselves, but nothing changed (crypto still fails on virtio). So the problem is elsewhere... |
Sorry, a few more details:
Here's a fleshed-out repro: https://github.com/pqwy/abstract-type. A couple of ways to see the problem:
This is the thing that's confusing me to no end: the same object file, compiled PIC, works on And yes, this is what's breaking |
Test-drive:
open Mirage
let main =
foreign "Unikernel.Main"
~libraries:["abstract-type"; "zarith"]
(console @-> job)
let () = register "uk" [main $ default_console]
module A = Abstract_type
module Main (C: V1_LWT.CONSOLE) = struct
let start c =
A.inspect_ops 1l;
A.inspect_ops 1L;
A.inspect_ops Z.(~$1 lsl 63);
A.inspect_ops A.(create 20);
C.log_s c (Format.sprintf "ptr: %d\n%!" (A.canary ()))
end
|
... and lastly, adding
... but only on |
@pqwy Thanks a lot for the test cases. The non-working behaviour with One pointer I found which may be useful is that it turns out that on OCaml 4.03.0+ it's possible to globally override and disable all use of |
I've managed to figure out why things are not working on
Note the offset of the
Given that we don't explicitly ask the linker to place What happens next is: Based on our multiboot header, the boot loader will (correctly) zero everything between 0x1150b8 ( The reason The fix is to explicitly add As for the question of "why does -fPIC-compiled code work in a unikernel in the first place", I think that the answer is "the linker knows it is creating an executable (as opposed to a shared object), and performs all the relocations at link time". Combined with the fact that RIP-relative addressing can be used on |
- Ensure all input sections are placed in the correct output section. This addresses Solo5#73 by placing .data.*, .got and .got.plt in the .data output section. - Unify symbols used as section delimiters to _stext, _etext, _erodata, _edata, _ebss and _end. - Rename ukvm kernel_main() to _start(). The ukvm and virtio linker scripts are now identical with the exception of .bootstrap for virtio.
Fixed via #76. |
Not much of a test, but also verifies that the memory mappings are (somewhat) correct.
This is probably equally a bug in mirage, but raising here as it concerns only solo5.
If I compile a C source that contains, at the top level, something like
with the flags given by
pkg-config --static --cflags ocaml-freestanding
[1], and then link it in usingmirage -t virtio
, which passespkg-config --variable=ldflags solo5-kernel-virtio
[2] andpkg-config --static --libs mirage-solo5 ocaml-freestanding
[3] told
, the generated unikernel ends up withp
==0
. I can see"xxx"
in the binary, butp
's value is never set to its address.I suspect the problem is in the linker script, but so far cannot figure out how to solve it.
This becomes more interesting when the pointer is supposed to point to functions, as it breaks OCaml's custom primitive data, like
zarith
bignums, which in turn breaks cryptography.[1]
-nostdinc -isystem /usr/lib/gcc/x86_64-pc-linux-gnu/6.1.1/include -ffreestanding -mno-red-zone -mno-3dnow -I/home/self/.opam/system+solo5/lib/pkgconfig/../../include/ocaml-freestanding/include -I/home/self/.opam/system+solo5/lib/pkgconfig/../../include/solo5-kernel-virtio/include
[2]
-nostdlib -z max-page-size=0x1000 -static -T /home/self/.opam/system+solo5/lib/pkgconfig/../../lib/solo5-kernel-virtio/solo5.lds /home/self/.opam/system+solo5/lib/pkgconfig/../../lib/solo5-kernel-virtio/solo5.o
[3]
/home/self/.opam/system+solo5/lib/pkgconfig/../../lib/mirage-solo5/libsolo5camlbindings.a /home/self/.opam/system+solo5/lib/pkgconfig/../../lib/ocaml-freestanding/libasmrun.a /home/self/.opam/system+solo5/lib/pkgconfig/../../lib/ocaml-freestanding/libotherlibs.a /home/self/.opam/system+solo5/lib/pkgconfig/../../lib/ocaml-freestanding/libnolibc.a /home/self/.opam/system+solo5/lib/pkgconfig/../../lib/ocaml-freestanding/libopenlibm.a
The text was updated successfully, but these errors were encountered: