Code Monkey home page Code Monkey logo

Comments (4)

acarno avatar acarno commented on June 12, 2024

I ran into (what I think is) a similar issue with struct epoll_event, which differs in size between x86_64 and aarch64 due to different structure-packing settings. Chiefly, on x86_64, the kernel expects a 12-byte struct; on aarch64, the kernel expects a 16-byte struct.

The issue I ran into -- and that I suspect you might run into here -- is that changing the kernel's definition of struct stat will break every existing program; however, changing the user's definition will break Popcorn applications on the aarch64 kernel only.

My ad-hoc solution involved declaring the "kernel-correct" version of the structure inside musl's epoll.c file and copying each field from the "user-correct" version into the corresponding field of the "kernel-correct" structure, using temporary stack-allocated variables. Needless to say, this is a terrible workaround:

diff --git a/lib/musl-1.1.18/src/linux/epoll.c b/lib/musl-1.1.18/src/linux/epoll.c
index deff5b1..0df118e 100644
--- a/lib/musl-1.1.18/src/linux/epoll.c
+++ b/lib/musl-1.1.18/src/linux/epoll.c
@@ -1,8 +1,19 @@
 #include <sys/epoll.h>
 #include <signal.h>
 #include <errno.h>
+#if !defined(__x86_64__)
+#include <string.h>
+#endif
 #include "syscall.h"
 
