Read Me
ibcs for Debian
===============
iBCS (Intel Binary Compatibility System) allows an Linux x86 kernel
to emulate at the following Unix systems at the system call level:
xenix, ibcs, isc, sco, solaris, svr4, util, uw7 and wyse.
The documentation is this file.
All documentation is readable online at the home page:
http://ibcs4.sourceforge.net/
Dependencies
------------
- Linux kernel. A given version of iBCS usually only works with
a narrow range of kernel versions.
Building
--------
Packages are available for Debian style distributions
at the home page. If you install using them you can
skip this section.
The build dependencies are:
- The kernel build system, https://www.kernel.org/
1. Examine and modify "CONFIG" if required.
2. Run "make".
3. Run "abi_ldr" to load compiled modules.
4. Run your application.
5. If it does not behave as expected run "en_tr" to enable tracing
via syslogd.
6. After fixing the problem run "rm_tr" to stop the trace.
7. Exit from your application.
8. Run "abi_uld" to unload modules from step "3".
9. It is recommended to run "make clean" after modifying "CONFIG".
Loading
-------
The modules must be loaded and initialised in a special way:
1. First abi_util.ko and abi_lcall.ko must be modprobe'ed.
2. Second, /usr/lib/ibcs/abi_exec must be run.
3. Third, the modules supporting executable formats you want to
use should be modprobe'ed (binfmt_coff.ko, binfmt_xout.ko).
4. Forth, the personalities should be modprobe'ed (abi_sco.ko,
abi_svr4.ko, etc).
The script /etc/init.d/ibcs does this for you. It reads its
parameters from /etc/default/ibcs.
Module parameters
-----------------
Some modules take parameters. /etc/init.d/ibcs reads the settings
for these parameters from /etc/default/ibcs:
abi_util.ko
short_inode_mapping=1 If set to '1', turns on mapping 32bit
inodes into 16 bit ones. If not set
inodes >65535 can't be used.
abi_lcall.ko
ExeFlags=pathname Pathname is the name of a file which provides
some per-executable control of the emulation.
See /etc/default/ibcs for more information.
Amd64vector=nnn Interrupt vector to use on amd64. Ignored on
i386. The default is 127. If you get reboots
try a different value in the ranged 96..127,
129..159.
binfmt_xout.ko
Emulx286=pathname This parameter is required. The pathname to
the xout loader. This is installed by
ibcs-tools to /usr/lib/ibcs/x286emul.
abi_svr4.ko
InodeMap=pathname Supplements short_inode_mapping to provide a
mapping to a fixed inode number for specific
files. See /etc/default/ibcs for more
information.
DeviceMap=pathname Maps Linux device numbers into different
device numbers in the emulation. See
/etc/default/ibcs for more information.
Debugging
---------
iBCS isn't particularly well maintained. It is only used by people
who don't have much choice, and the bits that work tend to be only
the bits they use. This means it is likely something your
application uses may not work. Yes, it is a kernel module, and yes
that means debugging it requires kernel development. But with the
advent of VM's a competent programmer who has a passing familiarity
with C should be able to cope.
Step 1 is using abitrace. It controls the output iBCS trace to
the kernel log. Usage is:
/usr/lib/ibcs/abitrace FLAGS
where FLAGS is a number representing a bit mask of the ABI_TRACE
flags defined in include/util/trace.h. The trace can generate
strace like output, which can be useful in getting a clue as to
what is breaking.
Step 2 is actually debugging. Once you get the setup out of the
way it is pretty easy. You end up with gdb connected to a kvm
VM running the modules you are debugging. You can set break
points, single step through the source and, examine variables.
Set up consists of these steps:
1. Create a disk image file, 10Gb will do:
dd if=/dev/zero bs=1K seek=$((10*1024*1024-1)) count=1 of=vm32.img
This creates a sparse file, meaning after this command is
executed it will appear to be 10Gb in side, but will only
occupy 1 block. Additional blocks will be allocated as
when they written to.
2. Install debian into your image:
sudo kvm -hda vm32.img -cdrom debian-squeeze-di-rc2-i386-netinst.iso -boot d
3. Tailor a few things in the vm image so you can use kvm's
console mode and can copy the disk images easily by replacing
a few lines in config files:
/etc/default/grub:
GRUB_TIMEOUT=1
GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0,9600n8"
GRUB_TERMINAL_INPUT="serial console"
GRUB_TERMINAL_OUTPUT="serial console"
GRUB_SERIAL_COMMAND="serial --unit=0 --speed=9600 --word=8 --parity=no --stop=1"
GRUB_DISABLE_LINUX_RECOVERY="true"
/etc/fstab:
/dev/sda1 / ext3 errors=remount-ro 0 1
/dev/sda5 none swap sw 0 0
Run update-grub when you are done.
4. Ensure you are using the same kernel in the VM and on your
host machine. Install linux-source-2.6.32 and
linux-image-2.6.32-5-i386-dbg (kernel debug symbols) onto
your host machine.
5. Unpack ibcs-source.tar.bz2 somewhere. This will become your
development tree. Ensure ABI_NOOPT=Y in CONFIG, and run make.
This will create the kernel modules.
6. Start your VM in console mode, and setup a GDB connection:
sudo kvm -hda vm32.img -gdb tcp::1234 --nographic
7. Copy the development tree into your VM. Use the abi_ldr
script in the development tree to load the compiled modules.
8. Now you have to tell gdb (which will be running on your host)
where the kernel loaded the modules into memory. This can be
tedious, so I used a shell script on the VM to calculate this
send rsync the information to the host:
~/ibcs-3.8.1/abi_ldr
(
echo set substitute-path /build/buildd-linux-2.6_2.6.32-30-amd64-d4MbNM/linux-2.6-2.6.32/debian/build/source_amd64_none linux
echo set substitute-path /home/rstuart/squeeze/z/bzr/ibcs-source source.vm64
sed -n 's;^binfmt_\([a-z0-9]*\) .* Live \(.*\);add-symbol-file /home/rstuart/squeeze/z/source.vm64/\1/binfmt_\1.ko \2;p' /proc/modules | sort
sed -n 's;^abi_\([a-z0-9]*\) .* Live \(.*\);add-symbol-file /home/rstuart/squeeze/z/source.vm64/\1/abi_\1.ko \2;p' /proc/modules | sort
echo target remote :1234
) >/tmp/ibcs.gdb
rsync /tmp/ibcs.gdb 10.0.2.2::root/home/rstuart/squeeze/z/.
Notice the substitute-path commands. These tell gdb where the
source trees are located, so you can single step through the
source code.
9. Now back on your host command you can start gdb. The first
command is "source ibcs.gdb", so it reads the file created
in step 8.
10. Set a break point. Good newbie starting points are:
coff_load_binary - You will hit this if a coff executable is run
xout_load_binary - You will hit this if a xout executable is run
abi_personality - Its trying to figure out what sort of emulation to use.
lcall7_dispatch - It it decides to do emulation all system calls end up here.
And with you are off on the usual diagnose/change/compile
development cycle. Fix the bug, and repeat steps 6..10 until
it works.
Finally, this little script is useful for getting direct access to
the file system in the VM HDD image file. I named it fsck.sh.
Invoked as "fsck.sh -l image-filename" it will create a loopback
device for your image which you can mount. Invoked as
"fsck.sh image-filename fsck-opts", it checks the partition with
e2fsck.
set -e
loop=
[ ."$1" != ."-l" ] || {
loop="yes"
shift
}
VM="$1"
lodev=$(sudo losetup -f)
unloop() { while ! sudo losetup -d "${lodev}"; do sleep 1 || exit; done; }
trap unloop 0 1 2 15
sudo losetup "${lodev}" "${VM}"
start_end=$(sudo fdisk -lu "${lodev}" | sed -n -e "s;^${lodev}p1[ *]\+\([0-9]\+\) \+\([0-9]\+\).*;\1:\2;p")
units=$(sudo fdisk -lu "${lodev}" | sed -n -e 's;^Units.* = \([0-9]\+\).*;\1;p')
unloop
sudo losetup -o $(dc -e "${start_end%:*} ${units}*p") "${lodev}" "${VM}"
[ -z "$loop" ] || {
trap "" 0 1 2 15
sudo losetup "${lodev}"
exit 0
}
if [ -z "$1" ]
then sudo e2fsck -f "${lodev}"
else sudo e2fsck $@ "${lodev}"
fi
unloop
trap "" 0 1 2 15
--
Russell Stuart
2011-03-08