[Top][All Lists]

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

Re: [RFC PATCH 00/34] The rest of the x86_64-gnu port

From: Sergey Bugaev
Subject: Re: [RFC PATCH 00/34] The rest of the x86_64-gnu port
Date: Sun, 19 Mar 2023 20:39:13 +0300

(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;


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"},

parse_startup_opt (int opt, char *arg, struct argp_state *state)
  switch (opt)
      _hurd_device_master = atoi (arg); break;
      _hurd_host_priv = atoi (arg); break;
      kernel_task = atoi (arg); break;
      return ARGP_ERR_UNKNOWN;

  return 0;

const struct argp startup_argp = { startup_options, parse_startup_opt };

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:
(should move this to the wiki). Replace i686 with x86_64 as

> 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

> 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.


reply via email to

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