+#if !defined(__x86_64__)
+struct epoll_event16 {
+    uint32_t events;
+    char pad[4];
+    epoll_data_t data;
+};
+#endif
+
 int epoll_create(int size)
 {
 	return epoll_create1(0);
@@ -19,16 +30,42 @@ int epoll_create1(int flags)
 
 int epoll_ctl(int fd, int op, int fd2, struct epoll_event *ev)
 {
+#if !defined(__x86_64__)
+    struct epoll_event16 ev16;
+    if (ev) {
+        memcpy(&ev16.events, &ev->events, sizeof (uint32_t));
+        memcpy(&ev16.data, &ev->data, sizeof (epoll_data_t));
+        return syscall(SYS_epoll_ctl, fd, op, fd2, &ev16);
+    }
+    else {
+        return syscall(SYS_epoll_ctl, fd, op, fd2, NULL);
+    }
+#else
 	return syscall(SYS_epoll_ctl, fd, op, fd2, ev);
+#endif
 }
 
 int epoll_pwait(int fd, struct epoll_event *ev, int cnt, int to, const sigset_t *sigs)
 {
+#if !defined(__x86_64__)
+    struct epoll_event16 ev16[cnt]; //VLAs are evil!
+    memset(ev16, 0, sizeof ev16[0] * cnt);
+    int r = __syscall(SYS_epoll_pwait, fd, ev16, cnt, to, sigs, _NSIG/8);
+#ifdef SYS_epoll_wait
+	if (r==-ENOSYS && !sigs) r = __syscall(SYS_epoll_wait, fd, ev16, cnt, to);
+#endif
+    for (int i = 0; i < cnt; ++i) {
+        memcpy(&ev[i].events, &ev16[i].events, sizeof (uint32_t));
+        memcpy(&ev[i].data, &ev16[i].data, sizeof (epoll_data_t));
+    }
+    return __syscall_ret(r);
+#else
 	int r = __syscall(SYS_epoll_pwait, fd, ev, cnt, to, sigs, _NSIG/8);
 #ifdef SYS_epoll_wait
 	if (r==-ENOSYS && !sigs) r = __syscall(SYS_epoll_wait, fd, ev, cnt, to);
 #endif
 	return __syscall_ret(r);
+#endif
 }
 
 int epoll_wait(int fd, struct epoll_event *ev, int cnt, int to)

from popcorn-compiler.

xjtuwxg avatar xjtuwxg commented on June 12, 2024

Thank Anthony for the comment. Do you mean I should modify the popcorn-compiler musl source to adjust to the kernel's declaration? I thought this is a problem caused by the different header files of x86/arm.

from popcorn-compiler.

acarno avatar acarno commented on June 12, 2024

Before I answer that, let me ask this question to clarify:

-- Are the x86/arm kernel declarations the same?
-- If so, do the popcorn-compiler musl headers match either of the kernel declarations, or none of them?

from popcorn-compiler.

xjtuwxg avatar xjtuwxg commented on June 12, 2024

Hey guys. [Good news] I wrote a patch inmusl-1.1.18/src/stat/fstat.c to marshal the struct stat from x86 to aarch64, it solves the tiny web server problem right now. [Bad news] It still has wrong result when passing the struct stat as a parameter to another function. I'll write another issue for that.

The patch for fstat is:

$ git diff 4ffd16e00d70a40b4cdde9507f6eddadffef62b8
diff --git a/lib/musl-1.1.18/src/stat/fstat.c b/lib/musl-1.1.18/src/stat/fstat.c
index ab4afc0..d3b47ad 100644
--- a/lib/musl-1.1.18/src/stat/fstat.c
+++ b/lib/musl-1.1.18/src/stat/fstat.c
@@ -4,10 +4,95 @@
 #include "syscall.h"
 #include "libc.h"

+#if defined(__x86_64__)
+#include <string.h>
+
+// The syscall on x86 returns the x86 version of struct stat.
+// But the x86 binary actually uses the arm version of stat.
+// copied from arch/x86_64/bits/stat.h
+struct stat_x86 {
+       dev_t st_dev;
+       ino_t st_ino;
+       nlink_t st_nlink;
+
+       mode_t st_mode;
+       uid_t st_uid;
+       gid_t st_gid;
+       unsigned int    __pad0;
+       dev_t st_rdev;
+       off_t st_size;
+       blksize_t st_blksize;
+       blkcnt_t st_blocks;
+
+       struct timespec st_atim;
+       struct timespec st_mtim;
+       struct timespec st_ctim;
+       long __unused[3];
+};
+
+// Copied from arch/aarch64/bits/stat.h
+struct stat_arm {
+       dev_t st_dev;
+       ino_t st_ino;
+       mode_t st_mode;
+       nlink_t st_nlink;
+       uid_t st_uid;
+       gid_t st_gid;
+       dev_t st_rdev;
+       unsigned long __pad;
+       off_t st_size;
+       blksize_t st_blksize;
+       int __pad2;
+       blkcnt_t st_blocks;
+       struct timespec st_atim;
+       struct timespec st_mtim;
+       struct timespec st_ctim;
+       unsigned __unused[2];
+};
+
+#define MARSHALLING_STAT(st, st_x86) \
+    memcpy(st, &st_x86, sizeof(struct stat)); \
+    st->st_mode = st_x86.st_mode; \
+    st->st_nlink = (unsigned)(st_x86.st_nlink);\
+    st->st_uid = st_x86.st_uid; \
+    st->st_gid = st_x86.st_gid; \
+    st->st_rdev = st_x86.st_rdev;
+
+#endif
 void __procfdname(char *, unsigned);

 int fstat(int fd, struct stat *st)
 {
+#if defined(__x86_64__)
+    struct stat_x86 st_x86;
+       int ret = __syscall(SYS_fstat, fd, &st_x86);
+
+    // convert a "kernel stat (x86_64)" to "musl stat (aarch64)"
+    MARSHALLING_STAT(((struct stat_arm *)st), st_x86)
+
+       if (ret != -EBADF || __syscall(SYS_fcntl, fd, F_GETFD) < 0) {
+               return __syscall_ret(ret);
+    }
+
+       char buf[15+3*sizeof(int)];
+       __procfdname(buf, fd);
+#ifdef SYS_stat
+       ret = syscall(SYS_stat, buf, &st_x86);
+
+    // convert a "kernel stat (x86_64)" to "musl stat (aarch64)"
+    MARSHALLING_STAT(((struct stat_arm *)st), st_x86)
+
+    return ret;
+#else
+       ret = syscall(SYS_fstatat, AT_FDCWD, buf, &st_x86, 0);
+
+    // convert a "kernel stat (x86_64)" to "musl stat (aarch64)"
+    MARSHALLING_STAT(((struct stat_arm *)st), st_x86)
+
+    return ret;
+#endif
+
+#else   // aarch64 default code
        int ret = __syscall(SYS_fstat, fd, st);
        if (ret != -EBADF || __syscall(SYS_fcntl, fd, F_GETFD) < 0)
                return __syscall_ret(ret);
@@ -19,6 +104,7 @@ int fstat(int fd, struct stat *st)
 #else
        return syscall(SYS_fstatat, AT_FDCWD, buf, st, 0);
 #endif
+#endif  // end if define(__x86_64__)
 }

 LFS64(fstat);

from popcorn-compiler.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.