(un-cc-ing libc-alpha) > One reason for troubles in testing with gnumach is that rpc don't work > very well yet... Simple syscalls should work if you take my patch with > syscall64 v3, and also some simple rpcs, but in general I still see some > issues with the 64-bit message format and the mig-generated stubs. I > still have most of my tests failing with a 64-bit userspace.
Ah, I see :( > That being said, once we have fully working rpcs, I think you could have > a "hello-static-glibc" bootstrap module, and assemble a grub rescue disk > to test it on gnumach, much like my "hello" test. For this you could > also take the commit [0] and add your bootstrap module manually, to > reuse the grub disk generation part. Yes yes, that's what I've tried. Here's my source code: -- >8 -- #define _GNU_SOURCE 1 #include <stdio.h> #include <stdlib.h> #include <argp.h> #include <error.h> #include <assert.h> #include <hurd.h> #include <device/device.h> mach_port_t kernel_task; enum { OPT_HOST_PRIV_PORT = -1, OPT_DEVICE_MASTER_PORT = -2, OPT_KERNEL_TASK = -3, }; const struct argp_option startup_options[] = { {"host-priv-port", OPT_HOST_PRIV_PORT, "PORT"}, {"device-master-port", OPT_DEVICE_MASTER_PORT, "PORT"}, {"kernel-task", OPT_KERNEL_TASK, "PORT"}, {0} }; error_t parse_startup_opt (int opt, char *arg, struct argp_state *state) { switch (opt) { case OPT_DEVICE_MASTER_PORT: _hurd_device_master = atoi (arg); break; case OPT_HOST_PRIV_PORT: _hurd_host_priv = atoi (arg); break; case OPT_KERNEL_TASK: kernel_task = atoi (arg); break; default: return ARGP_ERR_UNKNOWN; } return 0; } const struct argp startup_argp = { startup_options, parse_startup_opt }; int main (int argc, char *argv[]) { error_t err; err = argp_parse (&startup_argp, argc, argv, 0, NULL, NULL); assert_perror (err); device_t dev_master, mach_console; err = get_privileged_ports (NULL, &dev_master); assert_perror (err); err = device_open (dev_master, D_READ|D_WRITE, "console", &mach_console); assert_perror (err); stdin = mach_open_devstream (mach_console, "r"); stdout = stderr = mach_open_devstream (mach_console, "w"); printf ("Well hello friends!\n"); fflush (stdout); while (1) { char buffer[100]; scanf ("%s", buffer); printf ("Read: %s\n", buffer); fflush (stdout); } } -- 8< -- This works great on 32-bit, but doesn't work for x86_64. > Once this works, you should be able > to build ext2fs.static, exec.static and run a "hello-dynamic-glibc" test > by replacing /hurd/startup, which is the first dynamically-linked > executable started. Actually no, exec is the first dynamic executable already, it's started as /lib/ld.so.1 /hurd/exec For this case creating a minimal bootable disk is a > bit more tricky, I did it once and I should have some scripts that could > be reused. Yes, I've taken the ideas (how to build the GRUB ISO) from your repo you showed me last time. > In your case you probably need to build a cross-compiler targeting > hurd64, maybe with Flavio's scripts (in my tests I use the > -ffreestanding environment so I can compile them on GNU/Linux). I'm not > sure how this could be optimized for iterative development. I do have a cross toolchain set up, yes, this is how I'm building glibc and the Hurd (and Mach, too). I took some hints from Flavio's scripts for sure; my exact steps are documented here: https://mail.gnu.org/archive/html/bug-hurd/2023-01/msg00132.html (should move this to the wiki). Replace i686 with x86_64 as appropriate. > About debugging, the nice thing is that you can load the debug symbols > of the bootstrap module in the same gdb remote session used to debug > gnumach, with: > > add-symbol-file <your-path>/module-hello-static-glibc > > and you can single-step, use breakpoints etc. on both the user and > kernel code. For example, you can set a breakpoint on the user entry > point _start() and single-step from there. Yes yes, I know that already (but thank you). What I'm saying is this did not work for me, I was unable to break there. I think I was unable to even set the breakpoint? IIUC, gdb breakpoints work by overwriting a single byte of code with int3 (though I wonder how that works in absence of Unix/SIGTRAP?..), so the code needs to be present in the virtual memory already when you place the breakpoint. How/when does that happen, when does Mach switch / set up the pagetables? > Also, when you attach gdb to qemu, you should avoid setting a breakpoint > too early, but anything after setup_main() should be ok. How do you even attach gdb to qemu properly without racing against Mach starting up? qemu -S doesn't work (unlike on i386), since if you attach GDB immediately at startup, it freaks out about some message size mismatch, apparently related to the long mode switch. > So if you want > to set a breakpoint on _start(), I suggest you do it after reaching > setup_main(), otherwise it will also stop on gnumach's own _start(), and > that will indeed mess up with segmentation and long mode. Ah, I was breaking to the entry address (as specified in the ELF header) directly, not via symbol, so that shouldn't have been an issue. > I hope this helps, > > Luca Well, yes, thank you, but as you can see, I knew most of that already, so that doesn't really solve my issue :( Maybe I just need to try again, maybe it will work this time. In the meantime, please try building my glibc branch with the hello world static executable and see if that works on your setup. Sergey