Cross compiling to i386 Linux ELF from OS X

This isn’t terribly useful for 99.9% of the people out there but I needed to do something creative on an F5.  Luckily they run a somewhat sane version of Linux.

Unfortunately I am stuck on Windows 10 right now, so installing a matching Linux distro is out of the question.  So on my OS X box, I thought I’d just build a cross compiler.  Going back to my DJGPP cross compiler, I thought I’d stick with binutils 2.9.1 and gcc 2.95.3, since they worked so well before.

Plus to flesh it out, you’ll want libc, libg++, and the appropriate Linux includes.  I took all of these from Slackware 3.3 since it’s from around that era.

So on the plus side this cross compiler + library set , will crank out static ELF executables, which makes running things on alien platforms all the better.

On the realistic side, I doubt anyone will need it, but here it is.

Clang didn’t want to build anything this old, but luckily that backported GCC-4.2 has no issues.

Run68 Human-68k emulator

I found this one by accident, but it’s more like DOSBox in that it runs 68000 executables with an emulated processor and emulated OS.  No SHARP ROMs or HumanOS diskettes needed.  It’s strictly text mode, but it’s enough to run executables produced by GCC.

Hello!

Hello!

The project is over on sourceforge, and unlike any other x68000 project this one is GPL’d.  The source code is remarkably tiny so I’d say for anyone looking for a way to sneak some C into something this may be an interesting ‘door’..

Cross compiling to the Sharp x68000

While looking for some stuff on the x68000, I came across this package Lydux, which features GCC setup as a cross compiler from either Windows or Linux to Human68k.

So I downloaded the Windows version, set it up according to this guide, and set on trying to build a simple EXE.  I did install CodeBlocks, but I ran into a problem while trying to build a running executable.  For some reason objcopy doesn’t work correctly unless it is in verbose mode.  I found that by accident, but much to my surprise it does work!

Hello World cross compiled from Windows to the x68000

Hello World cross compiled from Windows to the x68000

In the script for CodeBlocks, changing

oc_x = _T(“human68k-objcopy -O xfile $(TARGET_OUTPUT_FILE) $(TARGET_OUTPUT_FILE).X”);

to

oc_x = _T(“human68k-objcopy -v -O xfile $(TARGET_OUTPUT_FILE) $(TARGET_OUTPUT_FILE).X”);

did the trick, and now it’ll generate working executables.

I’ve found the emulator XM6 TypeG version 3.13 L21 the easiest to deal with as it has English translated menu’s and lets you mount a folder on your PC as a virtual drive.  This makes loading cross compiled stuff much easier.

Since finding this stuff is getting harder and harder, and that most of the xm6 forked emulators are closed source, I thought I’d at least upload what I’ve been able to find.  It’s a shame the 68030 stuff is closed off, but there isn’t anything I can do about that.  Apparently there was some feud between some dev groups.  I’m not really sure as it seems.

All my work on this is here.

WindrvXM settings

WindrvXM settings

Be sure to set the shared directory under Tools -> Options to be able to map a shared directory.  In the disks sub directory there is a HUMAN302 disk image which contains the needed device driver to map into the directory.  You can run either the 68000 or 68030 model depending on what you like more.  If you have no emulated SCSI or SASI disk, the shared directory will appear as your ‘c’ drive.  And as always the keyboard will be mapped to a Japanese keyboard, so that is why the : * = keys seem in the wrong place.

On the OS X front I went ahead and built a cross compiler.  I ran into this fun error building GCC on OS X:

Makefile:142: ../.././gcc/libgcc.mvars: No such file or directory

So yeah it turns out you really should configure/compile gcc in a separate directory from the source. Bad old habits die hard. Anyways my tool chain is here. I’m running 10.10 so I’m not sure about older versions of OS X.

Adding Solaris packages, under Qemu

So you know the drill, someone wants to do something with Solaris, and they’ve already installed the OS, and done a bunch of customization and whatnot, now they call up all in a panic as they copy in a binary distribution of GCC, but they can’t compile anything because they are missing values-Xa.o , or worse just about everything from the development tools.

Well I’m not sure about ancient Qemu, but 2.2 can mount the CD-ROM’s post install! … manually.

The poor guy didn’t want to re-install, but one option was to boot up the CD in single user mode, mount his disk, and copy the /cdrom path onto some partition so he could then install the packages as needed, and even better have the whole tree ready if need be.

But the better thing is to just mount the CD, install the package and be done with it right?

I’ve only tested this with Solaris 2.6…

While booting up single user mode from the CD (boot disk2:d -s) I noticed this line in the mount table:

/cdrom             (/devices/iommu@f,e0000000/sbus@f,e0001000/espdma@f,400000/esp@f,800000/sd@2,0:a):       0 blocks        0 files

