Write tests for new APE loader and fix bugs

- Add FreeBSD-specific mmap() flags
- Reduce size of the APE loader from 8kb to 4kb
- Work towards fixing the Makefile build on WSL
- Automate testing of APE no-modify-self behaviors
- Make the ape.S shell script code cleaner and tinier
- Improve the APE sanity check to test behavior better
- Fixed issue with ShowCrashReports() sigaltstack() on BSDs
- Delete symbols for S_MODE magnums which wasted compile time

If you checked out yesterday's APE commit, please run:

    rm -f /usr/bin/ape o/tmp/ape /tmp/ape "${TMPDIR:-/tmp}/ape"

Because this change fixes certain aspects of the new ABI. We don't have
automated migrations for APE loader versions yet. Thanks! You can also
download prebuilt binaries here:

- https://justine.lol/ape.elf    (Linux/FreeBSD/NetBSD/OpenBSD)
- https://justine.lol/ape.macho  (Apple)

Install the appropriate one as `/usr/bin/ape`.
This commit is contained in:
Justine Tunney 2022-05-22 04:51:02 -07:00
parent 056dc5f554
commit 4e9662cbc7
75 changed files with 759 additions and 443 deletions

View file

@ -34,12 +34,22 @@
char program_executable_name[PATH_MAX];
static inline char *StrCat(char buf[PATH_MAX], const char *a, const char *b) {
char *p, *e;
p = buf;
e = buf + PATH_MAX;
while (*a && p < e) *p++ = *a++;
while (*b && p < e) *p++ = *b++;
return buf;
}
static inline void GetProgramExecutableNameImpl(char *p, char *e) {
char *q;
ssize_t rc;
size_t i, n;
union {
int cmd[4];
char path[PATH_MAX];
char16_t path16[PATH_MAX];
} u;
@ -61,7 +71,11 @@ static inline void GetProgramExecutableNameImpl(char *p, char *e) {
return;
}
if (__argc && (q = __argv[0]) && !sys_faccessat(AT_FDCWD, q, F_OK, 0)) {
// if argv[0] exists then turn it into an absolute path. we also try
// adding a .com suffix since the ape auto-appends it when resolving
if (__argc && (((q = __argv[0]) && !sys_faccessat(AT_FDCWD, q, F_OK, 0)) ||
((q = StrCat(u.path, __argv[0], ".com")) &&
!sys_faccessat(AT_FDCWD, q, F_OK, 0)))) {
if (*q != '/') {
if (q[0] == '.' && q[1] == '/') {
q += 2;
@ -78,12 +92,12 @@ static inline void GetProgramExecutableNameImpl(char *p, char *e) {
return;
}
// if argv[0] doesn't exist, then fallback to interpreter name
if ((rc = sys_readlinkat(AT_FDCWD, "/proc/self/exe", p, e - p - 1)) > 0 ||
(rc = sys_readlinkat(AT_FDCWD, "/proc/curproc/file", p, e - p - 1)) > 0) {
p[rc] = 0;
return;
}
if (IsFreebsd() || IsNetbsd()) {
u.cmd[0] = CTL_KERN;
u.cmd[1] = KERN_PROC;
@ -101,7 +115,7 @@ static inline void GetProgramExecutableNameImpl(char *p, char *e) {
}
/**
* Returns absolute path of executable.
* Returns absolute path of program.
*/
char *GetProgramExecutableName(void) {
int e;

View file

@ -58,7 +58,7 @@ int __ensurefds_unlocked(int fd) {
if (!(p2 = weaken(malloc)(n2 * sizeof(*p1)))) return -1;
__cxa_atexit(FreeOldFdsArray, p1, 0);
memcpy(p2, p1, n1 * sizeof(*p1));
bzero(p2 + n1, (p2 + n2) - (p2 + n1));
bzero(p2 + n1, (n2 - n1) * sizeof(*p1));
g_fds.p = p2;
g_fds.n = n2;
return fd;

View file

@ -16,10 +16,15 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/weaken.h"
#include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/errno.h"
#include "libc/nt/errors.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/sicode.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
@ -37,12 +42,18 @@ static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size,
// return ebadf(); /* handled by consts.sh */
// case kNtErrorNotEnoughQuota:
// return edquot(); /* handled by consts.sh */
case kNtErrorBrokenPipe: // broken pipe
case kNtErrorNoData: // closing named pipe
__sig_raise(SIGPIPE, SI_KERNEL); //
return epipe(); //
case kNtErrorAccessDenied: // write doesn't return EACCESS
return ebadf(); //
case kNtErrorBrokenPipe: // broken pipe
case kNtErrorNoData: // closing named pipe
if (weaken(__sig_raise)) {
weaken(__sig_raise)(SIGPIPE, SI_KERNEL);
return epipe();
} else {
STRACE("broken pipe");
__restorewintty();
_Exit(128 + EPIPE);
}
case kNtErrorAccessDenied: // write doesn't return EACCESS
return ebadf(); //
default:
return __winerr();
}