mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-11-20 00:31:28 +00:00
Merge in __PAGEZERO hack from Michael Z. Sliczniak so that REAL_ADDRESSING
mode can work under Darwin.
This commit is contained in:
parent
4641be3209
commit
45c30ba9f2
148
BasiliskII/src/Unix/Darwin/lowmem.c
Normal file
148
BasiliskII/src/Unix/Darwin/lowmem.c
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* lowmem.c - enable access to low memory globals on Darwin
|
||||
*
|
||||
* Copyright (c) 2003 Michael Z. Sliczniak
|
||||
*
|
||||
* Basilisk II (C) 1997-2003 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <mach/vm_prot.h>
|
||||
#include <mach-o/loader.h>
|
||||
|
||||
static const char progname[] = "lowmem";
|
||||
|
||||
/*
|
||||
* Under Mach there is very little assumed about the memory map of object
|
||||
* files. It is the job of the loader to create the initial memory map of an
|
||||
* executable. In a Mach-O executable there will be numerous loader commands
|
||||
* that the loader must process. Some of these will create the initial memory
|
||||
* map used by the executable. Under Darwin the static object file linker,
|
||||
* ld, automatically adds the __PAGEZERO segment to all executables. The
|
||||
* default size of this segment is the page size of the target system and
|
||||
* the initial and maximum permissions are set to allow no access. This is so
|
||||
* that all programs fault on a NULL pointer dereference. Arguably this is
|
||||
* incorrect and the maximum permissions shoould be rwx so that programs can
|
||||
* change this default behavior. Then programs could be written that assume
|
||||
* a null string at the null address, which was the convention on some
|
||||
* systems. In our case we need to have 8K mapped at zero for the low memory
|
||||
* globals and this program modifies the segment load command in the
|
||||
* basiliskII executable so that it can be used for data.
|
||||
*/
|
||||
|
||||
int
|
||||
main(int argc, const char *argv[])
|
||||
{
|
||||
int fd;
|
||||
char *addr;
|
||||
struct mach_header *machhead;
|
||||
struct segment_command *sc_cmd;
|
||||
|
||||
if (argc != 2) {
|
||||
(void)fprintf(stderr, "Usage: %s executable\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fd = open(argv[1], O_RDWR, 0);
|
||||
if (fd == -1) {
|
||||
(void)fprintf(stderr, "%s: could not open %s: %s\n",
|
||||
progname, argv[1], strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Size does not really matter, it will be rounded-up to a multiple
|
||||
* of the page size automatically.
|
||||
*/
|
||||
addr = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE,
|
||||
MAP_FILE | MAP_SHARED, fd, 0);
|
||||
if (addr == NULL) {
|
||||
(void)fprintf(stderr, "%s: could not mmap %s: %s\n",
|
||||
progname, argv[1], strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if the Mach-O magic bytes are in the header.
|
||||
* If we cared about cross compiling we would also check against
|
||||
* MH_CIGAM and then change the endianness with every access, but
|
||||
* we do not care about that.
|
||||
*/
|
||||
machhead = (void *)addr;
|
||||
if (machhead->magic != MH_MAGIC) {
|
||||
(void)fprintf(stderr, "%s: %s does not appear to be a Mach-O object file\n",
|
||||
progname, argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (machhead->filetype != MH_EXECUTE) {
|
||||
(void)fprintf(stderr, "%s: %s does not appear to be an executable file\n",
|
||||
progname, argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (machhead->ncmds == 0) {
|
||||
(void)fprintf(stderr, "%s: %s does not contain any load commands\n",
|
||||
progname, argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sc_cmd = (void *)&machhead[1];
|
||||
if (sc_cmd->cmd != LC_SEGMENT){
|
||||
(void)fprintf(stderr, "%s: load segment not first command in %s\n",
|
||||
progname, argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (strncmp(sc_cmd->segname, "__PAGEZERO",
|
||||
sizeof (*sc_cmd->segname))) {
|
||||
(void)fprintf(stderr, "%s: zero page not first segment in %s\n",
|
||||
progname, argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* change the permissions */
|
||||
sc_cmd->maxprot = VM_PROT_ALL;
|
||||
sc_cmd->initprot = VM_PROT_ALL;
|
||||
|
||||
/*
|
||||
* We do not make __PAGEZERO 8K in this program because then
|
||||
* all of the offsets would be wrong in the object file after
|
||||
* this segment. Instead we use the -pagezero_size option
|
||||
* to link the executable.
|
||||
*/
|
||||
if (msync(addr, 0x1000, MS_SYNC) == -1) {
|
||||
(void)fprintf(stderr, "%s: could not sync %s: %s\n",
|
||||
progname, argv[1], strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (munmap(addr, 0x1000) == -1) {
|
||||
(void)fprintf(stderr, "%s: could not unmap %s: %s\n",
|
||||
progname, argv[1], strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
(void)close(fd);
|
||||
|
||||
exit(0);
|
||||
}
|
31
BasiliskII/src/Unix/Darwin/pagezero.c
Normal file
31
BasiliskII/src/Unix/Darwin/pagezero.c
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* pagezero.c - test to see if low memory globals can be accessed
|
||||
*
|
||||
* Copyright (c) 2003 Michael Z. Sliczniak
|
||||
*
|
||||
* Basilisk II (C) 1997-2003 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
int
|
||||
main(int argc, const char *argv[])
|
||||
{
|
||||
volatile char *pagezero = (void *)0;
|
||||
|
||||
pagezero[0x1234] = pagezero[0x123];
|
||||
|
||||
return (0);
|
||||
}
|
34
BasiliskII/src/Unix/Darwin/testlmem.sh
Executable file
34
BasiliskII/src/Unix/Darwin/testlmem.sh
Executable file
@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
|
||||
# testlmem.sh - test whether the Mach-O hack works
|
||||
#
|
||||
# Basilisk II (C) 1997-2003 Christian Bauer
|
||||
#
|
||||
# testlmem.sh Copyright (C) 2003 Michael Z. Sliczniak
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
PAGEZERO_SIZE=0x2000
|
||||
[[ -n "$1" ]] && PAGEZERO_SIZE=$1
|
||||
# You want all the output to go to stderr so that configure is quiet but
|
||||
# config.log is verbose.
|
||||
{ echo 'building lowmem utility' && \
|
||||
make -f /dev/null Darwin/lowmem && \
|
||||
echo 'building pagezero test' && \
|
||||
make -f /dev/null LDFLAGS="-pagezero_size $PAGEZERO_SIZE" Darwin/pagezero && \
|
||||
echo 'enabling low memory globals in pagezero' && \
|
||||
Darwin/lowmem Darwin/pagezero && \
|
||||
echo 'running pagezero test' && \
|
||||
Darwin/pagezero; } 1>&2
|
@ -23,6 +23,7 @@ LDFLAGS = @LDFLAGS@
|
||||
LIBS = @LIBS@
|
||||
SYSSRCS = @SYSSRCS@
|
||||
CPUSRCS = @CPUSRCS@
|
||||
BLESS = @BLESS@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@ -s
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
@ -61,6 +62,7 @@ VPATH += $(addprefix :, $(subst ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(S
|
||||
|
||||
$(APP): $(OBJ_DIR) $(OBJS)
|
||||
$(CXX) -o $(APP) $(LDFLAGS) $(OBJS) $(LIBS)
|
||||
$(BLESS) $(APP)
|
||||
|
||||
modules:
|
||||
cd Linux/NetDriver; make
|
||||
|
@ -558,6 +558,19 @@ AC_TRANSLATE_DEFINE(HAVE_MMAP_VM, $have_mmap_vm,
|
||||
|
||||
fi dnl HAVE_MMAP_VM
|
||||
|
||||
dnl Check if we can modify the __PAGEZERO segment for use as Low Memory
|
||||
AC_CACHE_CHECK([whether __PAGEZERO can be Low Memory area 0x0000-0x2000],
|
||||
ac_cv_pagezero_hack, [
|
||||
ac_cv_pagezero_hack=no
|
||||
if AC_TRY_COMMAND([Darwin/testlmem.sh 0x2000]); then
|
||||
ac_cv_pagezero_hack=yes
|
||||
dnl might as well skip the test for mmap-able low memory
|
||||
ac_cv_can_map_lm=no
|
||||
fi
|
||||
])
|
||||
AC_TRANSLATE_DEFINE(PAGEZERO_HACK, "$ac_cv_pagezero_hack",
|
||||
[Define if the __PAGEZERO Mach-O Low Memory Globals hack works on this system.])
|
||||
|
||||
dnl Check if we can mmap 0x2000 bytes from 0x0000
|
||||
AC_CACHE_CHECK([whether we can map Low Memory area 0x0000-0x2000],
|
||||
ac_cv_can_map_lm, [
|
||||
@ -743,6 +756,9 @@ if [[ -n "$sigsegv_recovery" ]]; then
|
||||
CAN_VOSF=yes
|
||||
fi
|
||||
|
||||
dnl A dummy program that returns always true
|
||||
BLESS=/bin/true
|
||||
|
||||
dnl Determine the addressing mode to use
|
||||
if [[ "x$WANT_NATIVE_M68K" = "xyes" ]]; then
|
||||
ADDRESSING_MODE="real"
|
||||
@ -753,10 +769,10 @@ else
|
||||
case $am in
|
||||
real)
|
||||
dnl Requires ability to mmap() Low Memory globals
|
||||
if [[ "x$ac_cv_can_map_lm" = "xno" ]]; then
|
||||
if [[ "x$ac_cv_can_map_lm$ac_cv_pagezero_hack" = "xnono" ]]; then
|
||||
continue
|
||||
fi
|
||||
dnl Requires VOSF screen updates
|
||||
dnl Requires VOSF screen updates
|
||||
if [[ "x$CAN_VOSF" = "xno" ]]; then
|
||||
continue
|
||||
fi
|
||||
@ -764,6 +780,10 @@ else
|
||||
ADDRESSING_MODE="real"
|
||||
WANT_VOSF=yes dnl we can use VOSF and we need it actually
|
||||
DEFINES="$DEFINES -DREAL_ADDRESSING"
|
||||
if [[ "x$ac_cv_pagezero_hack" = "xyes" ]]; then
|
||||
BLESS=Darwin/lowmem
|
||||
LDFLAGS="$LDFLAGS -pagezero_size 0x2000"
|
||||
fi
|
||||
break
|
||||
;;
|
||||
direct)
|
||||
@ -1152,6 +1172,7 @@ AC_SUBST(DEFINES)
|
||||
AC_SUBST(SYSSRCS)
|
||||
AC_SUBST(CPUINCLUDES)
|
||||
AC_SUBST(CPUSRCS)
|
||||
AC_SUBST(BLESS)
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_OUTPUT
|
||||
|
||||
|
@ -413,7 +413,7 @@ int main(int argc, char **argv)
|
||||
|
||||
// Under Solaris/SPARC and NetBSD/m68k, Basilisk II is known to crash
|
||||
// when trying to map a too big chunk of memory starting at address 0
|
||||
#if defined(OS_solaris) || defined(OS_netbsd)
|
||||
#if defined(OS_solaris) || defined(OS_netbsd) || defined(PAGEZERO_HACK)
|
||||
const bool can_map_all_memory = false;
|
||||
#else
|
||||
const bool can_map_all_memory = true;
|
||||
@ -425,6 +425,7 @@ int main(int argc, char **argv)
|
||||
memory_mapped_from_zero = true;
|
||||
}
|
||||
|
||||
#ifndef PAGEZERO_HACK
|
||||
// Otherwise, just create the Low Memory area (0x0000..0x2000)
|
||||
else if (vm_acquire_fixed(0, 0x2000) == 0) {
|
||||
D(bug("Could allocate the Low Memory globals\n"));
|
||||
@ -438,6 +439,7 @@ int main(int argc, char **argv)
|
||||
QuitEmulator();
|
||||
}
|
||||
#endif
|
||||
#endif /* REAL_ADDRESSING */
|
||||
|
||||
// Create areas for Mac RAM and ROM
|
||||
#if REAL_ADDRESSING
|
||||
|
Loading…
Reference in New Issue
Block a user