So I thought I’d try to mount that once the copy was done.  The first thing I did was make a symbolic link as that name is a little hard to type, and I didn’t want to remember that path after this day.

mkdir /cdrom
cd /dev
ln -s /devices/iommu@f,e0000000/sbus@f,e0001000/espdma@f,400000/esp@f,800000/sd@2,0:a jr0

this gives me a /dev/jr0 linking to where the Solaris 2.6 install path was.

# mount -oro /dev/jr0 /mnt
mount: /dev/jr0 is not this fstype.

Well that was disappointing.  Could I even read the CD?

# head -1 /dev/jr0
CD-ROM Disc for SunOS Solaris Installation

Ok, so it must be the file-system type.  The ‘bootable’ partition on the CD contains a SYSV filesystem, as it’s a “live CD”..

mount -o ro /dev/dsk/c0t2d0s1 /mnt

# ls /mnt
a dev kernel opt reconfigure usr
bin devices lib platform sbin var
cdrom etc mnt proc tmp

You can even fsck it!

# fsck /dev/dsk/c0t2d0s1
** /dev/dsk/c0t2d0s1 (NO WRITE)
** Last Mounted on /tmp/MntDev.12554
** Phase 1 – Check Blocks and Sizes
** Phase 2 – Check Pathnames
** Phase 3 – Check Connectivity
** Phase 4 – Check Reference Counts
** Phase 5 – Check Cyl groups
2445 files, 19114 used, 4873 free (17 frags, 1214 blocks, 0.0% fragmentation)
#

But the part of the CD-ROM that we want, with all the packages uses a different file-system, and with a bit of hunting I found the right string:

mount -F hsfs -r /dev/jr0 /cdrom

Now we can manually add in the missing packages!

# mount -F hsfs -r /dev/jr0 /cdrom
# ls /cdrom
Copyright Solaris_2.6

We just have to point the pkgadd command to where the CD-ROM is mounted.  In my case I just had to type in:

pkgadd -d /cdrom/Solaris_2.6/Product/

And then I got the “interactive” mode showing off all 471 packages.  Don’t just slam the enter key or you’ll start installing everything.  Hit control-d and then we can manually add them in.

<RETURN> for more choices, <CTRL-D> to stop display:^D

Select package(s) you wish to process (or ‘all’ to process
all packages). (default: all) [?,??,q]:

And in this case, the packages I wanted were:

SUNWarc
SUNWbtool

With those installed, now I can see the object files I wanted:

# find / -name ‘*.o’ -print
/usr/lib/adb/adbsub.o
/usr/ccs/lib/values-Xa.o
/usr/ccs/lib/values-Xc.o
/usr/ccs/lib/values-Xs.o
/usr/ccs/lib/values-Xt.o
/usr/ccs/lib/values-xpg4.o

Wasn’t that great?  Nobody had to re-install, no disk space is wasted, and now if other packages are needed, it’ll be easy to add them.

Did you know that GCC used to support Windows NT ?

I’m not talking about MingGW, Cygwin or anything else like that, but rather when support for Windows NT first appeared, it had to be compiled with Microsoft Visual C++ 1.0 of all things.

It was back in the 2.6 days of GCC, right before the stagnation that led to EGCS.

