The program below implements a clone lookalike on IA64.  It has been
tested to work properly with CLONE_NEWNS defined as 0 because I didn't
have sufficient privilege to perform a real test.  Of course, no real
functionality test has been performed.

The debian/copyright file needs updating; the code snippet from GNU
libc is covered by the LGPL.

Based on the example program, it should be possible to add the
necessary #ifdef __ia64__ hunk to utils/setupns.c (note that there are
actually two files with that name).

#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <asm/unistd.h>

#define CLONE_NEWNS 0x00020000 /* Flag to create new namespace */

// The following code has been copied from GNU libc 2.3.2, Debian
// version 2.3.2.ds1-18,, file sysdeps/unix/sysv/linux/ia64/sysdeps.h.
// The __set_errno call has been replaced with an assignment to the
// errno location.
//
// We cannot use __clone2 because it requires a callback and
// automatically invokes _exit in the child.  Even if we used longjmp to
// work around this problem, we are still using an internal GNU libc
// interface.  The kernel interface used below should be fairly stable.

// BEGIN OF GNU LIBC EXCERPT

#define BREAK_INSN_1(num) "break " #num ";;\n\t"
#define BREAK_INSN(num) BREAK_INSN_1(num)

/* On IA-64 we have stacked registers for passing arguments.  The
   "out" registers end up being the called function's "in"
   registers.

   Also, since we have plenty of registers we have two return values
   from a syscall.  r10 is set to -1 on error, whilst r8 contains the
   (non-negative) errno on error or the return value on success.
 */
#undef INLINE_SYSCALL
#define INLINE_SYSCALL(name, nr, args...)                       \
  ({                                                            \
    register long _r8 asm ("r8");                               \
    register long _r10 asm ("r10");                             \
    register long _r15 asm ("r15") = __NR_##name;               \
    long _retval;                                               \
    LOAD_ARGS_##nr (args);                                      \
    __asm __volatile (BREAK_INSN (__BREAK_SYSCALL)              \
                      : "=r" (_r8), "=r" (_r10), "=r" (_r15)    \
                        ASM_OUTARGS_##nr                        \
                      : "2" (_r15) ASM_ARGS_##nr                \
                      : "memory" ASM_CLOBBERS_##nr);            \
    _retval = _r8;                                              \
    if (_r10 == -1)                                             \
      {                                                         \
        errno = _retval;                                        \
        _retval = -1;                                           \
      }                                                         \
    _retval; })

#define ASM_OUTARGS_0
#define ASM_OUTARGS_1   ASM_OUTARGS_0, "=r" (_out0)
#define ASM_OUTARGS_2   ASM_OUTARGS_1, "=r" (_out1)
#define ASM_OUTARGS_3   ASM_OUTARGS_2, "=r" (_out2)
#define ASM_OUTARGS_4   ASM_OUTARGS_3, "=r" (_out3)
#define ASM_OUTARGS_5   ASM_OUTARGS_4, "=r" (_out4)
#define ASM_OUTARGS_6   ASM_OUTARGS_5, "=r" (_out5)

#define ASM_ARGS_0
#define ASM_ARGS_1      ASM_ARGS_0, "3" (_out0)
#define ASM_ARGS_2      ASM_ARGS_1, "4" (_out1)
#define ASM_ARGS_3      ASM_ARGS_2, "5" (_out2)
#define ASM_ARGS_4      ASM_ARGS_3, "6" (_out3)
#define ASM_ARGS_5      ASM_ARGS_4, "7" (_out4)
#define ASM_ARGS_6      ASM_ARGS_5, "8" (_out5)

#define ASM_CLOBBERS_6  , "out6", "out7",                               \
  /* Non-stacked integer registers, minus r8, r10, r15.  */             \
  "r2", "r3", "r9", "r11", "r12", "r13", "r14", "r16", "r17", "r18",    \
  "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27",        \
  "r28", "r29", "r30", "r31",                                           \
  /* Predicate registers.  */                                           \
  "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15",     \
  /* Non-rotating fp registers.  */                                     \
  "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",     \
  /* Branch registers.  */                                              \
  "b6", "b7"

#define LOAD_ARGS_0()   do { } while (0)
#define LOAD_ARGS_1(out0)                               \
  register long _out0 asm ("out0") = (long) (out0);     \
  LOAD_ARGS_0 ()
#define LOAD_ARGS_2(out0, out1)                         \
  register long _out1 asm ("out1") = (long) (out1);     \
  LOAD_ARGS_1 (out0)
#define LOAD_ARGS_3(out0, out1, out2)                   \
  register long _out2 asm ("out2") = (long) (out2);     \
  LOAD_ARGS_2 (out0, out1)
#define LOAD_ARGS_4(out0, out1, out2, out3)             \
  register long _out3 asm ("out3") = (long) (out3);     \
  LOAD_ARGS_3 (out0, out1, out2)
#define LOAD_ARGS_5(out0, out1, out2, out3, out4)       \
  register long _out4 asm ("out4") = (long) (out4);     \
  LOAD_ARGS_4 (out0, out1, out2, out3)
#define LOAD_ARGS_6(out0, out1, out2, out3, out4, out5) \
  register long _out5 asm ("out5") = (long) (out5);     \
  LOAD_ARGS_5 (out0, out1, out2, out3, out4)

// END OF GNU LIBC EXCERPT

static inline int
clone (int flags, ...)
{
        return INLINE_SYSCALL (clone2, 6, flags, NULL, 0, NULL, NULL, NULL);
}

int
main()
{
        errno = 0;
        int ret = clone(CLONE_NEWNS|SIGCHLD, 0);
        int e = errno;
        printf("%d %d(%s) %d %d\n", ret, e, strerror(e), getpid(), getppid());
        return 0;
}


-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to