`i[345]86-*-winnt3.5'
     This version requires a GAS that has not yet been released.  Until
     it is, you can get a prebuilt binary version via anonymous ftp from
     `cs.washington.edu:pub/gnat' or `cs.nyu.edu:pub/gnat'. You must
     also use the Microsoft header files from the Windows NT 3.5 SDK.
     Find these on the CDROM in the `/mstools/h' directory dated
     9/4/94.  You must use a fixed version of Microsoft linker made
     especially for NT 3.5, which is also is available on the NT 3.5
     SDK CDROM.  If you do not have this linker, can you also use the
     linker from Visual C/C++ 1.0 or 2.0.

     Installing GNU CC for NT builds a wrapper linker, called `ld.exe',
     which mimics the behaviour of Unix `ld' in the specification of
     libraries (`-L' and `-l').  `ld.exe' looks for both Unix and
     Microsoft named libraries.  For example, if you specify `-lfoo',
     `ld.exe' will look first for `libfoo.a' and then for `foo.lib'.

     You may install GNU CC for Windows NT in one of two ways,
     depending on whether or not you have a Unix-like shell and various
     Unix-like utilities.

       1. If you do not have a Unix-like shell and few Unix-like
          utilities, you will use a DOS style batch script called
          `configure.bat'.  Invoke it as `configure winnt' from an
          MSDOS console window or from the program manager dialog box.
          `configure.bat' assumes you have already installed and have
          in your path a Unix-like `sed' program which is used to
          create a working `Makefile' from `Makefile.in'.

          `Makefile' uses the Microsoft Nmake program maintenance
          utility and the Visual C/C++ V8.00 compiler to build GNU CC.
          You need only have the utilities `sed' and `touch' to use
          this installation method, which only automatically builds the
          compiler itself.  You must then examine what `fixinc.winnt'
          does, edit the header files by hand and build `libgcc.a'
          manually.

       2. The second type of installation assumes you are running a
          Unix-like shell, have a complete suite of Unix-like utilities
          in your path, and have a previous version of GNU CC already
          installed, either through building it via the above
          installation method or acquiring a pre-built binary.  In this
          case, use the `configure' script in the normal fashion.

Well that is quite the tall order!  I can’t believe I somehow managed to build it back then, and out of curiosity I managed to build it again.  And as you can see you need a ‘beta’ release of the GAS assembler, which is kind of impossible to find now, but it was part of the GNAT project, which used to distribute binary builds of the GCC core back in the day.  Luckily I have a version stuffed away, although it’s from GCC 2.8.1, not as ancient as it would have when GCC 2.6 was a new thing.   But it at lest assembles enough for my simple Hello World experiment.

To build GCC you need a working SED, which surprisingly CL 8.0 from the Win32s SDK, and it runs fine on Windows 7 x64 of all things.  I had to mess with some of the files, and substitute the linker & headder files from Visual C++ 2.0 but much to my amazement not only can I build GCC along with libgcc.a, it also builds incredibly fast.  On my machine I can compile GCC in about 5 seconds.  I remember in 1995 building this on Windows 95 (I was crazy) and it taking HOURS and HOURS.

So one nice thing about these binaries is that you don’t need any external DLL’s  Even the import section of a simple hello world exe is tiny:

GetVersion GetEnvironmentStrings GetCommandLineA ExitProcess RtlUnwind UnhandledExceptionFilter GetModuleFileNameA GetFileType GetStdHandle GetStartupInfoA VirtualFree VirtualAlloc WriteFile WideCharToMultiByte GetLastError FlushFileBuffers SetFilePointer SetStdHandle CloseHandle KERNEL32.dll

Which implies that it only needs KERNEL32 to function.

I don’t know if it’s of any use to anyone else, but HERE is my dump of all the source and tools I used to build GCC.

Saving RISC GCC from the dumpster

Well it seems that the old GNAT stuff from NYU.EDU is no more.

D:\gnat>ftp cs.nyu.edu
Connected to cs.nyu.edu.
220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
220-Local time is now 23:26. Server port: 21.
220-Only anonymous FTP is allowed here
220-IPv6 connections are also welcome on this server.
220 You will be disconnected after 15 minutes of inactivity.
User (cs.nyu.edu:(none)): anonymous
230-Your bandwidth usage is restricted
230 Anonymous user logged in
ftp> cd pub/gnat
250 OK. Current directory is /pub/gnat
ftp> ls
200 PORT command successful
150 Connecting to port 54057
README
c++-interface.ps.gz
papers
private
226 4 matches total
ftp: 46 bytes received in 0.00Seconds 46000.00Kbytes/sec.
ftp>

For those unfamiliar they provided binary builds of GCC for various platforms, including a bunch of RISC machines. It would be a great loss for anyone trying to bootstrap GCC on one of these platforms with missing parts.

Luckily I have saved them, and put them back online!

*Dec Alpha OSF4
*HP HPPA HPUX 10.20
*i386 Solaris 2.6
*SUN Sparc Solaris 2.5.1
*IBM PowerPC AIX 4.1

For anyone interested, this is how I used GNAT to turn Solaris 2.4 into something usable.

Shoebill now has working Ethernet support!

Great news!  The excellent A/UX capable emulator Shoebill, now has working Ethernet support!  The sad news is that it only supports the TUN/TAP interface.  So Windows users are kind of left out in the fun.

Shoebill + Ethernet

Shoebill + Ethernet

Except, I’ve been here before with SIMH ages ago.  So I dusted off my source code, and injected it into Shoebill.  The first issue I had was that SLiRP was rejecting all the inputted frames, because of invalid frame length.  Even more weird is that ARP worked, and I could see the 10.0.2.2 and 10.0.2.3 virtual IP’s but TCP and UDP outbound wouldn’t work at all.

It took me longer than it should have but although this code worked great with GCC 2.7 and 3.0, 4.x breaks it.  And it’s the same reason why Shoebill originally didn’t work on Win32, the blasted packed structures!  So adding the ‘-mno-ms-bitfields’ flag to GCC is all it took, and now I could ping 10.0.2.2 for about 5-7 pings until SLiRP would crash.  I tried all kinds of stuff trying to see if there was an issue with SLiRP, but I should have payed closer attention to the debugger, with all those threads flying around.  It turns out Shoebill was trying to read & write a the same time, which caused SLiRP to crash as it is not re-entrant.  I tried to place mutex’s on every SLiRP call but that ended up having SLiRP not process any packets.  Very strange.  I then reduced it to where I read the frame out of SLiRP and pass it to Shoebill, and where Shoebill write’s a frame out the SLiRP.  And much to my amazement I can run ‘worms’ just fine!

So after a minute of worming and pinging I called it ‘good enough’ and rebuilt a production binary, and packaged up my source code.

For anyone who want’s to play, my Win32 EXE is here, and the source code I am using is here.

Shoebill ported to Windows!

Shoebill!

Shoebill!

Good news, as mentioned here, the Shoebill emulator was recently given some much needed SDL love, and ported to Linux.

Well that’s great and all, but the vast majority of people who run anything these days do it with Windows.  So I decided to try to get it to compile with MinGW to see how far I could get.

And the short version is that I got it working!

The long version is that in the first pass there is some SIGUSR2 stuff that is undefined.  And for a good reason, since it won’t work.  So I just commented them out.  The next minor problem was the lack of bzero.  Honestly I don’t know why bzero is missing from MinGW, but who knows why.

Shoebill also processes some internal macros with a perl script that for some reason was dropping in binary values into the source, making GCC mad.  I just commented out a line that was adding in more comments into the header.  This let me compile with a simple pass.

There was some issues reading the ROM file, since the 68000 is a BIG ENDIAN processor, and the 8086 is LITTLE ENDIAN, Shoebill makes extensive use of hotns and hotnl, ntohl, and ntohll.  These can be found in the winsock library, and even better they dont need any winsock initialization, they work right away.  I just have to make sure I include winsock2.h, and link against the winsock library.

However when trying to boot, the checksum was 0x00000000, not the expected value!   Luckily there was an assert to catch that and crash.  This led me to notice that in Linux files are opened in binary mode by default, while on Windows, they are opened in ASCII mode.  A quick change of all the fopen calls, and I was reading the ROM, but now crashing on the disk.

As it turns out newer versions of GCC go all crazy when it comes to structs, and try to automatically align to boundaries for quick access.  Which sound nice, until you try to read in some binary data, and expect things to be in certain locations and find out that your structure is larger than expected, and data is read in the wrong place.

The solution is to force the compiler to leave it alone with

__attribute__ ((__packed__))

HOWEVER as luck would have it, Microsoft apparently packs structures a different way, and you have to either make a macro to do a bunch of work to force it to make the structure 1:1 of what you expect, or use the CFLAG option of

-mno-ms-bitfields

And now MinGW’s GCC will build something along the lines of what it’d build on Linux.

Putting it all together, I amazingly got this!

Shoebill on Windows

Shoebill on Windows

Phew!  So for those interested, here is the source code drop(Use the updated one here!), and here is the binary.

If you ever wanted to see the “OS X” of the 1980’s, now is your chance!

Public Domain Operating System

So, I came across this project from some random google search on Watcom the other day.  Simply put it is a MS-DOS API that is supported in both a 16bit real mode operating system, and a 32bit operating system.  It is quite sparse but very interesting all the same.  Using the ancient EMX port of GCC you can build 32bit (simple) programs, and run them in the 32bit DOS like Operating System.  What makes this even more interesting is that there is a port to the IBM 370, and 390 based hardware, along with the fictional 380.

Screen Shot 2013-09-16 at 6.40.03 PM

PDOS-16 booting in Qemu 1.6

Screen Shot 2013-09-16 at 6.39.47 PM

PDOS-32 booting in Qemu 1.6

You can download my diskimages, (VMDK & floppy disk) that I’ve used with Qemu to build & boot PDOS both 16bit and 32bit.

The included libc & system libraries are lacking compared to real MS-DOS, but this is public domain code, and with a bit of TLC it could be made into something much more.

AmiDevCpp

Antoni sent me a link to this project, AmiDevCpp. It is a nice little wrapped up IDE for cross compiling applications for the following platforms:

  • AmigaOS (m68k)
  • AmigaOS4 (PPC)
  • MorphOS(PPC)
  • AROS (i386, ppc and x86_64).

Naturally it doesn’t work correctly on Wine.. .Oh well, but for you Windows users out there that haven’t installed Cygwin this is an easy way to cross build stuff for the ancient Amiga platform.

Apparently he was able to rebulid the infamous aclock using this cross compiler…